转载注明出处:简书-十个雨点
如题,最近在做调用系统相册选取图片的功能时,发现在一些手机上就会出现这种问题,具体的现象是使用如下代码选取图片:
String IMAGE_UNSPECIFIED = "image/*";
int SELECTPHOTO=10086;
Intent intent=new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.putExtra(Intent.EXTRA_TITLE, "Pick a Pic");
intent.setType(IMAGE_UNSPECIFIED);
startActivityForResult(intent, SELECTPHOTO);
此时在onActivityResult()中会立即收到结果:resultCode=0,data=null。
而且最奇怪的是这个问题不是在所有手机上都出现的,也不一定在某些Android系统版本上都出现,比如据我所知,在4.4的酷派k1和6.0的小米3是会出现的,在6.0的三星s6e就不出现。
百度谷歌stackoverflow了许久也没找到答案,最后经过多番实验,发现的Activity的launchMode导致的:当android:launchMode=”singleInstance”时,就会出现,其他launchMode则不会。
在小李子吃苹果的指导下,我又进行了一些探索:
一开始他说:被启动activity在另一个task栈时候都会立即返回,比如被启动activity指定了taskAffinity。
我关注的重点放到了是taskaffinity不同导致的,于是我试着设置了一下,发现:first启动second的时候,如果second设了taskAffinity,还必须把second设成singleTask或者singleInstance才会直接立刻返回;或者first设成singleInstance才会出现。还得是低版本(4.4)的手机,高版本(6.0,其他没尝试)不会出现。
然后通过百度,我又发现taskaffinity必须配合singleTask或者singleInstance,才会产生新task的效果(4.4)。而在高版本(6.0)上则还必须设置FLAG_ACTIVITY_NEW_TASK才行。
至于如何判断taskaffinity是否生效,可以使用
adb shell dumpsys activity
打印出Recent tasks查看。
于是自然就想到,是不是只要设置FLAG_ACTIVITY_NEW_TASK来启动就会出这个问题呢?简单尝试,发现果然如此!
因此可以得出最后的结论,只要startActivityForResult()的调用方和被调用方不在同一个task中,就会立刻返回cancel。而在低版本和高版本中,可能产生新task的条件不完全相同,所以也导致了差异性。至于为什么有这样的差异性,等以后我研究明白了再单开一篇说说。
最后贴一段代码,ActivityStarter中的:
private void sendNewTaskResultRequestIfNeeded() {
if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
&& mStartActivity.resultTo.task.stack != null) {
// For whatever reason this activity is being launched into a new task...
// yet the caller has requested a result back. Well, that is pretty messed up,
// so instead immediately send back a cancel and let the new task continue launched
// as normal without a dependency on its originator.
Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
mStartActivity.resultTo = null;
}
}
阅读注释部分就可以发现跟我上面总结的一样的结论。
记录下来,方便万一有朋友遇到类似问题能搜到。
参考:
TaskAffinity属性小结