如何在 Android 7 中在 Webview 加载 HTML 前注入 JavaScript 脚本

7

我将提供一个修改过的例子来简化这个问题,但是本质上对于我的完整示例来说是相同的:

我需要在webview中加载一段HTML代码,这段代码假设已经声明了一些JavaScript函数。以下是示例HTML代码:

<html>
<body><h1>JavaScript Math.random()</h1>
<p>A random number:</p>
<p id="demo"></p>
<script>showRandomValue();</script>
</body>
</html>

在这个例子中,代码假设已经声明了一个名为 showRandomValue() 的函数。因此,在代码执行之前,我需要注入这个函数。以下是我想要注入的函数:
<script>
function showRandomValue() {
           document.getElementById("demo").innerHTML = Math.random();
      }
</script>

到目前为止,我一直在加载代码之前在webview中执行以下操作:

public static final String JAVASCRIPT_FUNCTION = 
        "javascript:function showRandomValue() {\n" +
        "           document.getElementById(\"demo\").innerHTML = Math.random();\n" +
        "      }";
webView.loadUrl(JAVASCRIPT_FUNCTION);
webView.loadData(HTML_CODE, "text/html", "UTF-8");

这对我很有帮助,直到我想将 targetSdkVersion 更新到 24。如果我设置了 targetSdkVersion 24 ,这段代码就无法工作,因为当代码加载时,函数找不到。
在修订 Android WebView 文档时,我发现了以下内容:
兼容性注意事项。针对 N 或更高版本的应用程序,从空 WebView 加载页面(如 loadUrl(String))时,不再持久保存 JavaScript 状态。例如,在调用 loadUrl(String) 之前定义的全局变量和函数将不存在于加载的页面中。应用程序应改用 addJavascriptInterface(Object, String),以便在导航过程中持续保存 JavaScript 对象。
我的问题是,使用 addJavascriptInterface 可以声明一个自定义对象,所以我可以声明:
webview.addJavascriptInterface(new MyInterface(),"javaInterface");

你需要使用javaInterface.getRandomValue()调用其方法,但是我无法通过这种方法声明全局函数。

重要提示: 我不能编辑或修改HTML代码,因为它来自第三方服务器。

如何使此代码在Android 7+中再次工作?

如果您想测试,请使用以下完整示例代码:

public class MainActivity extends Activity {

    private WebView webView;
    String HTML_CODE = "<html>\n" +
            "<body><h1>Hello World</h1>\n" +
            "<p>A random number:</p>\n" +
            "<p id=\"demo\"></p>\n" +
            "<script>showRandomValue();</script>\n" +
            "</body>\n" +
            "</html>";

    public static final String JAVASCRIPT_FUNCTION = "(function showRandomValue() {document.getElementById(\"demo\").innerHTML = Math.random();})";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = (WebView) findViewById(R.id.webview);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.loadUrl("javascript:" + JAVASCRIPT_FUNCTION);
        webView.loadData(HTML_CODE, "text/html", "UTF-8");
    }    
}

如果使用targetSdkVersion 23编译此代码,将会起作用;但是如果使用targetSdkVersion 24编译,则无法显示随机数。


你的minSdk是多少? - Kirill
如果您在应用程序代码和服务器代码中进行更改,那么JavaScriptInterface似乎会完美地为您工作。如果无法对服务器代码进行更改,那么我认为您现在没有任何可用的解决方案。您可以尝试向Google报告此问题。 - Amrut Bidri
1个回答

0

我知道你说过不能修改HTML...但是如果你使用预取内容的loadData函数,我不认为有任何理由反对在脚本标签中将所需的函数注入到html头部。总之,你所做的事情已经有点hacky了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接