Intent – если активность запущена, переведите ее вперед, иначе запустите новую (из уведомления)
У моего приложения есть уведомления, которые, очевидно – без каких-либо флагов, запускают новое действие каждый раз, поэтому я получаю несколько одинаковых действий, выполняющихся поверх друг друга, что просто неправильно.
То, что я хочу сделать, – это привести активность, указанную в ожидающих уведомления уведомлениях, на фронт, если она уже запущена, иначе запустите ее.
До сих пор намерение / ожидающее намерения для этого уведомления у меня есть
private static PendingIntent prepareIntent(Context context) { Intent intent = new Intent(context, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); }
и это странно, иногда это работает, иногда это не так … Я чувствую, что я уже пробовал каждую комбинацию флагов.
Вы можете использовать это:
который будет работать подобно "singleInstance"
но у него не будет такой странной анимации.
Я думаю, что лучший способ сделать это и простым способом – начать работу нормально, но установить эту активность в манифесте с singleInstance
свойства singleInstance
. При этом вы практически подходите к обоим проблемам, которые у вас есть сейчас, постоянно перенося деятельность на фронт и позволяя ОС автоматически создавать новую, если никакой активности не существует или не вывести на передний план текущую деятельность (благодаря свойство singleInstance
).
Таким образом, активность объявляется как один экземпляр:
Кроме того, чтобы избежать прерывистой анимации при запуске через singleInstance, вы можете использовать вместо этого «singleTask», оба очень похожи, но разница здесь объясняется документацией Google:
singleInstance – это то же самое, что и «singleTask», за исключением того, что система не запускает никаких других действий в задачу, содержащую экземпляр. Деятельность всегда является единственным и единственным членом ее задачи.
Надеюсь это поможет.
С уважением!
Я думаю, что вам нужно в singleTop
Activity
, а не в singleTask
или singleInstance
.
То, что говорит документация , отлично соответствует вашим потребностям:
[…] может быть создан новый экземпляр действия «
singleTop
» для обработки нового намерения. Однако, если целевая задача уже имеет существующий экземпляр активности вверху своего стека, этот экземпляр получит новое намерение (вonNewIntent()
); новый экземпляр не создается. В других случаях – например, если существующий экземпляр действия «singleTop
» находится в целевой задаче, но не в верхней части стека, или если он находится в верхней части стека, но не в целевой задаче – новый экземпляр будет создан и помещен в стек.
Вдобавок к этому (каламбур не предназначен), у меня была такая же потребность, как и вы. Я тестировал все флаги launchMode
чтобы выяснить, как они на самом деле ведут себя на практике, и в результате singleTop
на самом деле является лучшим для этого: ни одна странная анимация, приложение отображается один раз в последнем списке приложений (в отличие от singleInstance
который отображает его дважды из-за того, это не позволяет какой-либо другой Activity
быть частью ее задачи), и надлежащее поведение, независимо от того, какая целевая Activity
уже существует или нет.
Поскольку вы говорите, что хотите начать свою деятельность, если она еще не началась, возможно, вы не возражаете ее перезапустить. Я тестировал массу предложений и комбинаций флагов для намерения, это всегда приведет к активности, которая вам нужна на фронт, хотя она не будет поддерживать какое-либо состояние, ранее связанное с ней.
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
Только API11 +.
Я знаю, что он старый, но ничего из вышеприведенного не подходит для моего приложения.
Без изменения манифестов и другой конфигурации, вот код, чтобы вернуть приложение обратно – или открыть его, когда он закрыт
Intent notificationIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()); notificationIntent.setPackage(null); // The golden row !!! notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Я пробовал это, и он работал, даже несмотря на то, что IDE жаловался на код
Intent notificationIntent = new Intent(THIS_CONTEXT, MainActivity.class); notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); PendingIntent intent = PendingIntent.getActivity(THIS_CONTEXT, 0, notificationIntent, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(THIS_CONTEXT) .setSmallIcon(R.drawable.cast_ic_notification_0) .setContentTitle("Title") .setContentText("Content") .setContentIntent(intent) .setPriority(PRIORITY_HIGH) //private static final PRIORITY_HIGH = 5; .setAutoCancel(true) /*.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS)*/; NotificationManager mNotificationManager = (NotificationManager) THIS_CONTEXT.getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(0, mBuilder.build());