Cordova-plugin-ionic-webview: Consider replacing WebViewLocalServer with WebViewAssetLoader

Created on 2 Dec 2019  Â·  3Comments  Â·  Source: ionic-team/cordova-plugin-ionic-webview

I'm an engineer on the Android WebView team. It recently came to my attention that you're using WebViewLocalServer (probably forked from https://github.com/google/webview-local-server).

Instead of forking this class, we strongly recommend using https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader, which will do most of the heavy lifting for you, and will be maintained as part of our AndroidX library. If this isn't a suitable replacement, we welcome any feedback on our bug tracker.

CC @HazemSamir (the author of WebViewAssetLoader).

Most helpful comment

@jcesarmobile
I have made a small test with WebViewAssetLoader.

Have enabled AndroidX like described here (doesn't seem to make a problem by the way)
and implemented the following test code

    setContentView(com.getcapacitor.android.R.layout.bridge_layout_main);
    webView = findViewById(com.getcapacitor.android.R.id.webview);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setDomStorageEnabled(true);
    webView.getSettings().setGeolocationEnabled(true);
    webView.getSettings().setDatabaseEnabled(true);
    webView.getSettings().setAppCacheEnabled(true);
    webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
    webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);

    WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
      // ---- Path handler
      // Default path handler not working
      // .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this))
      // .addPathHandler("/res/", new WebViewAssetLoader.ResourcesPathHandler(this))
      //  => implementing custom handler
      .addPathHandler("/", new WebViewAssetLoader.PathHandler() {
        @Override
        public WebResourceResponse handle(String path) {
          try {
            if (path.isEmpty())
              path = "index.html";
            InputStream is = getAssets().open("public/" + path);
            String mimeType = AssetHelper.guessMimeType(path);

            return new WebResourceResponse(mimeType, null, is);
          } catch(Exception e) {
          }
          return null;
        }
      })
      // ----
      .build();
    webView.setWebViewClient(new WebViewClient() {
      @Override
      public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        // return super.shouldInterceptRequest(view, request);
        return assetLoader.shouldInterceptRequest(request.getUrl());
      }
    });

    // webView.loadUrl("file:///android_asset/public/index.html");
    webView.loadUrl("https://appassets.androidplatform.net/");

The App seems to be working.
Of course the native part won't work as the plugins aren't bound etc.
But maybe you can take this as base.

All 3 comments

Cordova doesn’t support android x yet, so we can’t use android x libraries without forcing users to install a few plugins that make android x possible and that can cause issues with other plugins.

Can the WebViewAssetHandler intercept just “/“? It’s not clear from the docs and fro angular routing and some other frameworks the apps should be served from the root

Yeah, just pass "/" to addPathHandler. This will let you intercept requests to https://some.origin/foo.html or https://some.origin/index.html. However, AssetLoader doesn't do anything special when you load a URL which ends in "/", so https://some.origin/ will not load the index.html file in the corresponding folder. We have a feature request for this at https://issuetracker.google.com/issues/144925597.

@jcesarmobile
I have made a small test with WebViewAssetLoader.

Have enabled AndroidX like described here (doesn't seem to make a problem by the way)
and implemented the following test code

    setContentView(com.getcapacitor.android.R.layout.bridge_layout_main);
    webView = findViewById(com.getcapacitor.android.R.id.webview);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setDomStorageEnabled(true);
    webView.getSettings().setGeolocationEnabled(true);
    webView.getSettings().setDatabaseEnabled(true);
    webView.getSettings().setAppCacheEnabled(true);
    webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
    webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);

    WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
      // ---- Path handler
      // Default path handler not working
      // .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this))
      // .addPathHandler("/res/", new WebViewAssetLoader.ResourcesPathHandler(this))
      //  => implementing custom handler
      .addPathHandler("/", new WebViewAssetLoader.PathHandler() {
        @Override
        public WebResourceResponse handle(String path) {
          try {
            if (path.isEmpty())
              path = "index.html";
            InputStream is = getAssets().open("public/" + path);
            String mimeType = AssetHelper.guessMimeType(path);

            return new WebResourceResponse(mimeType, null, is);
          } catch(Exception e) {
          }
          return null;
        }
      })
      // ----
      .build();
    webView.setWebViewClient(new WebViewClient() {
      @Override
      public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        // return super.shouldInterceptRequest(view, request);
        return assetLoader.shouldInterceptRequest(request.getUrl());
      }
    });

    // webView.loadUrl("file:///android_asset/public/index.html");
    webView.loadUrl("https://appassets.androidplatform.net/");

The App seems to be working.
Of course the native part won't work as the plugins aren't bound etc.
But maybe you can take this as base.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

acollazomayer picture acollazomayer  Â·  3Comments

50l3r picture 50l3r  Â·  7Comments

begbeder picture begbeder  Â·  5Comments

mowaiskalam picture mowaiskalam  Â·  6Comments

lincolnthree picture lincolnthree  Â·  7Comments