cordova-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From riknoll <>
Subject [GitHub] cordova-android pull request: API for saving/restoring plugin and ...
Date Wed, 28 Oct 2015 19:00:49 GMT
GitHub user riknoll opened a pull request:

    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 ``
as part of the CoreAndroid API. An application can pass an object to ``
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>,
            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 save-state

Alternatively you can review and apply these changes as the patch at:

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 <>
Date:   2015-10-27T19:36:43Z

    Added support for Android lifecycle state saving/restoring

commit 02ef016863cc6faf722149342294566564f8055e
Author: riknoll <>
Date:   2015-10-28T18:03:59Z

    Cleaning up the resume event object api a bit

commit 760223e076783337a8442f61237b2820f7026f1d
Author: riknoll <>
Date:   2015-10-28T18:09:56Z

    Merge branch 'master' of

commit 448c69555f002378f88ff06b26dc797fe2f3d5a1
Author: riknoll <>
Date:   2015-10-28T18:43:15Z

    Removed logging code


If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at or file a JIRA ticket
with INFRA.

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message