[
https://issues.apache.org/jira/browse/CB-8917?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14999723#comment-14999723
]
ASF GitHub Bot commented on CB-8917:
------------------------------------
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 <[email protected]>
Date: 2015-11-10T23:01:13Z
CB-8917: Added pending plugin callbacks to resume event payload
----
> 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]