Understanding Android webview javascript interface

25,887

Solution 1

TRY

You may try to make another object, which will retranslate calls to javascript interface.Implement onPageStarted method in WebViewClient , and inject javascript in onPageStarted method, in the following way.

 mWebView.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
        @Override
        public void onPageStarted (WebView view, String url, Bitmap favicon){
            String jsScript= "javascript:var functions_array = ['testNativeMethod'];";
                   jsScript+="var jsinterface = {};"
                   jsScript+="functions_array.map(function(id){"
                   jsScript+="jsinterface[id]= function() {"
                   jsScript+="try{return temp_obj[id].apply(temp_obj, arguments);}"
                   jsScript+="catch(e) { console.log('ERROR: ' + e + ', method ' + id);"
                   jsScript+="return false;}}})"
            view.loadUrl(jsScript);
        }
    });

Hope this helps :-)

Solution 2

Think about document in javascript. When you are in a web browser, this is a global object that you have access to at any point. If you make your own new var called document, you are going to have problems accessing the global document.

When you execute this line:

    mWebView.addJavascriptInterface(new testClass(), "jsinterface");

you are adding a global object called jsinterface. This is the same situation as document. If you create a var with the same name, it will overwrite the existing global reference.

Once you add a javascript interface to the WebView, you don't need to create a new reference to the interface. addJavascriptInterface has already done that for you.

Share:
25,887
Umair Anwar
Author by

Umair Anwar

I am a programmer. I build and ship things. I have mostly worked on the backend and also on the frontend. On the Backend, I have mostly worked using PHP and its MVC frameworks. Other than that, I have some experience with Java and .NET. On the frontend, I have worked in vanilla javascript and angularjs. I would also like to mention that I have mostly worked on AWS cloud. I have used services like EC2, RDS and S3. To know about me and my coworkers, please view my linkedin profile. https://www.linkedin.com/in/umair3

Updated on July 09, 2022

Comments

  • Umair Anwar
    Umair Anwar almost 2 years

    I have created an android WebView, and injected javascript interface using addJavascriptInterface(mObject, "jsinterface"). It works fine until I create an object with same name (jsinterface) in JavaScript using the new operator.

    My Java Code:

    WebView mWebView = findViewById(R.id.myWebView);
    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.setWebChromeClient(new MyWebChromeClient((Activity)mContext));
    mWebView.addJavascriptInterface(new testClass(), "jsinterface");
    mWebView.loadUrl("UrlToLoad");
    

    testClass.java

    public class testClass{
        public testClass() {
        }
    
        @JavascriptInterface
        public String testNativeMethod() {
            return "Java method called!!";
        }
    }
    

    My Java Script Code

    test.js

    function test(msg){
        this.message = msg;
    
        this.testJSMethod = function(){
            return this.message;
        }
    }
    
    alert(jsinterface.testNativeMethod()); // prints Java method called!!
    jsinterface= new test("JS method called...");
    alert(jsinterface.testJSMethod()); // prints JS method called...
    alert(jsinterface.testNativeMethod()); // errors "NPMethod called on non- NPObject"
    

    Problem:

    Is this possible for a javascript object to have access to both , i.e javascript methods and native JAVA methods(exposed to it via javascriptinterface) ? Is there any possibility of setting any property to webview OR executing any JS script to get this done?