Android Notification: Intent.FLAG_ACTIVITY_NEW_TAS

2019-02-18 01:36发布

问题:

In the document of the Notification class I see this:

public PendingIntent contentIntent

The intent to execute when the expanded status entry is clicked. If this is an activity, it must include the FLAG_ACTIVITY_NEW_TASK flag, which requires that you take care of task management as described in the Tasks and Back Stack document. In particular, make sure to read the notification section Handling Notifications for the correct ways to launch an application from a notification.

I've read the materials linked from the above, but I still don't get it. Why is the FLAG_ACTIVITY_NEW_TASK flag required when an activity is to be started from clicking a notification? I tried the following code:

NotificationManager manager = (NotificationManager)context.
    getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(
    android.R.drawable.stat_notify_sync, title,
    System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
Intent intent = new Intent(context, NotifiedActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  // IS THIS REALLY REQUIRED??
PendingIntent pt = PendingIntent.getActivity(context, 0, intent, 0);
notification.setLatestEventInfo(context, title, text, pt);
manager.notify(0, notification);

I ran the above code, both with and without the intent.setFlags line, and there seems to be no difference. In fact, many code samples I found simply don't have that line. So why does the document says that the FLAG_ACTIVITY_NEW_TASK flag is a must, and exactly what difference does it make in notification handling?

回答1:

Technically this flag is required. But since it is required, Android is nice and will just set it for you ;-)

The reason it is required is as follows:

The code that processes the Notification and calls startActivity() to actually launch the Intent, isn't running in a "task". It is system code, part of the Notification system. Normally, if you call startActivity() and the flag Intent.FLAG_ACTIVITY_NEW_TASK is not set, Android will try to launch that Activity into the current task (ie: the task containing the Activity that is calling startActivity()). Since, in this case, there is no task, Android must launch the Activity into another task. That's why you need to specify Intent.FLAG_ACTIVITY_NEW_TASK.

In practice, this won't always create a new task, since Android will first try to find an (suitable) existing task to launch the Activity into. If your app is already running, Android will just launch the Activity into that task. (This isn't 100% true, there are other special cases that can change this logic, but I'm not going to address them here).

NOTE: The same situation exists if you call startActivity() from a Service or a BroadcastReceiver. In those cases, the flag Intent.FLAG_ACTIVITY_NEW_TASK must be set, because there is no "current task", so Android must launch the Activity into another task.