当你通过通知打开一个Activity时,你必须保留用户期望的导航体验。当点击back键时,你应该将用户带到Home 界面,并且你应该显示那个Activity作为一个隔离的任务(task)。为了保留导航体验,你应该在一个新的任务(task)中显示Activity。如何在一个新的任务(task)中启动一个 PendingIntent取决于你要启动的Activity的性质。这里有两个一般的情况:
1. 一般Activity
你打开的Activity是你的应用程序正常工作流程的一部分。在这种情况下,在一个新的任务(task)中启动 PendingIntent,并且给PendingIntent 提供一个回退栈用来复制应用程序的常规的返回操作。
2. 特殊的Activity
如果使用通知进入的话用户仅仅看到进入的这个Activity。有一种场景,就是一个Activity提供那些一个通知很难展示的信息。在这种情况下,在一个新的任务中启动一个PendingIntent。没有必要创建一个回退栈,因为启动的那个Activity并不是应用程序Activity的一部分。点击返回仍然会将用户带到Home 界面。
- 建立一个一般的PendingIntent
建立一个直接打开Activity的PendingIntent,要按照下面的步骤:
1. 在manifest文件中定义你的应用程序的Activity层级
a.为Android4.0.3及更早版本添加支持。为此,通过添加<meta-data>元素作为<activity>的子元素指定你要打开的Activity的父Activity。
对于这个元素,设置 android:name=”android.support.PARENT_ACTIVITY”.设置 android:value=”<parent_activity_name>” ,<parent_activity_name>是<activity>子元素android:name 的值。
b.也要为Android4.1及之后的版本添加支持。为此,为你要打开的Activity的<activity>元素添加android:parentActivityName 属性。
最终的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>
2. 基于要启动的Activity的intent创建一个回退栈
a.创建一个Intent来启动Activity。
b.通过调用TaskStackBuilder.create() 来创建一个栈。
c.通过调用 addParentStack() 将回退栈添加到之前创建的那个栈中。对于任意一个你在manifest中定义的Activity,这个回退栈包含一个 Intent 对象来开始这个Activity。这种方法仍然添加了一个在新任务中打开这个栈的标志标志。
注意:尽管addParentStack() 的参数是一个要开启Activity的引用,但是这个方法并没有添加要打开的Activity的Intent。反而,你要注意下面的这一步。
d.通过调用 addNextIntent() 添加从通知进入的那个Activity的Intent,将这个Intent作为参数传递给addNextIntent()。
e.如果需要的话,通过调用 TaskStackBuilder.editIntentAt() 将参数Intent添加栈中。有些时候当用户利用返回键导航到这个Activity的时候要确保目标Activit显示有意义的数据。
f.通过调用 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的PendingIntent不需要使用回退栈,所以你不需要在manifest文件中定义Activity的层级结构,并且也不需要调用 addParentStack() 来构建一个回退栈。取而代之的是,使用manifest文件建立Activity的任务选项,并且通过调用 getActivity()创建PendingIntent。
1.在你的manifest文件中,为Activity的<activity>元素添加以下属性:
android:name = “activityclass”
Activity的全类名
android:taskAffinity=””
结合你设置在代码中的标志 FLAG_ACTIVITY_NEW_TASK ,这会确保这个Activity不会进入到应用程序默认的任务。一些已经存在的与应用程序默认任务相同的任务不会受影响。
android:excludeFromRecents=”true”
从最近你的任务中排除新的任务,这样一来用户就不会无意中导航到它。
下面的代码片段显示了这个元素:
<activity
android:name=".ResultActivity"
...
android:launchMode="singleTask"
android:taskAffinity=""
android:excludeFromRecents="true">
</activity>
2.构建并显示通知
a.创建一个启动Activity的Intent。
b.通过使用标志FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TASK调用 setFlags() 方法设置Activity在一个新的,空的任务中启动。
c.为Intent设置一些其他的选项。
d.通过调用 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());