Delphian
Delphian

Reputation: 1760

Return the button text from Javascript to Java using WebView

I need to read text on the button which is located on the website. I tried to parse the page using JSOUP, but JSOUP doesn't see Javascript object. That is why I decide to use WebView to read text. But it doesn't work. I need to return the button text from Javascript to Java. Is it possible?

 public class MainActivity extends AppCompatActivity {

    WebView mWebView;
    Button mButton, mClick;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mWebView = (WebView) findViewById(R.id.web_view);
        mButton = (Button) findViewById(R.id.start_URL);
        mClick = (Button) findViewById(R.id.click);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mWebView.getSettings().setJavaScriptEnabled(true);
                mWebView.getSettings().setUseWideViewPort(true);
                mWebView.getSettings().setLoadWithOverviewMode(true);
                mWebView.getSettings().setDomStorageEnabled(true);
                mWebView.setWebViewClient(new PersonalWebView());
                mWebView.setWebChromeClient(new PersonalWebChrome());
                mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
                mWebView.loadUrl(URL);

             mClick.setOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
                 mWebView.loadUrl("javascript: window.JSInterface.callFromJS('buttonText')");}
    }

    private class JavaScriptInterface {

        @JavascriptInterface
        public void callFromJS(String buttonText) {
            Log.d("JScript","callFromJS "+ buttonText);
        }
    }

    private class PersonalWebView extends WebViewClient{
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
        }
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            super.onReceivedError(view, request, error);
        }
    }


    private class PersonalWebChrome extends WebChromeClient {

        private PersonalWebChrome() {
            super();
        }

        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            return super.onJsAlert(view, url, message, result);
        }
    }     
      @Override                                                                                  
    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
        Log.d("TAG", consoleMessage.message()+" "+consoleMessage.sourceId());
        return super.onConsoleMessage(consoleMessage);
    }
}

I tried to change code, but it doesn't work:

    mClick.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
                 ValueCallback<String> result = new ValueCallback<String>() {
                     @Override
                     public void onReceiveValue(String value) {
                         Log.d("TAG", value);
                     }
                 };                                                     
  mWebView.evaluateJavascript("javascript: window.JSInterface.callFromJS('buttonText')",result);}}     

In the Log I see:

D/TAG: Uncaught TypeError: Cannot read property 'callFromJS' of undefined

Upvotes: 0

Views: 238

Answers (2)

Mikhail Naganov
Mikhail Naganov

Reputation: 6861

This is not the correct way of dealing with injected Java objects:

mWebView.addJavascriptInterface(new JavaScriptInterface(), "javaCallback");
mWebView.loadUrl("javascript:window.javaCallback.callFromJS('buttonText')";

Injected objects only become "visible" on the next page load after calling addJavascriptInterface. Loading javascript: URIs doesn't count as a page load.

Check out the sample from the docs:

webView.addJavascriptInterface(new JsObject(), "injectedObject");
webView.loadData("", "text/html", null);
webView.loadUrl("javascript:alert(injectedObject.toString())");

The loadData in between is what actually makes the object to be inserted. You can as well use loadUrl but it needs to be a real page (from the network, assets, about:blank, whatever), but not a javascript: URI.

Upvotes: 1

Vladyslav Matviienko
Vladyslav Matviienko

Reputation: 10871

The problem should be in trying to call callFromJS method before registering interface. You register the JS interface only on the button click:

mClick.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
             }
}

But you try to call the callFromJS immediately.

Instead of doing this, move your mWebView.evaluateJavascript("javascript: window.JSInterface.callFromJS('buttonText')",result); inside onClick()

Upvotes: 0

Related Questions