I need to retrieve information from my PWA in response to system events (Android but maybe iOS one day too).
I already have the native code to respond to the Android “Activity” (if that’s the right term) and have my PWA successfully hosted by Capacitor and able to load a custom plugin (I’m just implementing it within the main project for simplicity).
I’m now stuck on a couple of details:
The notifyListeners("myPluginEvent", ret); statement in the plugin documentation can’t be invoked from a static method but I don’t see how to get hold of the instance that Capacitor is using so I can’t see how to send an event to the web app.
I can’t find any documentation about how to respond to the event with some data - it looks like this communication approach is “fire and forget”. Am I overlooking something?
Assuming that (1) is solvable then for (2) I guess I can implement some sort of async communication channel via events and plugin calls by tracking some unique IDs but this seems pretty hacky so I want to get some expert opinions first.
The 1 is not clear, why do you want to use it from a static method in first place?
For 2, events are “fire and forget”, if you set a listener for the event then you can call to a native method to communicate back or do whatever you want.
Maybe what you want is the callback return instead of events, see Geolocation plugin’s watchPosition as example, or if you want to respond to activity results you can check camera plugin, you don’t need events or callbacks for that.
I just want to use it - I don’t mind whether it’s from static or an instance but since I can’t see any way to get the instance that Capacitor magically creates during initialisation (e.g. below), I figured that a static call might be an option.
...
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
// This is the only place MyPlugin is referenced so I have
// no idea how to get the relevant instance after this point
add(MyPlugin.class);
}});
}
...
Thanks for the suggestions. I think I need an activity “request” rather than a result but I’ll dig into the Camera plugin code in case that provides inspiration or even just a better understanding of these terms.
The watchPosition example looks interesting; so does the CallbackID approach used in the BackgroundTask plugin since that’s similar to what I was thinking might be my implementation approach if Capacitor doesn’t offer a generalised communication method that keeps track of callback IDs across asynchronous system-initiated events/activities/messages. I’m increasingly thinking it does not offer this feature because otherwise why would the BackgroundTask API require the hosted web code to manually track the callback ID and pass it back to the finish method when its async work is complete? I’ve run out of time today but will keep investigating and hopefully get my head around the API soon.
Also, from MainActivity.java you can use the bridge object to fire javascript events with this.bridge.triggerDocumentJSEvent, this.bridge.triggerWindowJSEvent and this.bridge.triggerJSEvent methods without a plugin.
Thanks. I’m sure that code sample will be useful in future.
Just to round off this topic, I have now learnt that Capacitor only works when the main Activity is active - the bridged WebView does not keep running while the Activity is paused/stopped. Since Android can’t activate additional Activities when another app is in the foreground, my immediate use for responding with data to system events (specifically via the AutoFillService) is invalid and I’ll instead need to develop some native code entirely unrelated to Capacitor.
So it’s totally my fault for not understanding some of the basics of Android application structure until now. Still, perhaps it’s interesting to see that these fundamental rules of Android apps can sometimes be unknown to developers whose first introduction to creating a mobile app is through the Capacitor getting started guide.