Android Web-View : Inject local Javascript file to Remote Webpage Android Web-View : Inject local Javascript file to Remote Webpage android android

Android Web-View : Inject local Javascript file to Remote Webpage


There is a way to 'force' the injection of your local Javascript files from local assets (e.g., assets/js/script.js), and to circumvent the 'Not allowed to load local resource : file:///android_assets/js/script.js ...' issue.

It is similar to what described in another thread (Android webview, loading javascript file in assets folder), with additional BASE64 encoding/decoding for representing your Javascript file as a printable string.

I am using an Android 4.4.2, API level 19 Virtual Device.

Here are some code snippets:

[assets/js/script.js]:

    'use strict';    function test() {       // ... do something    }    // more Javascript

[MainActivity.java]:

    ...    WebView myWebView = (WebView) findViewById(R.id.webView);    WebSettings webSettings = myWebView.getSettings();    webSettings.setJavaScriptEnabled(true);    webSettings.setAllowUniversalAccessFromFileURLs(true);    myWebView.setWebViewClient(new WebViewClient() {       @Override       public boolean shouldOverrideUrlLoading(WebView view, String url) {          return false;       }       @Override       public void onPageFinished(WebView view, String url) {          super.onPageFinished(view, url);          injectScriptFile(view, "js/script.js"); // see below ...          // test if the script was loaded          view.loadUrl("javascript:setTimeout(test(), 500)");       }       private void injectScriptFile(WebView view, String scriptFile) {          InputStream input;          try {             input = getAssets().open(scriptFile);             byte[] buffer = new byte[input.available()];             input.read(buffer);             input.close();             // String-ify the script byte-array using BASE64 encoding !!!             String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);             view.loadUrl("javascript:(function() {" +                          "var parent = document.getElementsByTagName('head').item(0);" +                          "var script = document.createElement('script');" +                          "script.type = 'text/javascript';" +             // Tell the browser to BASE64-decode the string into your script !!!                          "script.innerHTML = window.atob('" + encoded + "');" +                          "parent.appendChild(script)" +                          "})()");          } catch (IOException e) {             // TODO Auto-generated catch block             e.printStackTrace();          }       }    });    myWebView.loadUrl("http://www.example.com");    ...


loadUrl will work only in old version use evaluateJavascript

webview.evaluateJavascript("(function() { document.getElementsByName('username')[0].value='USERNAME';document.getElementsByName('password')[0].value='PASSWORD'; "+"return { var1: \"variable1\", var2: \"variable2\" }; })();", new ValueCallback<String>() {                @Override                public void onReceiveValue(String s) {                    Log.d("LogName", s); // Prints: {"var1":"variable1","var2":"variable2"}                }            });


Yes, you could use shouldInterceptRequest() to intercept remote url loading and return local stored content.

WebView webview = (WebView) findViewById(R.id.webview);webview.setWebViewClient(new WebViewClient() {    @Override    public WebResourceResponse shouldInterceptRequest (final WebView view, String url) {       if (url.equals("script_url_to_load_local")) {           return new WebResourceResponse("text/javascript", "UTF-8", new FileInputStream("local_url")));       } else {           return super.shouldInterceptRequest(view, url);       }    }});