onActivityResult 与 launchMode="singleTask"?
Posted
技术标签:
【中文标题】onActivityResult 与 launchMode="singleTask"?【英文标题】:onActivityResult With launchMode="singleTask"? 【发布时间】:2012-02-16 02:52:55 【问题描述】:当您尝试使用startActivityForResult
获取具有launchMode="singleTask"
的Activity
时;它不会返回任何带有onActivityResult
的值,并且当您设置launchMode="standard"
时;一切正常,但系统要求说这个Activity
必须是singleTask
,有没有办法解决这个问题?
【问题讨论】:
【参考方案1】:startActivityForResult
的文档说:
For example, if the activity you are launching uses the singleTask launch mode,
it will not run in your task and thus you will immediately receive a cancel result.
似乎没有办法解决这个问题。
如果您是被调用 Activity 的开发者,那么您可以让它在某些结果可用时发送广播。然后调用的 Activity 可以列出这个广播。
【讨论】:
那么如何防止在 onClick 中创建多个实例(例如列表视图)?【参考方案2】:答案显示在 ActivityStackSupervisor
类的函数 startActivityUncheckedLocked
中。
在android 5.x之前,启动一个activity时,会先检查launchMode,如果launchMode是singleTask或者singleInstance,会在launchFlags中加上FLAG_ACTIVITY_NEW_TASK
。如果活动的launchFlags 包含FLAG_ACTIVITY_NEW_TASK
,它会立即发回一个取消,让新任务继续正常启动,而不依赖于它的发起者。
if (sourceRecord == null)
// This activity is not being started from another... in this
// case we -always- start a new task.
if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0)
Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
"Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
else 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;
// ......
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0)
// 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.");
r.resultTo.task.stack.sendActivityResultLocked(-1,
r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
r.resultTo = null;
但在 Android 5.x 中,更改如下:
final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
int launchFlags = intent.getFlags();
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
(launchSingleInstance || launchSingleTask))
// We have a conflict between the Intent and the Activity manifest, manifest wins.
Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
"\"singleInstance\" or \"singleTask\"");
launchFlags &=
~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
else
switch (r.info.documentLaunchMode)
case ActivityInfo.DOCUMENT_LAUNCH_NONE:
break;
case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
break;
case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
break;
case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
break;
final boolean launchTaskBehind = r.mLaunchTaskBehind
&& !launchSingleTask && !launchSingleInstance
&& (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0)
// 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.");
r.resultTo.task.stack.sendActivityResultLocked(-1,
r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
r.resultTo = null;
这就是为什么 onActivityResult
可以在 Android 5.x 中运行,即使您将 launchMode 设置为 singleTask
或 singleInstance
。
【讨论】:
【参考方案3】:@Peter Knego 怎么说
加
它似乎在 5.1 中工作,而不是在 4.4.4
表示 onActivityResult 触发
【讨论】:
是的,我还观察到它在 5.o 及更高版本中工作,而不是在 4.4.4 中【参考方案4】:澄清一些答案:
API 的
startActivityForResult()
与启动模式 singleTask
或 singleInstance
结合使用不起作用。 onActivityResult()
将立即被调用,结果代码为Activity.RESULT_CANCELED
。
API 的 >= Android 5.x:
startActivityForResult()
有效,但启动模式singleTask
或singleInstance
基本上被忽略,这意味着活动被启动到同一个任务中并且没有创建新任务。
如果你想验证这个运行adb shell dumpsys activity activities
。我只希望系统至少会向我显示一个警告。
这种变化也反映在@GGCoke 的代码位中有posted。
【讨论】:
【参考方案5】:我知道这已经很晚了,但您可以对 onNewIntent() 方法产生 OnActivityResult 效果,因为这是您的 singleTask 活动。
【讨论】:
以上是关于onActivityResult 与 launchMode="singleTask"?的主要内容,如果未能解决你的问题,请参考以下文章
关于Fragment的onActivityResult 不执行
Android startActivityForResult和onActivityResult的基本用法
Android Studio基础项目-两个Activity的Intent跳转与传值,并onActivityResult回传一个/多个值,与回传消息内容。
Android Studio基础项目-两个Activity的Intent跳转与传值,并onActivityResult回传一个/多个值,与回传消息内容。
Android Studio基础项目-两个Activity的Intent跳转与传值,并onActivityResult回传一个/多个值,与回传消息内容。