Skip to content

Commit

Permalink
fix(android): resuming with intent "FLAG_ACTIVITY_MULTIPLE_TASK" can …
Browse files Browse the repository at this point in the history
…hang the app (#11080)

- Modified to effectively restart the app when the following intent flags are set:
  * FLAG_ACTIVITY_MULTIPLE_TASK
  * FLAG_ACTIVITY_NEW_DOCUMENT
- Modified resume code to use main/launch intent flags.
  * We don't want flags such as FLAG_ACTIVITY_CLEAR_TOP to destroy child activities when resuming app.

Fixes TIMOB-27271
  • Loading branch information
jquick-axway authored and sgtcoolguy committed Aug 20, 2019
1 parent c139922 commit 3a71853
Showing 1 changed file with 38 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ public void run()
} catch (Exception ex) {
Log.e(TAG, "Failed to close existing Titanium root activity.", ex);
}
} else if (!canResumeActivityUsing(newIntent) || !canResumeActivityUsing(rootActivity.getLaunchIntent())) {
// It's impossible to resume existing root activity. So, we have to destroy it and restart.
// Note: This typically happens with ACTION_SEND and ACTION_*_DOCUMENT intents.
rootActivity.finishAffinity();
TiApplication.terminateActivityStack();
if ((newIntent != null) && !newIntent.filterEquals(mainIntent)) {
mainIntent.putExtra(TiC.EXTRA_TI_NEW_INTENT, newIntent);
}
mainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(mainIntent);
} else {
// Simulate "singleTask" handling by updating existing root activity's intent with received one.
if (newIntent == null) {
Expand All @@ -215,9 +225,13 @@ public void run()
rootActivity.onNewIntent(newIntent);

// Resume the pre-existing Titanium root activity.
// Note: On Android, you resume a backgrounded activity by using its initial launch intent.
// Note: You can resume a backgrounded activity by using its initial launch intent,
// but we need to remove flags such as CLEAR_TOP to preserve its child activities.
Intent resumeIntent = rootActivity.getLaunchIntent();
if (resumeIntent == null) {
if (resumeIntent != null) {
resumeIntent = new Intent(resumeIntent);
resumeIntent.setFlags(mainIntent.getFlags());
} else {
resumeIntent = mainIntent;
}
startActivity(resumeIntent);
Expand Down Expand Up @@ -543,4 +557,26 @@ public static boolean isScriptRunning()
{
return TiRootActivity.isScriptRunning;
}

/**
* Determine if an existing activity can be resumed with the given intent via startActivity() method.
* <p>
* For example, an intent flag such as "FLAG_ACTIVITY_MULTIPLE_TASK" always creates a new activity instance
* even if an existing activity with a matching intent already exists. This makes resumes impossible.
* @param intent The intent to be checked. Can be null.
* @return
* Returns true if an activity can be resumed based on given intent's flags.
* <p>
* Returns false if impossible to resume or if given a null argument.
*/
private static boolean canResumeActivityUsing(Intent intent)
{
if (intent != null) {
final int BAD_FLAGS = (Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
if ((intent.getFlags() & BAD_FLAGS) == 0) {
return true;
}
}
return false;
}
}

0 comments on commit 3a71853

Please sign in to comment.