1. 程式人生 > >Notification點選跳轉到訊息介面返回到主介面Bug解決

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中對於這個方法的解釋:

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

Like , 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. Upon sending the resulting PendingIntent, all of the Intents are started in the same way as they would be by passing them to .

The first intent in the array will be started outside of the context of an existing activity, so you must use the  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 , its content will be the subject of replacement by  and , 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  objects you supply here should almost always be explicit intents, that is specify an explicit component to be delivered to through 

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 , , , , or any of the flags as supported by  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  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的系統。