On Android, when using plugins that launch other intents, e.g. the Camera
plugin, I'm now seeing reliable crashes when the cordova activity is resumed -
if it was "destroyed" when the intent launched. The reliable way to reproduce
this is to enable the "Don't keep activities" setting in Android's Developer
options. Based on the Google Play crash reports, this just started when we
updated our app to use the new
[email protected]<mailto:[email protected]> runtime.
In the Camera plugin, the issue is that the
CameraLauncher.processResultFromCamera method uses an instance variable,
imageUri, which is set prior to launching the intent, but null when the
activity is resumed. Presumably, this is because the plugin isn't aware that it
needs to save state? Here's the full stack trace:
java.lang.RuntimeException: Unable to resume activity {<app>}:
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null,
request=34, result=-1, data=null} to activity {<app>}:
java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.String android.net.Uri.toString()' on a null object reference
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3349)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3380)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2731)
at android.app.ActivityThread.access$900(ActivityThread.java:172)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5835)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)
Caused by: java.lang.RuntimeException: Failure delivering result
ResultInfo{who=null, request=34, result=-1, data=null} to activity {<app>}:
java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.String android.net.Uri.toString()' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:3977)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3335)
... 11 more
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.String android.net.Uri.toString()' on a null object reference
at
org.apache.cordova.camera.CameraLauncher.processResultFromCamera(CameraLauncher.java:445)
at
org.apache.cordova.camera.CameraLauncher.onActivityResult(CameraLauncher.java:674)
at
org.apache.cordova.CordovaInterfaceImpl.onActivityResult(CordovaInterfaceImpl.java:120)
at org.apache.cordova.CordovaActivity.onActivityResult(CordovaActivity.java:321)
at android.app.Activity.dispatchActivityResult(Activity.java:6475)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3973)
... 12 more
I've been looking at this for a bit, and am wondering whether this can even be
supported with the current plugin architecture. I see that onStart and onStop
are now part of the plugin interface, but not
onSaveInstanceState/onRestoreInstanceState. It seems like a fairly common
pattern for plugins to save the CallbackContext, so this will impact more than
just the Camera plugin.
Has any thought gone into supporting this scenario? Is it possible to do with
the current plugin interface, or would it need to be extended to add the
instance state handlers to allow plugins to preserve necessary state? I'm happy
to take a stab at addressing this, but would appreciate insight from the
android native devs on the right way to approach this issue. (I haven't yet
filed a JIRA issue on this, but will shortly.)
Thanks,
Dan