天天看點

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的系統。