[背景]
当一个业务流程涉及到多个task之间的交互,如一个Task_A中的Activity_1 startActivityForResult() 了一个Activity_2, Activity_2启动另一个Task_B并且期望利用Task_B运行的结果setResult()返回给Activity_1。
TaskRecord如下图所示:
[问题]
Task_B取得result之后,需要
把Task_A带到前台(active)
,这样Activity_1才能响应(onActivityResult)到Activity_2返回(setResult)的结果。
现在的问题就在于,Task_B并不一定能够退出(Activity_3其可能其他程序,如browser等),从而把Task_A带到前台;又或者Task_A和Task_B中又夹杂了其他的Task(你知道,长按home键你可以做得出来),以至于调用Task_B.moveTaskToBack()也不能解决问题。
[解决方案]
如果
你的平台是面向Android3.0(API level 11),那么恭喜你,一个函数就可以搞定:
moveTaskToFront
http://developer.android.com/reference/android/app/ActivityManager.html#moveTaskToFront(int, int)
如果你和我一样苦逼的在用2.2的平台,那么就要稍微麻烦点了,基本上是用
taskAffinity
+FLAG_ACTIVITY_NEW_TASK +
FLAG_ACTIVITY_SINGLE_TOP。
先来看一下sdk怎么说的:
1. taskAffinity
:
SDK说,如果用带FLAG_ACTIVITY_NEW_TASK标志来启动一个activity,并且这个activity与当前运行的另一个task(A)的affinity名字相同,那么就这个activity就会在那个task(A)里启动。
Ok,到这还不行,人家没说会把Task_A带到前台,接着看另一个Flag
2. FLAG_ACTIVITY_NEW_TASK
好了,重点来了:如果Task_A中已经有了Activity_2,这时候如果以FLAG_ACTIVITY_NEW_TASK来start Activity_2,那么这个Task_A就会被
带到前台。
好了,现在Task_A已经可以到前台了,剩下最后一步:Activity_2不能创建两次,这就要求同时使用下面这个flag:
3. FLAG_ACTIVITY_SINGLE_TOP
如果Activity_2在Task的顶端,那么这个Activity_2就不会被再此创建,而是走onNewIntent.
至此,结合上面3个特性,问题得以解决。结合代码,流程如下:
1. 在androdiManifest.xml中添加Activity_2的taskAffinity name与Task_A相同(也就是与Activity_1的taskAffinity名字相同),如android:taskAffinity = "android.task.calendar"。
2. 在Task_B启动前,Activity_1先启动Activity_2并要求返回结果,startActivityForResult().
3. Task_B中的Activity_4取得所需数据后,保存好(intent,或其他方法),然后startActivity(Activity_2),并带上(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP)标志。
4. Task_A被带到前台,并且调用到Activity_2::onNewIntent().
5. Activity_2取得之前保存的信息(从Intent或其他地方),调用setResult(),然后finish().
6. Activity_1中的onActivityResult()响应,得到返回结果。
总结下: