diff --git a/src/android/app/src/main/java/org/citra/citra_android/CitraApplication.java b/src/android/app/src/main/java/org/citra/citra_android/CitraApplication.java index 9318ff4b0..29cffebc5 100644 --- a/src/android/app/src/main/java/org/citra/citra_android/CitraApplication.java +++ b/src/android/app/src/main/java/org/citra/citra_android/CitraApplication.java @@ -5,7 +5,10 @@ package org.citra.citra_android; import android.app.Application; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.content.Context; +import android.os.Build; import org.citra.citra_android.model.GameDatabase; import org.citra.citra_android.services.DirectoryInitializationService; @@ -15,13 +18,32 @@ public class CitraApplication extends Application { public static GameDatabase databaseHelper; private static CitraApplication application; + private void createNotificationChannel() { + // Create the NotificationChannel, but only on API 26+ because + // the NotificationChannel class is new and not in the support library + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + CharSequence name = getString(R.string.app_notification_channel_name); + String description = getString(R.string.app_notification_channel_description); + int importance = NotificationManager.IMPORTANCE_DEFAULT; + NotificationChannel channel = new NotificationChannel(getString(R.string.app_notification_channel_id), name, importance); + channel.setDescription(description); + // Register the channel with the system; you can't change the importance + // or other notification behaviors after this + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + } + } + @Override public void onCreate() { super.onCreate(); application = this; - if (PermissionsHandler.hasWriteAccess(getApplicationContext())) + if (PermissionsHandler.hasWriteAccess(getApplicationContext())) { DirectoryInitializationService.startService(getApplicationContext()); + } + + createNotificationChannel(); databaseHelper = new GameDatabase(this); } diff --git a/src/android/app/src/main/java/org/citra/citra_android/activities/EmulationActivity.java b/src/android/app/src/main/java/org/citra/citra_android/activities/EmulationActivity.java index db20ec676..f9f90a03a 100644 --- a/src/android/app/src/main/java/org/citra/citra_android/activities/EmulationActivity.java +++ b/src/android/app/src/main/java/org/citra/citra_android/activities/EmulationActivity.java @@ -12,6 +12,8 @@ import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; import android.support.v7.app.AppCompatActivity; import android.util.SparseIntArray; import android.view.InputDevice; @@ -63,6 +65,8 @@ public final class EmulationActivity extends AppCompatActivity { public static final int MENU_ACTION_SCREEN_LAYOUT_SIDEBYSIDE = 8; public static final int MENU_ACTION_SWAP_SCREENS = 9; public static final int MENU_ACTION_RESET_OVERLAY = 10; + + private static final int EMULATION_RUNNING_NOTIFICATION = 0x1000; private static final String BACKSTACK_NAME_MENU = "menu"; private static final String BACKSTACK_NAME_SUBMENU = "submenu"; private static SparseIntArray buttonsActionsMap = new SparseIntArray(); @@ -132,6 +136,27 @@ public final class EmulationActivity extends AppCompatActivity { options.toBundle()); } + private void showRunningNotification() { + NotificationCompat.Builder builder = new NotificationCompat.Builder(this, getString(R.string.app_notification_channel_id)) + .setSmallIcon(R.drawable.ic_stat_notification_logo) + .setContentTitle(getString(R.string.app_name)) + .setContentText(getString(R.string.app_notification_running)) + .setPriority(NotificationCompat.PRIORITY_MIN) + .setOngoing(true); + + NotificationManagerCompat.from(this).notify(EMULATION_RUNNING_NOTIFICATION, builder.build()); + } + + public static void tryDismissRunningNotification(Activity activity) { + NotificationManagerCompat.from(activity).cancel(EMULATION_RUNNING_NOTIFICATION); + } + + @Override + protected void onDestroy() { + tryDismissRunningNotification(this); + super.onDestroy(); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -221,6 +246,8 @@ public final class EmulationActivity extends AppCompatActivity { } mPreferences = PreferenceManager.getDefaultSharedPreferences(this); + + showRunningNotification(); } @Override @@ -308,6 +335,8 @@ public final class EmulationActivity extends AppCompatActivity { } public void exitWithAnimation() { + tryDismissRunningNotification(this); + runOnUiThread(() -> { Picasso.get() diff --git a/src/android/app/src/main/java/org/citra/citra_android/ui/main/MainActivity.java b/src/android/app/src/main/java/org/citra/citra_android/ui/main/MainActivity.java index b66d35fd4..176b825b7 100644 --- a/src/android/app/src/main/java/org/citra/citra_android/ui/main/MainActivity.java +++ b/src/android/app/src/main/java/org/citra/citra_android/ui/main/MainActivity.java @@ -6,7 +6,6 @@ import android.database.Cursor; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; -import android.support.v4.app.Fragment; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Menu; @@ -15,6 +14,7 @@ import android.view.MenuItem; import android.widget.Toast; import org.citra.citra_android.R; +import org.citra.citra_android.activities.EmulationActivity; import org.citra.citra_android.model.GameProvider; import org.citra.citra_android.services.DirectoryInitializationService; import org.citra.citra_android.ui.platform.PlatformGamesFragment; @@ -60,6 +60,9 @@ public final class MainActivity extends AppCompatActivity implements MainView { } else { mPlatformGamesFragment = (PlatformGamesFragment) getSupportFragmentManager().getFragment(savedInstanceState, "mPlatformGamesFragment"); } + + // Dismiss previous notifications (should not happen unless a crash occurred) + EmulationActivity.tryDismissRunningNotification(this); } @Override @@ -191,4 +194,10 @@ public final class MainActivity extends AppCompatActivity implements MainView { private PlatformGamesView getPlatformGamesView() { return (PlatformGamesView) getSupportFragmentManager().findFragmentById(mFrameLayoutId); } + + @Override + protected void onDestroy() { + EmulationActivity.tryDismissRunningNotification(this); + super.onDestroy(); + } } diff --git a/src/android/app/src/main/res/drawable-hdpi/ic_stat_notification_logo.png b/src/android/app/src/main/res/drawable-hdpi/ic_stat_notification_logo.png new file mode 100644 index 000000000..2282f1a3b Binary files /dev/null and b/src/android/app/src/main/res/drawable-hdpi/ic_stat_notification_logo.png differ diff --git a/src/android/app/src/main/res/drawable-xhdpi/ic_stat_notification_logo.png b/src/android/app/src/main/res/drawable-xhdpi/ic_stat_notification_logo.png new file mode 100644 index 000000000..5e2787ba3 Binary files /dev/null and b/src/android/app/src/main/res/drawable-xhdpi/ic_stat_notification_logo.png differ diff --git a/src/android/app/src/main/res/drawable-xxhdpi/ic_stat_notification_logo.png b/src/android/app/src/main/res/drawable-xxhdpi/ic_stat_notification_logo.png new file mode 100644 index 000000000..06cef9de3 Binary files /dev/null and b/src/android/app/src/main/res/drawable-xxhdpi/ic_stat_notification_logo.png differ diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index f6a0974df..05224978e 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -4,6 +4,10 @@ Citra This software will run games for the Nintendo 3DS handheld game console. No game titles are included.\n\nBefore you run, please place your rightfully owned 3DS game files onto your device storage. + Citra + Citra + Citra 3DS emulator notifications + Citra is running Circle Pad