【问题标题】:android Cannot run Java function from Javascriptandroid无法从Javascript运行Java函数
【发布时间】:2018-06-28 13:09:38
【问题描述】:

在我的项目中,我有一个 WebView,它加载了一个页面 (HTML)。 我想更改所有图像并在用户单击任何图像时显示祝酒词。

所以我添加了调用 Java 函数的 javascript 代码:

// 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 类:

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() 应该在什么时候调用

  1. 页面已完成加载

  2. 用户点击了图片

问题:showToast() 仅被调用一次 - 当页面完成加载时。 当用户点击图片时,showToast() 不会被调用,而是出现以下日志:

未捕获的类型错误:无法读取未定义的属性“showToast””, 来源:

问题

点击图片时如何调用showToast()

【问题讨论】:

  • 这绝对是你会做的事情(假设第一个电话有效,如你所说)。与您的真实代码相比,您是否过于简化了示例(如果这不是您的真实代码)?具体来说,在您的真实代码中,您是否在事件处理程序中使用i?因为那将是this problem
  • T.J. Crowder:其实我并没有简化代码——我已经剪切和粘贴了。
  • 在这种情况下,您需要查看自页面加载和点击后发生的变化。错误消息告诉您window.JSInterface 是(现在)undefined,而之前它具有不同的值(对您的对象的引用)。出于某种原因,情况发生了变化。我认为我们无法从上面的问题中看出 什么 发生了变化,但这就是您想要寻找的。​​span>

标签: javascript android


【解决方案1】:

我不知道为什么,但您可以通过在加载 HTML 内容之前添加 JavaScript 界面来解决此问题。

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(); ");
    }
});

【讨论】:

    【解决方案2】:

    删除 evaluateJavascript 方法并使用 loadUrl。试试下面的代码它对我有用:-

    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");
    

    界面:-

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

    【讨论】:

      【解决方案3】:

      您似乎没有&lt;img&gt; 标签 尝试先添加它们并检查

      安卓功能

      WebView webView= findViewById(R.id.webview);
          JavaScriptInterface jsInterface = new JavaScriptInterface(this);
          webView.getSettings().setJavaScriptEnabled(true);
          webView.addJavascriptInterface(jsInterface, "JSInterface");
      
          webView.evaluateJavascript(
      
                  "document.write('<img>');" +
                          "document.write('<img>');\n"+
                          "var x = document.getElementsByTagName('IMG');" +
                          "console.log(x.length);"+
                          "for (var i = 0; i < x.length; i++) {" +
                          "x[i].src = 'https://www.imagemagick.org/Usage/images/badge_overlay.png';" +
                          "x[i].addEventListener('click', function() {" +
                          "window.JSInterface.showToast(); " +    // <-- now calling :)
                          "});" +
                          "} " +
                          "window.JSInterface.showToast();"   // <-- is called
                  , null);
      

      或者您可以先从资产加载 html 内容。 webView.loadUrl();

      【讨论】:

        【解决方案4】:

        您无需在 dom 级别等待图像出现。

         string code = `
             document.addEventListener("click",(e)=> {
                if(e.target instanceof Image){
                    window.JSInterface.showToast();
                }
             });`
         webView.evaluateJavascript(code, null);
        

        在这个例子中,我使用了字符串文字 => https://stackoverflow.com/a/50155171/5138198

        【讨论】:

          【解决方案5】:

          您是否尝试过在实际调用 Java 的地方使用 Javascript 函数并将其放置在与 webview 相关的 html 页面中。将它放在标题中,以便稍后发生单击事件时它会明确存在,并且在对功能进行任何评估后不会消失,就像您现在的情况一样。

          <script type="text/javascript">
              function showAndroidToast(toast) {
                  JSInterface.showToast(toast);
              }
          </script>
          

          我发现的类似案例的来源总是指单独的 html:

          [1]Toast does not work in webview

          [2]Android WebView showToast onButtonClick

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-09
            相关资源
            最近更新 更多