Reputation: 1799
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?
Upvotes: 8
Views: 7977
Reputation: 10952
Anyone having similar problem I was able to solve by updating android/app/main/java/.../MainAcitivity.java
https://github.com/ionic-team/capacitor/issues/5278#issuecomment-1313531876
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ServiceWorkerController swController = ServiceWorkerController.getInstance();
swController.setServiceWorkerClient(new ServiceWorkerClient() {
@Nullable
@Override
public WebResourceResponse shouldInterceptRequest(WebResourceRequest request) {
if (request.getUrl().toString().contains("index.html")) {
request.getRequestHeaders().put("Accept", "text/html");
}
return bridge.getLocalServer().shouldInterceptRequest(request);
}
});
}
}
Also need to update minSdkVersion = 24
in android/variables.gradle
Upvotes: 0
Reputation: 12579
I'm dealing with a Capacitor v2 project that also requires to have in-app navigation to a remote website which uses custom Capacitor plugins that are hosted on the Capacitor wrapper. I was also testing with a local WebServer that can be reached at 10.0.2.2
(Android emulator to localhost). The accepted solution is not relevant anymore, the code was never reached, and it was not helpful, however I did some digging into the bridge itself.
My WebServer was hosted on port 8000 locally, so the Bridge failed to have an exact match of the url within the UrlMatcher and thus was returning no handler to progress the request to http://10.0.2.2:8000
in my wrapper.
I figured it would work when I put this into my capacitor.config.json
:
"server": {
"allowNavigation": [
"10.0.2.2",
"10.0.2.2:8000",
]
}
The first entry is to prevent capacitor from opening a new browser instead of launching it within the frame, the 2nd is to exact match the authority segment within the UrlMatcher. Maybe it was fixed in more recent versions, but for v2 this worked.
Upvotes: 0
Reputation: 1799
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.)
Upvotes: 11