Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onActivityResult With launchMode="singleTask"?

Tags:

When you try to startActivityForResult for Activity that has launchMode="singleTask"; it will not return any values with onActivityResult,and when you set launchMode="standard"; everything works fine, but the system requirements says this Activity must be singleTask, is there anyway to solve this?

like image 241
Mohammad Ersan Avatar asked Jan 22 '12 09:01

Mohammad Ersan


People also ask

What is result code in onActivityResult?

onActivityResult - resultCode is always 0.

What is Android launchMode singleTop?

singleTopIf an instance is not present on top of task then new instance will be created. Using this launch mode you can create multiple instance of the same activity in the same task or in different tasks only if the same instance does not already exist at the top of stack.

What is the use of onActivityResult in Android?

When you done with the subsequent activity and returns, the system calls your activity's onActivityResult() method. This method includes three arguments: @The request code you passed to startActivityForResult() . @A result code specified by the second activity.

How can I get result from startActivityForResult?

First you use startActivityForResult() with parameters in the first Activity and if you want to send data from the second Activity to first Activity then pass the value using Intent with the setResult() method and get that data inside the onActivityResult() method in the first Activity .


2 Answers

The docs of the startActivityForResult say:

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. 

It seems there is no way to get around this.

If you are the developer of called Activity, then you can have it send a broadcast when some result is available. The calling Activity can then list to this broadcasts.

like image 77
Peter Knego Avatar answered Nov 11 '22 08:11

Peter Knego


The answer shows in function startActivityUncheckedLocked of class ActivityStackSupervisor. Before Android 5.x, when starting an activity, it will check launchMode first and add FLAG_ACTIVITY_NEW_TASK to launchFlags if launchMode is singleTask or singleInstance. If the activity's launchFlags contains FLAG_ACTIVITY_NEW_TASK, it will send back a cancel immediately and let the new task continue launched as normal without a dependency on its originator.

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; } 

But in Android 5.x, this was changed as below:

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; } 

That's why onActivityResult works in Android 5.x even you set launchMode to singleTask or singleInstance.

like image 23
GGCoke Avatar answered Nov 11 '22 09:11

GGCoke