From 7f4e632d915fe425b7b0f6f2b3ef8172ed1808d5 Mon Sep 17 00:00:00 2001 From: Steven Sherry Date: Fri, 11 Nov 2022 12:02:36 -0600 Subject: [PATCH 1/2] feat(android): Adds support for registering already initialized instances of plugins to the bridge. --- .../main/java/com/getcapacitor/Bridge.java | 100 +++++++++++++----- .../java/com/getcapacitor/PluginHandle.java | 32 ++++-- 2 files changed, 99 insertions(+), 33 deletions(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java index bca83fbaf8..4829ec18d6 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java @@ -120,6 +120,8 @@ public class Bridge { private final List> initialPlugins; + private final List pluginInstances; + // A map of Plugin Id's to PluginHandle's private Map plugins = new HashMap<>(); @@ -162,7 +164,7 @@ public Bridge( CordovaPreferences preferences, CapConfig config ) { - this(context, null, null, webView, initialPlugins, cordovaInterface, pluginManager, preferences, config); + this(context, null, null, webView, initialPlugins, new ArrayList<>(), cordovaInterface, pluginManager, preferences, config); } private Bridge( @@ -171,6 +173,7 @@ private Bridge( Fragment fragment, WebView webView, List> initialPlugins, + List pluginInstances, MockCordovaInterfaceImpl cordovaInterface, PluginManager pluginManager, CordovaPreferences preferences, @@ -183,6 +186,7 @@ private Bridge( this.webView = webView; this.webViewClient = new BridgeWebViewClient(this); this.initialPlugins = initialPlugins; + this.pluginInstances = pluginInstances; this.cordovaInterface = cordovaInterface; this.preferences = preferences; @@ -578,6 +582,10 @@ private void registerAllPlugins() { for (Class pluginClass : this.initialPlugins) { this.registerPlugin(pluginClass); } + + for (Plugin plugin : pluginInstances) { + registerPluginInstance(plugin); + } } /** @@ -590,6 +598,12 @@ public void registerPlugins(Class[] pluginClasses) { } } + public void registerPluginInstances(Plugin[] pluginInstances) { + for (Plugin plugin : pluginInstances) { + this.registerPluginInstance(plugin); + } + } + @SuppressWarnings("deprecation") private String getLegacyPluginName(Class pluginClass) { NativePlugin legacyPluginAnnotation = pluginClass.getAnnotation(NativePlugin.class); @@ -606,39 +620,65 @@ private String getLegacyPluginName(Class pluginClass) { * @param pluginClass a class inheriting from Plugin */ public void registerPlugin(Class pluginClass) { - String pluginName; + String pluginId = pluginId(pluginClass); + if (pluginId == null) return; - CapacitorPlugin pluginAnnotation = pluginClass.getAnnotation(CapacitorPlugin.class); - if (pluginAnnotation == null) { - pluginName = this.getLegacyPluginName(pluginClass); - if (pluginName == null) { - return; - } - } else { - pluginName = pluginAnnotation.name(); + try { + this.plugins.put(pluginId, new PluginHandle(this, pluginClass)); + } catch (InvalidPluginException ex) { + logInvalidPluginException(pluginClass); + } catch (PluginLoadException ex) { + logPluginLoadException(pluginClass, ex); } + } + + public void registerPluginInstance(Plugin plugin) { + Class clazz = plugin.getClass(); + String pluginId = pluginId(clazz); + if (pluginId == null) return; + + try { + this.plugins.put(pluginId, new PluginHandle(this, plugin)); + } catch (InvalidPluginException ex) { + logInvalidPluginException(clazz); + } + } - String pluginId = pluginClass.getSimpleName(); + private String pluginId(Class clazz) { + String pluginName = pluginName(clazz); + String pluginId = clazz.getSimpleName(); + if (pluginName == null) return null; - // Use the supplied name as the id if available if (!pluginName.equals("")) { pluginId = pluginName; } + Logger.debug("Registering plugin instance: " + pluginId); + return pluginId; + } + + private String pluginName(Class clazz) { + String pluginName; + CapacitorPlugin pluginAnnotation = clazz.getAnnotation(CapacitorPlugin.class); + if (pluginAnnotation == null) { + pluginName = this.getLegacyPluginName(clazz); + } else { + pluginName = pluginAnnotation.name(); + } - Logger.debug("Registering plugin: " + pluginId); + return pluginName; + } - try { - this.plugins.put(pluginId, new PluginHandle(this, pluginClass)); - } catch (InvalidPluginException ex) { - Logger.error( + private void logInvalidPluginException(Class clazz) { + Logger.error( "NativePlugin " + - pluginClass.getName() + - " is invalid. Ensure the @CapacitorPlugin annotation exists on the plugin class and" + - " the class extends Plugin" - ); - } catch (PluginLoadException ex) { - Logger.error("NativePlugin " + pluginClass.getName() + " failed to load", ex); - } + clazz.getName() + + " is invalid. Ensure the @CapacitorPlugin annotation exists on the plugin class and" + + " the class extends Plugin" + ); + } + + private void logPluginLoadException(Class clazz, Exception ex) { + Logger.error("NativePlugin " + clazz.getName() + " failed to load", ex); } public PluginHandle getPlugin(String pluginId) { @@ -1360,6 +1400,7 @@ public static class Builder { private Bundle instanceState = null; private CapConfig config = null; private List> plugins = new ArrayList<>(); + private List pluginInstances = new ArrayList<>(); private AppCompatActivity activity; private Fragment fragment; private RouteProcessor routeProcessor; @@ -1403,6 +1444,16 @@ public Builder addPlugins(List> plugins) { return this; } + public Builder addPluginInstance(Plugin plugin) { + this.pluginInstances.add(plugin); + return this; + } + + public Builder addPluginInstances(List plugins) { + this.pluginInstances.addAll(plugins); + return this; + } + public Builder addWebViewListener(WebViewListener webViewListener) { webViewListeners.add(webViewListener); return this; @@ -1452,6 +1503,7 @@ public Bridge create() { fragment, webView, plugins, + pluginInstances, cordovaInterface, pluginManager, preferences, diff --git a/android/capacitor/src/main/java/com/getcapacitor/PluginHandle.java b/android/capacitor/src/main/java/com/getcapacitor/PluginHandle.java index cb1bf448e7..955d8055bf 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/PluginHandle.java +++ b/android/capacitor/src/main/java/com/getcapacitor/PluginHandle.java @@ -16,7 +16,7 @@ public class PluginHandle { private final Bridge bridge; private final Class pluginClass; - private Map pluginMethods = new HashMap<>(); + private final Map pluginMethods = new HashMap<>(); private final String pluginId; @@ -28,9 +28,9 @@ public class PluginHandle { private Plugin instance; @SuppressWarnings("deprecation") - public PluginHandle(Bridge bridge, Class pluginClass) throws InvalidPluginException, PluginLoadException { + private PluginHandle(Class clazz, Bridge bridge) throws InvalidPluginException { this.bridge = bridge; - this.pluginClass = pluginClass; + this.pluginClass = clazz; CapacitorPlugin pluginAnnotation = pluginClass.getAnnotation(CapacitorPlugin.class); if (pluginAnnotation == null) { @@ -57,11 +57,20 @@ public PluginHandle(Bridge bridge, Class pluginClass) throws I this.pluginAnnotation = pluginAnnotation; } - this.indexMethods(pluginClass); + this.indexMethods(clazz); + } + public PluginHandle(Bridge bridge, Class pluginClass) throws InvalidPluginException, PluginLoadException { + this(pluginClass, bridge); this.load(); } + public PluginHandle(Bridge bridge, Plugin plugin) throws InvalidPluginException { + this(plugin.getClass(), bridge ); + this.loadInstance(plugin); + } + + public Class getPluginClass() { return pluginClass; } @@ -94,16 +103,21 @@ public Plugin load() throws PluginLoadException { try { this.instance = this.pluginClass.newInstance(); - this.instance.setPluginHandle(this); - this.instance.setBridge(this.bridge); - this.instance.load(); - this.instance.initializeActivityLaunchers(); - return this.instance; + return this.loadInstance(instance); } catch (InstantiationException | IllegalAccessException ex) { throw new PluginLoadException("Unable to load plugin instance. Ensure plugin is publicly accessible"); } } + public Plugin loadInstance(Plugin plugin) { + this.instance = plugin; + this.instance.setPluginHandle(this); + this.instance.setBridge(this.bridge); + this.instance.load(); + this.instance.initializeActivityLaunchers(); + return this.instance; + } + /** * Call a method on a plugin. * @param methodName the name of the method to call From b89c6ea665fe1932d1583d9effa2e39ac313c905 Mon Sep 17 00:00:00 2001 From: Steven Sherry Date: Fri, 11 Nov 2022 12:16:29 -0600 Subject: [PATCH 2/2] chore(android): Run formatter --- .../capacitor/src/main/java/com/getcapacitor/Bridge.java | 8 ++++---- .../src/main/java/com/getcapacitor/PluginHandle.java | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java index 4829ec18d6..5512d0fc36 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java @@ -670,10 +670,10 @@ private String pluginName(Class clazz) { private void logInvalidPluginException(Class clazz) { Logger.error( - "NativePlugin " + - clazz.getName() + - " is invalid. Ensure the @CapacitorPlugin annotation exists on the plugin class and" + - " the class extends Plugin" + "NativePlugin " + + clazz.getName() + + " is invalid. Ensure the @CapacitorPlugin annotation exists on the plugin class and" + + " the class extends Plugin" ); } diff --git a/android/capacitor/src/main/java/com/getcapacitor/PluginHandle.java b/android/capacitor/src/main/java/com/getcapacitor/PluginHandle.java index 955d8055bf..2e520b3a4e 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/PluginHandle.java +++ b/android/capacitor/src/main/java/com/getcapacitor/PluginHandle.java @@ -66,11 +66,10 @@ public PluginHandle(Bridge bridge, Class pluginClass) throws I } public PluginHandle(Bridge bridge, Plugin plugin) throws InvalidPluginException { - this(plugin.getClass(), bridge ); + this(plugin.getClass(), bridge); this.loadInstance(plugin); } - public Class getPluginClass() { return pluginClass; }