I have a hosted, CMS-based web app that I want to package as an Android / iOS app with Ionic Capacitor. So I added
"server": {
"url": "https://my.domain/"
},
to capacitor.config.json and did
import { Capacitor, Plugins } from '@capacitor/core';
console.log('Plugins', Capacitor.Plugins);
in the main Javascript file of my app (I use webpack for bundling). This basically works, i.e. the app gets loaded and displayed properly. But on the console I see that Capacitor loads the web versions of the plugins, and Device.getInfo()
says that the platform is "web", not "android".
How can I make Capacitor act like it would when my app was loaded from the device's file system, and in particular how can I make it use the native versions of the plugins in this setup?
As it turned out, the reason for my troubles where that my pages had an active service worker. Capacity uses WebViewClient::shouldInterceptRequest for injecting the Javascript code that initializes the bridge to the native world, and Android does not call this callback for requests that a service worker handles. Instead, it has a separate callback for these requests that is available via a ServiceWorkerController.
So what I did was creating my own tiny plugin:
@NativePlugin
public class ServiceWorker extends Plugin {
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void load() {
ServiceWorkerController swController = ServiceWorkerController.getInstance();
swController.setServiceWorkerClient(new ServiceWorkerClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebResourceRequest request) {
return bridge.getLocalServer().shouldInterceptRequest(request);
}
});
}
}
and then it worked as expected. (I also had to add the getter for localServer to the Bridge class.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With