2016-12-27 80 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

創建捆綁的隊列,並不斷增加,並從隊列中按照您的要求移除捆紮物體。

/** 
    * 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等是由於我實際上正在爲應用程序開發一個嵌入式組件,所以我實際上並不知道它們的根/家/啓動活動實際上是什麼。我嘗試了蓋房子的意向更簡單的方法:

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

但出於某種原因startActivity是拋出一個異常:

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

即使queryIntentActivities做法表明,沒有爲一個適當的ActivityIntent