In my project I have a WebView
which loads a page (HTML).
I want to change all images and show a toast when a user clicks on any image.
So I'm adding javascript code which calls Java function:
// code is inside onPageFinished(..) function
JavaScriptInterface jsInterface = new JavaScriptInterface(activity);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(jsInterface, "JSInterface");
webView.evaluateJavascript(
"var imgs = document.getElementsByTagName('img');" +
"for (var i = 0; i < imgs.length; i++) {" +
"imgs[i].src = 'file:///android_asset/rules_images_placeholder.png';" +
"imgs[i].addEventListener('click', function() {" +
"window.JSInterface.showToast(); " + // <-- isn't called: see logs
"});" +
"} " +
"window.JSInterface.showToast();" // <-- is called
, null);
JavaScriptInterface class:
public class JavaScriptInterface {
private Activity activity;
public JavaScriptInterface(Activity activity) {
this.activity = activity;
}
@JavascriptInterface
public void showToast() {
Toast.makeText(activity, "Toast message", Toast.LENGTH_SHORT).show();
}
}
showToast()
should be called when
page has finished loading
user has clicked on image
Problem: showToast()
is called only once - when page has finished loading.
When the user clicks on image, showToast()
isn't called, instead the following log appears:
Uncaught TypeError: Cannot read property 'showToast' of undefined", source:
Question
How to call showToast()
on image click?
I am not sure why, but you can fix this problem by adding a JavaScript interface prior to loading your HTML content.
jsInterface = new JavaScriptInterface(activity);
fragmentWebView.getSettings().setJavaScriptEnabled(true);
fragmentWebView.getSettings().setDomStorageEnabled(true);
fragmentWebView.addJavascriptInterface(jsInterface, "JSInterface");
fragmentWebView.loadDataWithBaseURL("file:///android_asset/", fullHtml, "text/html", "utf-8", null);
fragmentWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl(
"javascript:var imgs = document.getElementsByTagName('img');" +
"for (var i = 0; i < imgs.length; i++) {" +
"imgs[i].src = 'file:///android_asset/rules_images_placeholder.png';" +
"imgs[i].addEventListener('click', function(e) {" +
"window.JSInterface.showToast(); " +
"});" +
"}" +
"console.log(window.JSInterface);" +
"window.JSInterface.showToast(); ");
}
});
Remove the evaluateJavascript methoad and use loadUrl. Try the below code its working for me:-
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
}
@Override
public void onPageFinished(final WebView view, String url) {
Log.e("checking", "MYmsg");
webView.loadUrl("javascript: var imgs = document.getElementsByTagName('img');" +
"for (var i = 0; i < imgs.length; i++) {" +
"imgs[i].addEventListener('click', function() {" +
"window.CallToAnAndroidFunction.showToast(); " +
"});" +
"} " );
}
});
webView.addJavascriptInterface(new WebAppInterface(Main2Activity.this),
"CallToAnAndroidFunction");
Interface:-
public class WebAppInterface {
Context mContext;
/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
}
/** Show a toast from the web page */
@JavascriptInterface
public void showToast() {
Toast.makeText(mContext, "Toast message", Toast.LENGTH_SHORT).show();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With