[
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 <[email protected]>
Date: 2015-10-27T19:36:43Z
Added support for Android lifecycle state saving/restoring
commit 02ef016863cc6faf722149342294566564f8055e
Author: riknoll <[email protected]>
Date: 2015-10-28T18:03:59Z
Cleaning up the resume event object api a bit
commit 760223e076783337a8442f61237b2820f7026f1d
Author: riknoll <[email protected]>
Date: 2015-10-28T18:09:56Z
Merge branch 'master' of
https://git-wip-us.apache.org/repos/asf/cordova-android
commit 448c69555f002378f88ff06b26dc797fe2f3d5a1
Author: riknoll <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]