[ https://issues.apache.org/jira/browse/CB-8917?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14979024#comment-14979024 ]
ASF GitHub Bot commented on CB-8917: ------------------------------------ GitHub user riknoll opened a pull request: https://github.com/apache/cordova-android/pull/236 API for saving/restoring plugin and js state Here is my proposal for dealing with Activity destruction in Android. The code is still a little rough and might need to be finalized, but I wanted to present it for discussion. This relates to CB-8917 and CB-9189. ### Background The issue at hand is that plugins can make calls to an external Activity and, if the device is low on memory, there is a chance that the CordovaActivity will get killed in the background causing the plugin to lose its state as well as its context for the callback. Activities in Android typically handle this situation by using `onSaveInstanceState()` and `onCreate()` methods to save and restore state respectively as the Activity is created and destroyed. This solution exposes that lifecycle to plugins as well as the js, allowing them to save state and have it restored if necessary. ### Saving js state The js is given the ability to save its state in JSON using a new method in `navigator.app` as part of the CoreAndroid API. An application can pass an object to `navigator.app.saveState()` to save state in case of Activity destruction. This state is returned to the js as part of the resume event's payload and the js application can use it to properly restore the app. The idea is that app developers can take care of state by subscribing to the pause event to save and have it returned in the corresponding resume event. Plugins are also given the opportunity to add to the JSON to convey any information that is needed for the js to resume properly (see [1] below). ### Saving plugin state A plugin that calls out to an external Activity is given the chance to properly restore its state before handling the result of the Activity by implementing the new `onSaveInstanceState()` and `onRestoreInstanceState()` methods that are called as part of the Activity lifecycle. The plugin is given a replacement CallbackContext as part of `onRestoreInstanceState` that can accept the result and add it to the resume event payload for use in the js (again, see [1] below). _NOTE:_ When I mention that plugins are given the opportunity to restore state, I want to clarify that this only happens for plugins that are waiting for an external Activity result (I try to emphasize this in the `onRestoreInstanceState` method's javadoc). This makes the API a little less intuitive, but otherwise we would be conflicting with the accepted behavior that plugins currently get destroyed (i.e. lose all of their state) and are selectively rebuilt whenever a new URL is loaded into the webview. If we restore state on resume, then we can end up with some awkward cases where part of the resuming involves loading a new page so the state gets lost again and so on and so forth. My thinking is that restoring the other state is better left to app developers ### Discussion #### Benefits: * It requires minimal updates to existing plugins (and no updates at all if the plugin doesn't use an external Activity) * It is a general solution/pattern that plugins can follow rather than forcing them to include platform specific methods in their APIs * It allows the js app to save/restore its state whereas previously the app would just restart with no context #### Downsides: * It still requires that app developers have platform specific code in their js (unless other platforms adopt this API, but I don't know if they have the corresponding need for it) * The resume callback will only ever get received after the initial page loads (potential page flickering) * The pending result part of the event object doesn't provide much context (so it puts more responsibility on the app developer to keep state so they know what they're getting) In the core plugins, this is mostly relevant to the Camera plugin which previously would crash upon receiving the Activity result if the CordovaActivity had been killed by the OS while a picture was being taken/chosen. I also updated the camera plugin to use this new API and the only necessary changes to the existing plugin code were the addition of the onSaveInstanceState and onRestoreInstanceState methods. I can post that code too if there is interest in seeing what the plugin side of this looks like [1] Anatomy of resume event object: ``` { action: "resume", state: <state object passed to app.saveState>, plugins: <objects for plugins in the form {serviceName:{pluginState}, ...}>, pendingResult: { pluginServiceName: <plugin service name e.g. "Camera">, pluginStatus: <description of result' status (see PluginResult.java)>, result: <argument(s) that would have been given to the callback> } } ``` You can merge this pull request into a Git repository by running: $ git pull https://github.com/MSOpenTech/cordova-android save-state Alternatively you can review and apply these changes as the patch at: https://github.com/apache/cordova-android/pull/236.patch To close this pull request, make a commit to your master/trunk branch with (at least) the following in the commit message: This closes #236 ---- commit 2fca689f9353ddb1058b418a26818444cace79bf Author: riknoll <rikn...@microsoft.com> Date: 2015-10-27T19:36:43Z Added support for Android lifecycle state saving/restoring commit 02ef016863cc6faf722149342294566564f8055e Author: riknoll <rikn...@microsoft.com> Date: 2015-10-28T18:03:59Z Cleaning up the resume event object api a bit commit 760223e076783337a8442f61237b2820f7026f1d Author: riknoll <rikn...@microsoft.com> Date: 2015-10-28T18:09:56Z Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/cordova-android commit 448c69555f002378f88ff06b26dc797fe2f3d5a1 Author: riknoll <rikn...@microsoft.com> Date: 2015-10-28T18:43:15Z Removed logging code ---- > Add api/way to get plugins results even when Cordova activity restarts > ------------------------------------------------------------------------ > > Key: CB-8917 > URL: https://issues.apache.org/jira/browse/CB-8917 > Project: Apache Cordova > Issue Type: Improvement > Components: Android > Reporter: Bnaya > > In android when you have a plugin that opens new activity the CordovaActivity > will be killed and you won't get the result from the plugin. > The new activity will get the results but because the plugin objects are dead > and the webview reloaded you can get the data to the js callback. > The most noticeable example is the camera plugin. (And maybe its the same > with even more platforms) > possible solution for this is to add metadata to the device ready event with > incoming data from plugins. -- This message was sent by Atlassian JIRA (v6.3.4#6332) --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@cordova.apache.org For additional commands, e-mail: issues-h...@cordova.apache.org