如何使外部Activity的startActivityForResult工作?

5
搜索了很久,但是没有找到解决我的问题的结果。因此,我最终发帖请求协助。
我有两个应用程序,都是我编写的。应用程序A启动应用程序B,通过Intent.putExtra()传递参数。当应用程序B被启动时,这个过程完美地进行,参数也被很好地传递了。
然而,我找不到一种方法来返回响应给应用程序A。使用startActivityForResult()总是立即返回onActivityResult(),并且其结果为RESULT_CANCELED。经过进一步检查,logcat给出了一个警告,指出“Activity正在作为新任务启动,因此取消活动结果”。
我尝试使用不同的启动模式、操作筛选器(android.intent.action.PICK)来创建应用程序B的Activity,但是我所做的一切都没有改变任何东西。
我是在试图做不可能的事情吗?从我所理解的来看,我所尝试的应该类似于使用第三方活动从设备的照片库中选择图片。
编辑:
好的,我尝试删除Activity B中的LAUNCHER类别,但仍然无法解决问题。以下是我的Activity:
<activity android:name=".${CLASSNAME}" android:label="@string/app_name" android:configChanges="mcc|mnc|locale|keyboardHidden|orientation" android:launchMode="standard">
    <intent-filter>
        <action android:name="android.intent.action.PICK" />
    </intent-filter>
</activity>

有人真正让这个工作了吗?我开始怀疑启动另一个应用程序的活动永远不会返回结果,因为无论您在“intent-filter”中放置什么,它似乎总是会启动一个新任务。


发布你正在使用的代码来构建和启动ActivityB的意图。你应该能够像这样放置一些内容:this.setResult(Activity.RESULT_OK, data);在第二个Activity中返回到第一个。 - FoamyGuy
你能发布你的清单文件吗?也许Activity B有一些特殊的<activity>标签。 - nandeesh
嗯...活动B有<category android:name="android.intent.category.LAUNCHER" />这会引起问题吗?我现在不在我的工作机器上。我会尝试删除它,看看是否有效。问题是根据我所读的,启动不属于同一包的活动将始终在新任务中启动?如果是这样,startActivityForResult对于启动另一个apk上的外部活动将无法工作? - Lf3T-Hn4D
我已经尝试删除LAUNCHER类别,但也没有起作用。我已经在我的活动清单上编辑了原始帖子。 - Lf3T-Hn4D
3个回答

15
确保您要启动的Activity在清单文件中没有设置android:launchMode属性,并且检查android:taskAffinity是否被使用。请参见此处:http://developer.android.com/guide/topics/manifest/activity-element.html#aff 确保您用于启动该Activity的Intent没有设置FLAG_ACTIVITY_NEW_TASK标志。请参见此处:http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_NEW_TASK 特别注意:“当调用者请求从被启动的Activity返回结果时,不能使用此标志。”
如果Activity作为一个新任务启动,那么Android将立即通过RESULT_CANCELED调用onActivityResult(),因为一个任务中的Activity无法向另一个任务返回结果,只有在同一任务中的Activity才能这样做。

3

我发现自己遇到了同样的问题,于是查看了源代码并了解了为什么会添加NEW_TASK标志。

原来,如果源活动A或目标活动B使用了单实例启动模式,则会自动添加NEW_TASK标志:

    if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        // The original activity who is starting us is running as a single
        // instance...  this new activity it is starting must go on its
        // own task.
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
        // The activity being started is a single instance...  it always
        // gets launched into its own task.
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    }

由于您拥有两个应用程序,因此您应该能够确保在清单或意图中未定义这些启动模式。

到目前为止,我找不到任何非自愿设置NEW_TASK标志的其他实例。


0
在您的活动B中,您应该有类似以下的内容,
Intent intent = new Intent();
setResult(Activity.RESULT_OK, intent);
finish();

或者可以是:

setResult(Activity.RESULT_OK);
finish();

在不需要向Activity A传递任何数据的情况下。

否则,它将始终以结果代码Activity.RESULT_CANCELED结束;

如果子Activity由于任何原因(如崩溃)而失败,则父Activity将收到一个带有代码RESULT_CANCELED的结果。

希望这可以帮助您。


1
我已经实现了。问题是Activity A在Activity B结束之前就调用了onActivityResult()。Logcat给出了“Activity is launching as a new task, so cancelling activity result”的信息。所以似乎Activity B被作为一个新任务启动了,这并不奇怪,因为它是一个不同的apk应用程序?像图片选择器这样的实用程序活动是如何编写的呢? - Lf3T-Hn4D
@Lf3T-Hn4D 正如您所提到的,如果您的 launcher 类别中有此代码,它将作为一个新任务启动该活动。因此,它将完全独立于启动它的活动进行启动。请移除该类别样式并尝试。详细信息请参考:http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_NEW_TASK - code-jaff
啊..好的。我会尝试一下,等我回到工作机器上后再汇报。 :-) 谢谢 - Lf3T-Hn4D
1
我已经尝试删除LAUNCHER类别,但也没有起作用。我已经在我的活动清单上编辑了原始帖子。 - Lf3T-Hn4D

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接