天天看点

Notification点击跳转到消息界面返回到主界面Bug解决

需求:

点击消息通知栏(Notification),跳转到APP的消息界面(MsgActivity),在MsgActivity做一系列操作之后,用户点击返回键,返回到MainActivity

实现:

采用PendingIntent.getActivity()方法来设置点击之后需要跳转到的Activity。

结果:

点击Notication------>跳转到MsgActivity-------->在MsgActivity做一些业务处理之后----->startActivity(MsgActivity,MainActivity),并杀死MsgActivity---------->在MainActivity按物理返回键------------>返回到桌面-------------->用安卓自带的最近任务程序里面进入到APP------>发现这个时候居然显示的是MsgActivity

显然,上面结果并不是我们预期的。

于是,采用Stack,将所有的Activity加入到自己定义的栈当中,并在启动MainActivity的时候,从栈中移除掉Stack, 结果还是一样。

解决方案:

采用PendingIntent.getActivities()方法来设置点击事件

PendingIntent android.app. PendingIntent.getActivities( Context context, int requestCode, Intent[] intents, int flags)

从上面的方法中,我们看到,需要传入的是一个Intent[]数组。

然后我们就手动构建一个Intent数组给

intents[0] = Intent.makeRestartActivityTask(new ComponentName(context, com.baimi.dujiangyan.activity.MainActivity.class));
	intents[1] = Intent.makeRestartActivityTask(new ComponentName(context, com.baimi.dujiangyan.activity.MsgActivity.class));
           
看一下API中对于这个方法的解释:

public static PendingIntent getActivities (Context context, int requestCode, Intent[] intents, int flags, Bundle options)

Added in  API level 16

Like 

getActivity(Context, int, Intent, int)

, but allows an array of Intents to be supplied. The last Intent in the array is taken as the primary key for the PendingIntent, like the single Intent given to

getActivity(Context, int, Intent, int)

. Upon sending the resulting PendingIntent, all of the Intents are started in the same way as they would be by passing them to 

startActivities(Intent[])

.

The first intent in the array will be started outside of the context of an existing activity, so you must use the 

Intent.FLAG_ACTIVITY_NEW_TASK

 launch flag in the Intent. (Activities after the first in the array are started in the context of the previous activity in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.)

The last intent in the array represents the key for the PendingIntent. In other words, it is the significant element for matching (as done with the single intent given to 

getActivity(Context, int, Intent, int)

, its content will be the subject of replacement by 

send(Context, int, Intent)

 and 

FLAG_UPDATE_CURRENT

, etc. This is because it is the most specific of the supplied intents, and the UI the user actually sees when the intents are started.

For security reasons, the 

Intent

 objects you supply here should almost always be explicit intents, that is specify an explicit component to be delivered to through 

Intent.setClass

Parameters
context The Context in which this PendingIntent should start the activity.
requestCode Private request code for the sender
intents Array of Intents of the activities to be launched.
flags May be 

FLAG_ONE_SHOT

FLAG_NO_CREATE

FLAG_CANCEL_CURRENT

FLAG_UPDATE_CURRENT

, or any of the flags as supported by 

Intent.fillIn()

 to control which unspecified parts of the intent that can be supplied when the actual send happens.
Returns
  • Returns an existing or new PendingIntent matching the given parameters. May return null only if 

    FLAG_NO_CREATE

     has been supplied.

从上面的意思中可以看出,数组中第一个Intent对象将会被额外的启动一个栈,于是,我就将MainActivity设置为intent[0]对象.

而intent数组中最后一个,将作为PendIntent的关键,也就是点击之后需要跳转的第一个类文件

所以,再调用了PendingIntent.getActivities之后,还需要给第一个Intent[]数组最后的一个Activity(在我这里是MsgActivity)设置一下启动模式,

因为Intent[0] 对象(MainActivity)和MsgActivity不处于同一个栈中,于是我就将MsgActivity设置一个属性:  android:excludeFromRecents="true",将它从最近运行的程序里面不显示。

综上所述,完整的代码如下:

public static void showFication(Context context) {
		NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
		NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
		builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher));
		builder.setSmallIcon(R.drawable.ic_launcher)
				.setContentTitle(title)
				.setContentText(message)
				.setContentIntent(PendingIntent.getActivities(context, requestCode, makeIntentStack(context),PendingIntent.FLAG_UPDATE_CURRENT));
		builder.setAutoCancel(true);
		Notification notification = builder.getNotification();
		notification.icon = R.drawable.ic_launcher;
		notification.defaults = Notification.DEFAULT_ALL;
		nm.notify(ficationId, notification);

	}

	private static Intent[] makeIntentStack(Context context) {
		Intent[] intents = new Intent[2];
			intents[0] = Intent.makeRestartActivityTask(new ComponentName(context, com.baimi.dujiangyan.activity.MainActivity.class));
			intents[1] = Intent.makeRestartActivityTask(new ComponentName(context, com.baimi.dujiangyan.activity.MsgActivity.class));
		return intents;
	}
           
这个时候还需要给Mainfest.xml清单文件中给MsgActivity设置一下属性:
<activity
            android:name="com.baimi.dujiangyan.activity.MsgActivity"
            android:excludeFromRecents="true"
            android:launchMode="singleTask"
            android:taskAffinity="" >
           

MainActivity的启动模式记得是要SingleTop。

在网上也有说可以采用: android:allowTaskReparenting 属性来解决。但是这个我测试过,也无效。可能和机型有关系。

上述的功能以及解决方案全是在小米平板2带上出现的,安卓5.1.1的系统。