0

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

1
  • I deleted mWebView.loadUrl(url) from mButton onnClick and it's work. Сorrected the example. Commented Dec 5, 2016 at 15:11

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Mikhail, thank you! It works great! I changed my example.
0

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()

1 Comment

thank you, EvaluateJavascript method is located inside onClick(). I missed the closing brace.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.