关于设置IntentFlag的一些总结

摘要

目前:新闻里的正文页Activity为NewspageActivity,其余专题、视频、图集等页面都使用SingleFragmentActivity。

在做消息推送通过Notification点击跳转时,代码如下:

1
2
Intent intent1 = new Intent(context, OneActivity.class); intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);

必须使用Intent.FLAG_ACTIVITY_NEW_TASK的原因是:在app不存在任何栈的时候,需要新建一个栈。

现象一

但是官方说明里关于Intent.FLAG_ACTIVITY_NEW_TASK的描述有这么一段话:

初步理解是当使用Intent.FLAG_ACTIVITY_NEW_TASK,如果栈里已经存在要启动的Activity,那么Activity不会被创建。

测试验证确实是,当两条Notification都是跳转至NewspageActivity,在Launcher页面点击第一条Notification可正确跳转,但点击第二条Notification则没有反应。

现象二

基于现象一,再次仔细测试,发现并不是栈里存在要启动的AActivity,AActivity不会创建。看以下测试结果:

发现是通过AActivity创建的栈,再次点击Notification跳转至AActivity无效果,而在栈内的其他BActivity、CActivity是可以再次跳转打开的。

自以为的解决方案一

基于以上分析,如果想解决问题,我们只要封装一个统一的PushActivity分发数据,随后finish掉自己。

模拟代码

Demo地址

写了个demo测试,demo中包含3个Activity,MainActivity,OneActivity,TwoActivity.

MainActivity:主要作用是创建Notification。Notification的点击跳转统一跳转至OneActivity。

OneActivity:onCreate()中通过以下代码

1
2
Intent intent = new Intent(OneActivity.this, TwoActivity.class);
OneActivity.this.startActivity(intent);

跳转至TwoActivity,并finish()自己。

TwoActivity:打印生命周期的调用。并获取intent的flags。代码如下:

1
2
3
4
5
private void getFlag() {
Intent intent = getIntent();
int flags = intent.getFlags();
System.out.println("xc " + "TwoActivity.getFlag flags:" + flags);
}

AndroidManifest.xml:都是默认设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".OneActivity" />
<activity android:name=".TwoActivity" />
<receiver android:name=".MainActivity$PushReceiver">
<intent-filter>
<action android:name="com.netease.newsreader.activity.push.receiver" />
</intent-filter>
</receiver>

结局

通过OneActivity做中转,每次点击Notification统一跳转至OneActivity,再由OneActivity去分发数据跳转至对应页面,分发数据完成后调用OneActivity.finish()方法。

这样每次点击Notification,栈里都不会存在OneActivity,那么应该都可以跳转了。但事实并非如此。

当收到两条Notification,在Launcher页面点击第一条Notification可正确跳转至OneActivity,但点击第二条Notification则没有反应。

无意尝试的解决方案二

解决方案一失败后,查看Intent的Flag其实并没有什么好招。

于是目光转向OneActivity的launchmode属性。

在不指定activity的launchmode属性,默认为standard。

突发奇想把它改成singleTask,发现问题完美解决。

1
2
<activity android:name=".OneActivity"
android:launchMode="singleTask"/>

点击第一条Notification生命周期大致为:

OneActivity#onCreate() taskid:2581;com.example.xiongcen.myapplication.OneActivity@ec892a6

->OneActivity#getFlag() flags:268435456

->TwoActivity#onCreate() taskid:2581;com.example.xiongcen.myapplication.TwoActivity@dca4873

->TwoActivity#getFlag() flags:0

->OneActivity#onDestroy()

点击第二条Notification生命周期大致为:

TwoActivity#onPause() com.example.xiongcen.myapplication.TwoActivity@dca4873

->OneActivity#onCreate() taskid:2581;com.example.xiongcen.myapplication.OneActivity@ca3d2b6

->OneActivity.getFlag flags:268435456

->TwoActivity#onCreate() taskid:2581;com.example.xiongcen.myapplication.TwoActivity@39061f2

->TwoActivity#getFlag() flags:0

->OneActivity#onDestroy()

->TwoActivity#onStop() com.example.xiongcen.myapplication.TwoActivity@dca4873


在OneActivity#onCreate()中通过getFlags()方法获取intent的flag,十进制为268435456,转成十六进制为0x10000000,即为Intent#FLAG_ACTIVITY_NEW_TASK。

在TwoActivity#onCreate()中通过getFlags()方法获取intent的flag,十进制数为0,这是因为我们在OneActivity启动TwoActivity时并没有添加任何flag。

尝试其他方案

经过方案二,尝试将OneActivity的launchmode改成singleInstance。

1
2
<activity android:name=".OneActivity"
android:launchMode="singleInstance"/>

singleInstance比较典型的就是,启动launchmode为singleInstance的activity,栈id和其他默认栈id是不同的,是一个单独的栈,并且这个栈内只有该activity。

但设置android:taskAffinity属性后,android:taskAffinity指定名字的栈存在的话,OneActivity就不会新建,而是走onNewIntent()->onRestart()->onStart()->onResume()。

尝试结果发现,点击第一条Notification:

OneActivity#onCreate() taskid:2704;com.example.xiongcen.myapplication.OneActivity@ec892a6

->OneActivity#getFlag() flags:268435456

->TwoActivity#onCreate() taskid:2705;com.example.xiongcen.myapplication.TwoActivity@dca4873

->TwoActivity#getFlag() flags:268435456

->OneActivity#onDestroy()

点击第二条Notification:

TwoActivity#onPause() com.example.xiongcen.myapplication.TwoActivity@dca4873

->OneActivity#onCreate() taskid:2706;com.example.xiongcen.myapplication.OneActivity@ca3d2b6

->OneActivity#getFlag() flags:268435456

->TwoActivity#onResume() 2705;com.example.xiongcen.myapplication.TwoActivity@dca4873

->TwoActivity#getFlag() flags:268435456

->OneActivity#onDestroy()


在OneActivity#onCreate()中通过getFlags()方法获取intent的flag,十进制为268435456,转成十六进制为0x10000000,即为Intent#FLAG_ACTIVITY_NEW_TASK。

在TwoActivity#onCreate()中通过getFlags()方法获取intent的flag,十进制为268435456,转成十六进制为0x10000000,即为Intent#FLAG_ACTIVITY_NEW_TASK。

通过生命周期的打印可以看出TwoActivity并没有创建多个。

分析原因是:

猜测和打开TwoActivity的flags有关。

可以看到,在launchmode为singleTask的情况下,TwoActivity的flags=0,应该打开方式默认是standard,所以每次TwoActivity都会创建新的;在launchmode为singleInstance的情况下,TwoActivity的flags=268435456,转成十六进制为0x10000000,Intent#FLAG_ACTIVITY_NEW_TASK,根据文档说明知道设置FLAG_ACTIVITY_NEW_TASK,只要后续入栈的Activity和因为设置NEW_TASK标识而新起的栈建立的第一个Activity一致,就会导致相同Activity无法入栈,所以再次打开TwoActivity会无反应。

IntentFlag和Launchmode的关系

应该是IntentFlag设置的优先生效,但在不冲突的情况下也有可能和Launchmode搭配使用,例如测试Demo中OneActivity设置launchmode为singleTask,启动OneActivity设置IntentFlag为FLAG_ACTIVITY_NEW_TASK。