如何通过通知

时间:2016-12-27 17:22:28

标签: android android-notifications back-stack

我试图提出一个通知,该通知由特殊活动处理,该活动不在正常的应用程序流程中,并试图让后台堆栈处理"正确,"意思是:

  1. 如果在应用程序运行时处理通知,则通知活动应出现在当前堆栈上,从通知返回应该留给我们在应用程序中的位置。请注意,这可能意味着应用程序已打开。
  2. 如果在应用程序未运行时处理通知,则通知活动应出现在应用程序的主(初始)活动中。
  3. 到目前为止,我用来呈现通知的代码是:

    /**
     * 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是一个单一意图,配置为打开通知处理活动。

    我的问题是,如果应用程序当前正在运行并在打开通知时打开,则应用程序将关闭,并且通知将显示在空堆栈上,并且应用程序的后备堆栈将被清除。

    我的理解是,如果内容意图是包含单个意图的待定意图,那么期望的行为应该是自动的,这就是这里的情况。

    我错过了什么?

3 个答案:

答案 0 :(得分:1)

TaskStackBuilder.create 将启动一个新的任务堆栈。

改为设置内容意图:

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

答案 1 :(得分: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();

答案 2 :(得分: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活动实际上是什么。我尝试了一种简单的方法来构建一个HOME意图:

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

但由于某种原因,startActivity引发了异常:

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

即使queryIntentActivities方法证明Activity有适当的Intent