Когда вы пытаетесь startActivityForResult
для Activity
, у которого есть launchMode="singleTask"
; он не вернет никаких значений с onActivityResult
, и когда вы установите launchMode="standard"
; все работает нормально, но в системных требованиях написано, что это Activity
должно быть singleTask
, можно ли как-то это решить?
onActivityResult С launchMode=singleTask?
Ответы:
Документы 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, вы можете отправить его в широковещательную рассылку, когда будет доступен какой-либо результат. Затем вызывающая активность может перечислить эти трансляции.
Ответ показан в функции startActivityUncheckedLocked
класса ActivityStackSupervisor
. До Android 5.x при запуске действия он сначала проверяет launchMode и добавляет FLAG_ACTIVITY_NEW_TASK
к launchFlags, если launchMode имеет значение singleTask или singleInstance. Если значение 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
.
Что говорит @Peter Knego
плюс
вроде работает в 5.1, а не в 4.4.4
это означает, что onActivityResult срабатывает
Чтобы уточнить некоторые ответы:
API ‹ Android 5.x:
startActivityForResult()
в сочетании с режимами запуска singleTask
или singleInstance
не работает. onActivityResult()
будет вызван немедленно с кодом результата Activity.RESULT_CANCELED
.
API ›= Android 5.x:
startActivityForResult()
работает, но режимы запуска singleTask
или singleInstance
в основном игнорируются, то есть активность запускается в той же задаче, и новая задача не создается.
Если вы хотите проверить это, запустите adb shell dumpsys activity activities
. Я только хочу, чтобы система, по крайней мере, показала мне предупреждение об этом.
Это изменение также отражено в фрагментах кода, которые @GGCoke опубликовал .
Я знаю, что это довольно поздно, но вы можете иметь эффект OnActivityResult для метода onNewIntent(), потому что это ваша активность singleTask.