Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-26075] Android: Refactor app resume and "newintent" handling

GitHub Issuen/a
TypeImprovement
PriorityHigh
StatusClosed
ResolutionFixed
Resolution Date2019-01-04T21:17:23.000+0000
Affected Version/sn/a
Fix Version/sRelease 8.0.0
ComponentsAndroid
Labelsandroid, breaking-change, intent, intent-filter, resume
ReporterJoshua Quick
AssigneeJoshua Quick
Created2018-05-30T03:33:56.000+0000
Updated2019-12-04T20:10:25.000+0000

Description

*Summary:* Titanium's app resume handling from notification, shortcuts, intent-filters, etc. is problematic. It does not always resume and instead displays a new splash-screen instance which never runs the "app.js" (appears to hang) or a dialog stating that the app needs to be restarted (which can get stuck in an infinite loop). The following is a list of issues that have been reported. Some are flagged closed, but they're not completely resolved: * [TIMOB-1559] * [TIMOB-4941] * [TIMOB-9285] * [TIMOB-15253] * [TIMOB-24427] * [TIMOB-24747] * [TIMOB-25776] *Recommended Solution:* Get rid of *+all+* of the activity "restarting" code. No one likes this behavior. * [TiRootActivity.onCreate()](https://github.com/appcelerator/titanium_mobile/blob/master/android/titanium/src/java/org/appcelerator/titanium/TiRootActivity.java#L75) * [TiLaunchActivity.onCreate()](https://github.com/appcelerator/titanium_mobile/blob/master/android/titanium/src/java/org/appcelerator/titanium/TiLaunchActivity.java#L142) * [TiBaseActivity.onCreate()](https://github.com/appcelerator/titanium_mobile/blob/master/android/titanium/src/java/org/appcelerator/titanium/TiBaseActivity.java#L578) Drop support for Android bug 2373/5277 related "tiapp.xml" properties: * [link](https://docs.appcelerator.com/platform/latest/#!/guide/tiapp.xml_and_timodule.xml_Reference-section-src-29004921_tiapp.xmlandtimodule.xmlReference-PropertiestoworkaroundAndroidbugs2373and5277) In the main activity's onCreate(), we should do the following:

Check if TiApplication.getRootActivity() is not null. This tells us if a pre-existing activity window is already in the background and needs to be resumed. If it doesn't exist, then go ahead and create the activity (we're done).

Fetch the pre-existing root activity's intent. If we call Context.startActivity() with this intent, then it'll resume it with all of its child activity windows intact. _(This is what we're missing.)_

Call finish() for the new activity since we don't want to spawn a new instance. Attempt to disable the activity window's animation if possible via Activity.overridePendingTransition().

Have the pre-existing root activity fire a "newintent" event with the intent received by the new activity that we just finished/closed. (We must wait for the old activity task to resume first though.)

*Issues to Investigate:* * The Activity.getIntent() can return null in rare cases ([link](https://stackoverflow.com/questions/37856407/can-activity-getintent-ever-return-null)). We need to figure out how to resume the app's activity in this case. * We need to double check the necessity of TiBaseActivity.isUnsupportedReLaunch(). I suspect it's handling the case where a new Java runtime and Application instance is being re-created for a pre-existing app process (the C/C++ side's static variables still remember previous application info). * Check how this works with launchMode "singleTop". (It is being used by some community users. Although with this change, we shouldn't need it anymore.) * Re-test with Titanium's "Live-View" feature and Ti.App._restart() method to make sure they don't break. *Limitations:* * Titanium only supports running one V8 JavaScript runtime at a time. So, multiple activity tasks cannot be supported due to this limitation. This is partly why we need to refactor the app resume behavior. _(This may be fine from a portability standpoint anyways since iOS does not support this.)_ * We should avoid launchMode "singleTask" support. While it does what we want and makes an Android app work more like iOS, it comes with a huge limitation. A "singleTask" activity's child activity windows are all torn down by the Android OS after homing-out of the app and then resuming it. "singleTask" is only a viable solution if we re-architected Titanium to only support one activity and and all Ti.UI.Window objects spawned fragments instead, but this would be a major MAJOR breaking-change that is best avoided for now.

Attachments

FileDateSize
IntentRequestResultTest.js2018-12-12T02:00:59.000+00001640
IntentReturnResultTest.js2018-12-12T02:00:59.000+00001924

Comments

  1. Joshua Quick 2018-12-12

    PR (master): https://github.com/appcelerator/titanium_mobile/pull/10519
  2. Lokesh Choudhary 2019-01-04

    FR Passed. PR Merged.
  3. Josh Longton 2019-01-08

    *Closing ticket.* The improvement is present in SDK: {noformat} 8.0.0.v20190104153150 {noformat}
  4. Jake Dempsey 2019-12-04

    This looks to be broken again: We have an issue where when we share a file from android downloads to our app it is launching a second instance of the app. This was fixed in a previous release and is broken again. We have a CSV file, when we share it to our app it used to open the existing instance of the app and we would get access to the CSV file that was sent to it via the intent and the getBlobExtra. We can no longer do this as its broken again. I have tried building w/ 8.1, 8.2, and 8.3 and all are launching a second app instance. If I get the currentActivity and the intent from that I can make my app work again but my understanding was that a second app instance was not intended and it should be launching the existing instance and we use the root activity to get the intent as outlined here: https://wiki.appcelerator.org/display/guides2/Android+Intent+Filters In addition when the app is not running and I send a file to it it will launch a new instance but intent.hasExtra(Ti.Android.EXTRA_STREAM) return false where intent is Ti.App.Android.launchIntent.

JSON Source