启动 Activity 时保留导航
从通知中启动 Activity
时,您必须保留用户的预期导航体验。 点击“返回”应该使用户将应用的正常工作流回退到主屏幕,而点击“最新动态”则应将Activity
显示为单独的任务。 要保留导航体验,您应该在全新任务中启动 Activity
。如何设置 PendingIntent
以获得全新任务取决于正在启动的Activity
的性质。一般有两种情况:
-
常规 Activity
-
您要启动的
Activity
是应用的正常工作流的一部分。在这种情况下,请设置PendingIntent
以启动全新任务并为PendingIntent
提供返回栈,这将重现应用的正常“返回”行为。Gmail 应用中的通知演示了这一点。点击一封电子邮件消息的通知时,您将看到消息具体内容。 触摸返回将使您从 Gmail 回退到主屏幕,就好像您是从主屏幕(而不是通知)进入 Gmail 一样。
无论您触摸通知时处于哪个应用,都会发生这种情况。 例如,如果您在 Gmail 中撰写消息时点击了一封电子邮件的通知,则会立即转到该电子邮件。 触摸“返回”会依次转到收件箱和主屏幕,而不是转到您在撰写的邮件。
特殊 Activity
-
仅当从通知中启动时,用户才会看到此
Activity
。 从某种意义上说,Activity
是通过提供很难显示在通知本身中的信息来扩展通知。对于这种情况,请将PendingIntent
设置为在全新任务中启动。但是,由于启动的Activity
不是应用 Activity 流程的一部分,因此无需创建返回栈。点击“返回”仍会将用户带到主屏幕。
设置常规 Activity PendingIntent
要设置可启动直接进入 Activity
的 PendingIntent
,请执行以下步骤:
- 在清单文件中定义应用的
Activity
层次结构。- 添加对 Android 4.0.3 及更低版本的支持。为此,请通过添加
<meta-data>
元素作为<activity>
的子项来指定正在启动的Activity
的父项。对于此元素,请设置
android:name="android.support.PARENT_ACTIVITY"
。 设置android:value="<parent_activity_name>"
,其中,<parent_activity_name>
是父<activity>
元素的android:name
值。请参阅下面的 XML 示例。 - 同样添加对 Android 4.1 及更高版本的支持。为此,请将
android:parentActivityName
属性添加到正在启动的Activity
的<activity>
元素中。
最终的 XML 应如下所示:
<activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ResultActivity" android:parentActivityName=".MainActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"/> </activity>
- 添加对 Android 4.0.3 及更低版本的支持。为此,请通过添加
- 根据可启动
Activity
的Intent
创建返回栈:- 创建
Intent
以启动Activity
。 - 通过调用
TaskStackBuilder.create()
创建堆栈生成器。 - 通过调用
addParentStack()
将返回栈添加到堆栈生成器。 对于在清单文件中所定义层次结构内的每个Activity
,返回栈均包含可启动Activity
的Intent
对象。此方法还会添加一些可在全新任务中启动堆栈的标志。注:尽管
addParentStack()
的参数是对已启动Activity
的引用,但是方法调用不会添加可启动Activity
的Intent
,而是留待下一步进行处理。 - 通过调用
addNextIntent()
,添加可从通知中启动Activity
的Intent
。 将在第一步中创建的Intent
作为addNextIntent()
的参数传递。 - 如需,请通过调用
TaskStackBuilder.editIntentAt()
向堆栈中的Intent
对象添加参数。有时,需要确保目标Activity
在用户使用“返回”导航回它时会显示有意义的数据。 - 通过调用
getPendingIntent()
获得此返回栈的PendingIntent
。 然后,您可以使用此PendingIntent
作为setContentIntent()
的参数。
- 创建
以下代码段演示了该流程:
... Intent resultIntent = new Intent(this, ResultActivity.class); TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); // Adds the back stack stackBuilder.addParentStack(ResultActivity.class); // Adds the Intent to the top of the stack stackBuilder.addNextIntent(resultIntent); // Gets a PendingIntent containing the entire back stack PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); ... NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setContentIntent(resultPendingIntent); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(id, builder.build());
设置特殊 Activity PendingIntent
下文介绍如何设置特殊 Activity PendingIntent
。
特殊 Activity
无需返回栈,因此您不必在清单文件中定义其 Activity
层次结构,也不必调用 addParentStack()
来构建返回栈。取而代之的是,您可使用清单文件设置 Activity
任务选项,并通过调用 getActivity()
创建 PendingIntent
:
- 在清单文件中,将以下属性添加到
Activity
的<activity>
元素- Activity 的完全限定类名。
-
与您在代码中设置的
FLAG_ACTIVITY_NEW_TASK
标志相结合,这可确保此Activity
不会进入应用的默认任务。任何具有应用默认关联的现有任务均不受影响。 - 将新任务从“最新动态”中排除,这样用户就不会在无意中导航回它。
android:name="activityclass"
android:taskAffinity=""
android:excludeFromRecents="true"
以下代码段显示了该元素:
<activity android:name=".ResultActivity" ... android:launchMode="singleTask" android:taskAffinity="" android:excludeFromRecents="true"> </activity> ...
- 构建并发出通知:
- 创建可启动
Activity
的Intent
。 - 通过使用
FLAG_ACTIVITY_NEW_TASK
和FLAG_ACTIVITY_CLEAR_TASK
标志调用setFlags()
,将Activity
设置为在新的空任务中启动。 - 为
Intent
设置所需的任何其他选项。 - 通过调用
getActivity()
从Intent
中创建PendingIntent
。 然后,您可以使用此PendingIntent
作为setContentIntent()
的参数。
以下代码段演示了该流程:
// Instantiate a Builder object. NotificationCompat.Builder builder = new NotificationCompat.Builder(this); // Creates an Intent for the Activity Intent notifyIntent = new Intent(this, ResultActivity.class); // Sets the Activity to start in a new, empty task notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); // Creates the PendingIntent PendingIntent notifyPendingIntent = PendingIntent.getActivity( this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT ); // Puts the PendingIntent into the notification builder builder.setContentIntent(notifyPendingIntent); // Notifications are issued by sending them to the // NotificationManager system service. NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // Builds an anonymous Notification object from the builder, and // passes it to the NotificationManager mNotificationManager.notify(id, builder.build());
- 创建可启动