Reputation: 1760
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
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
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