这两天做了一个Notification 通知消息的东西,需要从通知点击调到指定的Activity,一般来说,这个需求挺简单的,直接在通知中添加,一个Intent 然后使用PendingIntent就可以完成需求。问题出现在了需求是要跳转到正在运行的MainActivity中的Fragment中去。结果发现使用原来的方法getIntent去获取数据就获取不到了。经过一通的搜索Google才找到了解决方案,这会特地记录一下。
正常使用一个Notification 打开一个activity:
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Intent intent = new Intent();
intent.putExtra(MainActivity.FLAG_MAINACTIVITY, MainActivity.PAGEINDEX_2);
builder.setContentText("您有新的任务!");
builder.setContentTitle("这个是标题");
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_launcher));
builder.setDefaults(NotificationCompat.DEFAULT_ALL);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
builder.setContentIntent(pendingIntent);
Notification notification = builder.build();
//notification.flags = Notification.FLAG_NO_CLEAR | Notification.DEFAULT_SOUND;
notificationManager.notify(1, notification);
正常的逻辑在MainActivity中我们可以使用getIntent方法获取到这个通知附带的数据。这里要说明的是这个activity要在没有运行的情况下这样是可以的。当前的
MainActivity就是应用的主界面,所以我一直获取不数据。
在stackoverflow找到了一篇文章,差不多和我的情况一样,参考这里我找到了一些解决的方法。
1.notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); //设置这个参数
2.在MainActivity中重写onNewIntent()方法 。并且设置setIntent().
3. PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); //设置参数
@Override
protected void onNewIntent(Intent intent) {
//super.onNewIntent(intent);
this.setIntent(intent);
LogUtils.e("TAG", "main-onNewIntent");
obtainFragmentIndex = getIntent().getIntExtra(MainActivity.FLAG_MAINACTIVITY, -1);
setRadioChecked(obtainFragmentIndex);
}
上面两个方式基本上就解决的这个问题。这样我们遇到的问题就先解决了,然后来看看原因。在上面搜索的文章中有说到,这个是因为我们给Activity设置了一个
SingleTask的启动模式。这样正在运行的MAinActivity就不会再启动,所以之前一直没有拿到数据。onNewIntent就是用来解决这个问题的,在onNewIntent中调用setIntent从新设置Intent后我们就可以拿到数据了。总的来说,还是自己太菜,四种启动模式没有搞清楚。
在解决了问题之后又查了一些资料对于上述的几个概念做一些解释:
1.FLAG_ACTIVITY_NEW_TASK
在新任务中启动Activity,如果已经为正在启动的Activity运行任务,则改任务会转到前台并恢复期最后状态,同时Activity会在onNewIntent() 中收到新的Intent。这个就会和SingleTask 的启动模式一样的行为。
2.FLAG_ACTIVITY_SINGLE_TOP
如果正在启动的Activity是当前的Activity(位于返回栈的顶部),则现在实例会接受对onNewIntent()的调用,而不是创建Activity的新实例。这个行为和SingleTop 启动模式相同。
3.FLAG_ACTIVITY_CLEAR_TOP
如果正在启动的Activity已在当前的任务中运行,则会销毁当前任务顶部的所有Activity,并通过onNewIntent()将Intent 传给Activity已恢复的实例(现在位于顶部)而不是启动该Activity的新实例。产生这个行为没有对应的启动模式。
FLAG_ACTIVITY_CLEAR_TOP一般和FLAG_ACTIVITY_NEW_TASK结合使用。一起使用时,通过这些标志,可以找到其他任务中现有的Activity,并将其放入可以从中相应的Intent的位置。
这些事从Android开发文档中找到的。开发文档 中详细介绍了四种启动模式的使用,以及这些参数的关联使用方式。这应该是最好的学习文档了。