2016-12-27 11 views
3

Я пытаюсь представить уведомление, которое обрабатывается специальным действием, которое не входит в обычный поток приложений, и пытается получить обратную обработку стека «правильно», что означает:Как сохранить стек с уведомлением

  1. Если уведомление обрабатывается во время работы приложения, в текущем стеке должно появиться уведомление об активности уведомления, которое должно быть отправлено из уведомления, если мы будем в приложении. Обратите внимание, что это может означать, что приложение открыто.
  2. Если уведомление обрабатывается, когда приложение не запущено, активность уведомления должна появляться в основном (первоначальном) действии приложения.

До сих пор код, я использую, чтобы представить уведомление является:

/** 
* Show (or update) a notification for the current message set. 
* 
* @param showNotification true to use a high priority notification which will be immediately 
*       displayed (as opposed to just added to the status bar) 
*/ 
private void createOrUpdateNotification(boolean showNotification) { 
    Message oldest = messages.get(0); 
    Message newest = messages.get(messages.size() - 1); 

    // Create the notification 
    NotificationCompat.Builder builder = new NotificationCompat.Builder(context) 
      // Set notification data and appearance 
      .setContentTitle(title) 
      .setContentText(newest.message) 
      .setSmallIcon(smallIcon) 
      .setWhen(newest.when) 
      .setColor(ContextCompat.getColor(context, R.color.primary_color)) 

      // Set notification options 
      .setAutoCancel(true) 
      .setCategory(NotificationCompat.CATEGORY_MESSAGE) 
      .setPriority(showNotification ? NotificationCompat.PRIORITY_HIGH : NotificationCompat.PRIORITY_LOW) 
      .setDefaults(NotificationCompat.DEFAULT_VIBRATE) 
      .setOnlyAlertOnce(!showNotification); 

    // Set up the action if the first (oldest) message has an intent builder 
    if(oldest.intent != null) { 
     TaskStackBuilder stackBuilder = TaskStackBuilder.create(context.getApplicationContext()); 
     stackBuilder.addNextIntent(oldest.intent); 
     builder.setContentIntent(stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)); 
    } 

    NotificationManagerCompat.from(context).notify(notificationId, builder.build()); 

    Log.i("notification created"); 
} 

Для осветления, Message.intent является единственным намерением, сконфигурированный, чтобы открыть обработку уведомлений деятельности.

Моя проблема заключается в том, что если приложение в настоящее время запущено и открыто при открытии уведомления, приложение закрывается, и уведомление, представленное в пустом стеке, и обратном стеке приложения очищается.

Мое понимание заключается в том, что желаемое поведение должно быть автоматическим, если намерение содержания является ожидающим намерением, содержащим одно намерение, что здесь и есть.

Что мне не хватает?

+0

Правильно ли я понял ваш вопрос? Вы хотите показать уведомление и остановить поток, который выдал уведомление, пока он отображается? Это то, что вы хотите? – Distjubo

+0

№ Уведомление генерируется службой. Действие содержимого открывает активность, которая не соответствует нормальному потоку приложения. Когда эта активность отклоняется, я хочу вернуться к активности приложения, которая была прервана. –

ответ

1

TaskStackBuilder.create запустит новый стек задач.

Установите намерение контента, как это вместо:

builder.setContentIntent(
    PendingIntent.getActivity(
    context, 
    0, 
    oldest.intent, 
    PendingIntent.FLAG_UPDATE_CURRENT 
)); 
+0

Спасибо, это очень близко! Единственное, чего не хватает на этом этапе, это то, что, если я вернусь полностью к экрану запуска (из моего приложения) до того, как уведомление будет сгенерировано, приложение не будет запущено вообще, просто уведомление. –

+0

Вы можете переопределить onBackPressed() для активности уведомления и вызвать isTaskRoot(). Если активность уведомления является корнем задачи, вы можете запустить основное мероприятие. – Luis

+0

Вот сложная часть, это все из SDK (у меня нет хост-приложения). Есть ли удобный способ запуска активности по умолчанию для приложения? –

0

Создание очереди Bundle и сохранить добавление и удаление Bundle объектов из очереди в соответствии с вашими требованиями.

/** 
    * Queue that holds notifications messages 
    */ 
    private Queue<Bundle> mNotificationQueue = new LinkedList<Bundle>(); 

/** 
* Method returning the singleton queue maintained in a static class 
*/ 
public Queue<Bundle> getNotificationQueue() { 
     return mNotificationQueue; 
    } 

Теперь, когда уведомление получено добавить уведомительное сообщение в очередь

// Fetching the message from intent and adding in bundle to add in the queue 

Bundle notificationMsgBundle = intent.getExtras(); 

notificationMsgBundle.getString(MyConstants.KEY_CHANNEL) + " :: " + notificationMsgBundle.getString(MyConstants.KEY_DATA)); 

DataManager.getInstance(). GetmNotificationQueue(). Добавить (notificationMsgBundle)

Теперь эта статическая очередь поддерживается в течение всего приложения, и вы можете удалить или добавить сообщения из очереди

// removing the node message in the queue as per requirement 
DataManager.getInstance().getmNotificationQueue().remove(); 
0

Чтобы развернуть немного на ответе @ leco, мое окончательное решение состояло из двух частей.

Первый строит Notification, как он рекомендовал, используя PendingIntent непосредственно вместо того, чтобы пытаться использовать TaskStackBuilder:

builder.setContentIntent(
    PendingIntent.getActivity(
    context, 
    0, 
    oldest.intent, 
    PendingIntent.FLAG_UPDATE_CURRENT 
)); 

Это заставило меня правильное поведение, если заявка была запущена, но в настоящее время не открыт (то есть., Вплоть до потребителя нанести ответный удар всему пути из приложения)

Чтобы получить «правильное» поведение в тот момент, я изменил мою Notification обработки активности переопределив finish():

public void finish() { 
    if(isTaskRoot()) { 
     // If we're the task root, probably because we were launched from a notification with the 
     // application closed, we should just open the default activity 
     try { 
      String homeClassName = getPackageManager().queryIntentActivities(
        new Intent(Intent.ACTION_MAIN).setPackage(getApplicationContext().getPackageName()), 
        0 
      ).get(0).activityInfo.name; 

      Class homeClass = Class.forName(homeClassName); 

      getApplicationContext().startActivity(new Intent(getApplicationContext(), homeClass).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); 
     } 
     catch(Exception exception) { 
      Log.w(String.format("Can't find the MAIN activity for package %s", getApplicationContext().getPackageName())); 
     } 
    } 
    super.finish(); 
} 

В резких колебаниях с queryIntentActivities и т. Д. Объясняются тем фактом, что я фактически разрабатываю компонент для добавления приложений, поэтому я фактически не знаю, что на самом деле означает их деятельность root/home/launch. Я попытался более простой подход просто построить дом намерение:

startActivity(new Intent(Intent.ACTION_MAIN).setPackage(getApplicationContext().getPackageName()) 

, но по какой-то причине startActivity бросает исключение:

android.content.ActivityNotFoundException: No Activity found to handle Intent 

даже несмотря на то, queryIntentActivities подход показывает, что имеется соответствующий Activity для Intent.