From 1aaba440b53b0622cff0bde3e143ba107c23c30a Mon Sep 17 00:00:00 2001 From: Serge Huijben Date: Tue, 31 Mar 2015 08:28:13 +0200 Subject: [PATCH] CB-8768 Fix onActivityResult called before plugins are loaded (after MainActivity gets killed) situation: one of the plugins launches startActivityForResult and the Android OS decides to kill our MainActivity. once the launched activity is fulfilled it comes back to our MainActivity, which has to be recreated first. unfortunately Android calls onActivityResult before our Activity has fully loaded our installed plugins. close #171 --- .../org/apache/cordova/CordovaActivity.java | 2 +- .../apache/cordova/CordovaInterfaceImpl.java | 37 +++++++++++++++---- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/framework/src/org/apache/cordova/CordovaActivity.java b/framework/src/org/apache/cordova/CordovaActivity.java index a40aaa6e..8e185dde 100755 --- a/framework/src/org/apache/cordova/CordovaActivity.java +++ b/framework/src/org/apache/cordova/CordovaActivity.java @@ -138,7 +138,7 @@ public class CordovaActivity extends Activity { if (!appView.isInitialized()) { appView.init(cordovaInterface, pluginEntries, preferences); } - cordovaInterface.setPluginManager(appView.getPluginManager()); + cordovaInterface.onCordovaInit(appView.getPluginManager()); // Wire the hardware volume controls to control media if desired. String volumePref = preferences.getString("DefaultVolumeStream", ""); diff --git a/framework/src/org/apache/cordova/CordovaInterfaceImpl.java b/framework/src/org/apache/cordova/CordovaInterfaceImpl.java index 2dc6b3db..96d316ab 100644 --- a/framework/src/org/apache/cordova/CordovaInterfaceImpl.java +++ b/framework/src/org/apache/cordova/CordovaInterfaceImpl.java @@ -17,6 +17,7 @@ public class CordovaInterfaceImpl implements CordovaInterface { protected ExecutorService threadPool; protected PluginManager pluginManager; + protected ActivityResultHolder savedResult; protected CordovaPlugin activityResultCallback; protected String initCallbackService; protected int activityResultRequestCode; @@ -30,10 +31,6 @@ public class CordovaInterfaceImpl implements CordovaInterface { this.threadPool = threadPool; } - public void setPluginManager(PluginManager pluginManager) { - this.pluginManager = pluginManager; - } - @Override public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) { setActivityResultCallback(command); @@ -72,6 +69,16 @@ public class CordovaInterfaceImpl implements CordovaInterface { return threadPool; } + /** + * Dispatches any pending onActivityResult callbacks. + */ + public void onCordovaInit(PluginManager pluginManager) { + this.pluginManager = pluginManager; + if (savedResult != null) { + onActivityResult(savedResult.requestCode, savedResult.resultCode, savedResult.intent); + } + } + /** * Routes the result to the awaiting plugin. Returns false if no plugin was waiting. */ @@ -80,17 +87,21 @@ public class CordovaInterfaceImpl implements CordovaInterface { if(callback == null && initCallbackService != null) { // The application was restarted, but had defined an initial callback // before being shut down. - callback = pluginManager.getPlugin(initCallbackService); + savedResult = new ActivityResultHolder(requestCode, resultCode, intent); + if (pluginManager != null) { + callback = pluginManager.getPlugin(initCallbackService); + } } - initCallbackService = null; activityResultCallback = null; if (callback != null) { Log.d(TAG, "Sending activity result to plugin"); + initCallbackService = null; + savedResult = null; callback.onActivityResult(requestCode, resultCode, intent); return true; } - Log.w(TAG, "Got an activity result, but no plugin was registered to receive it."); + Log.w(TAG, "Got an activity result, but no plugin was registered to receive it" + (savedResult != null ? " yet!": ".")); return false; } @@ -119,4 +130,16 @@ public class CordovaInterfaceImpl implements CordovaInterface { public void restoreInstanceState(Bundle savedInstanceState) { initCallbackService = savedInstanceState.getString("callbackService"); } + + private static class ActivityResultHolder { + private int requestCode; + private int resultCode; + private Intent intent; + + public ActivityResultHolder(int requestCode, int resultCode, Intent intent) { + this.requestCode = requestCode; + this.resultCode = resultCode; + this.intent = intent; + } + } }