GitHub user riknoll opened a pull request:

    https://github.com/apache/cordova-android/pull/239

    CB-8917: Added pending plugin callbacks to resume event payload

    This is a redo of #236 after receiving some feedback. 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, allowing them to save state and 
have it restored if necessary.
    
    ### Saving/Restoring plugin state
    Two new methods are exposed to plugins that they can override to 
save/restore state.
    ```java
    /**
     * Called when the Activity is being destroyed (e.g. if a plugin calls out 
to an external
     * Activity and the OS kills the CordovaActivity in the background). The 
plugin should save its
     * state in this method only if it is awaiting the result of an external 
Activity and needs
     * to preserve some information so as to handle that result; 
onRestoreStateForActivityResult()
     * will only be called if the plugin is the recipient of an Activity result
     *
     * @return  Bundle containing the state of the plugin or null if state does 
not need to be saved
     */
    public Bundle onSaveInstanceState() {}
    
    /**
     * Called when a plugin is the recipient of an Activity result after the 
CordovaActivity has
     * been destroyed. The Bundle will be the same as the one the plugin 
returned in
     * onSaveInstanceState()
     *
     * @param state             Bundle containing the state of the plugin
     * @param callbackContext   Replacement Context to return the plugin result 
to
     */
    public void onRestoreStateForActivityResult(Bundle state, CallbackContext 
callbackContext) {}
    ```
    The plugin is given a replacement CallbackContext as part of 
`onRestoreStateForActivityResult` that can accept the result the plugin would 
normally return and add it to the resume event payload for use in the js (see 
JSON below). Thus, it requires minimal modifications to existing plugins
    
    _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. 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
    
    ### Saving/Restoring js state
    We already send out pause and resume events. This solution enhances these 
events in the case of Activity destruction by adding to them the result of any 
pending Plugin calls. The resume event is of the form
    ```
    {
        action: "resume",
        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>
        }
    }
    ```
    It is the responsibility of the application developer to properly use these 
events and save their state as well as keep information about what plugin 
results they have pending. We should provide guidance for this in the Android 
documentation and plugin documentation should clearly communicate when it is 
necessary.
    
    ### 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
    
    #### Downsides:
    
    * 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 (CB-9189). The updated Camera Plugin can be found in [this 
branch](https://github.com/MSOpenTech/cordova-plugin-camera/tree/save-state-plugin-only)
 and a (trivial) example application that uses this API + instructions for 
testing can be found 
[here](https://gist.github.com/riknoll/d0ab25583b1dc8ab22af).


You can merge this pull request into a Git repository by running:

    $ git pull https://github.com/MSOpenTech/cordova-android 
save-state-plugin-only

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

    https://github.com/apache/cordova-android/pull/239.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 #239
    
----
commit 62a7873792205696c25b8498b521ef9828648e59
Author: riknoll <richard.b.kn...@gmail.com>
Date:   2015-11-10T23:01:13Z

    CB-8917: Added pending plugin callbacks to resume event payload

----


---
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 infrastruct...@apache.org or file a JIRA ticket
with INFRA.
---

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@cordova.apache.org
For additional commands, e-mail: dev-h...@cordova.apache.org

Reply via email to