【问题标题】:Listen to javascript function invocation from java - Android收听来自 java - Android 的 javascript 函数调用
【发布时间】:2012-03-07 14:04:53
【问题描述】:

我在服务器上托管了一些 HTML5/javascript 文件。当在 HTML5 页面上单击一个按钮时,将调用一个 javascript 函数。我想监听何时调用函数并获取函数返回的 json。以前我在设备上打开了一个端口,但这似乎不适用于 Android 3.0。我听说你可以使用external interface来监听javascript调用,但我不知道如何实现。

【问题讨论】:

  • 您是否在 WebView 中运行您的页面?

标签: android webview


【解决方案1】:

要使用外部接口,您需要在 WebView 中运行您的网站。以下解决方案也意味着,

  1. 您知道所有要拦截的函数名称,并且...
  2. 这些函数在 JS 代码的公共范围内。

要注册您的接口,您需要在您的WebView 实例上调用addJavascriptInterface 方法。您需要为其选择一个名称并创建一个实现。你的接口应该拦截函数调用并报告它们的结果,所以,让我们描述一下......

class FunctionCallInterceptor {
    public void reportCall(String functionName, String result) {
      // some code, handling interception
    }
}

并注册它...

mWebView.addJavascriptInterface(new FunctionCallInterceptor(), 'Interceptor');

有关 JavaScript 接口的更多信息,请参阅Binding JavaScript

然后您需要将函数结果“传输”到您的界面...这里您需要一些 JavaScript 代码。

function wrapFunc(name) {
  if(typeof window[name] == 'function') {  // If target is accessible
    var original = window['__' + name] = window[name];  // remember original one
    window[name] = function() {  // and replace with wrapper
        var result = original.apply(this, arguments); // call original                
        Interceptor.reportCall(name, result.toString()); // report to interceptor
        return result;  // return result as usual
    }
  }
}

要包装您的函数,请使用此代码

wrapFunc('myFunction'); // wraps myFunction in the source

另外,别忘了启用 JavaScript

mWebView.getSettings().setJavaScriptEnabled(true);

何时,如何将此代码嵌入到您的外部页面(我暗示您无法访问外部 JS 代码)...要在页面上下文中执行任意代码,您可以使用 WebViewloadUrl 方法

mWebView.loadUrl('javascript:some... js... code...');

这不会触发页面重新加载,只会执行 JavaScript。请注意页面完全加载后需要执行的操作。您可以通过以下代码获取:

mWebView.setWebViewClient(new WebViewClient {
    @Override
    public void onPageFinished (WebView view, String url) {
        // here page is loaded
    }
});

详情请参阅setWebViewClientonPageFinished

另请注意,通过loadUrl 调用转移到页面的代码不得包含换行符。所以你需要摆脱它们(通过 String.replace 左右)。

添加 所以,最终的解决方案是:

String wrapFuncCode = "function wrapFunc ...... "; // or maybe place it in resources?
mWebView.addJavascriptInterface(new FunctionCallInterceptor(), 'Interceptor');
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient {
    @Override
    public void onPageFinished (WebView view, String url) {
       // inject wrapper
       // don't forget to remove newline chars
       mWebView.loadUrl("javascript:" + wrapFuncCode.replace('\n', ''));

       // wrap all the functions needed
       String[] funcToWrap = new String[] { 'myFunc1', ... };
       for(String f : funcToWrap) {
           mWebView.loadUrl("javascript:wrapFunc('" + f + "myFunction');");  
       }  
    }
});

【讨论】:

  • 嗨,你能详细说明一下这个函数吗 wrapFunc(name) { if(typeof window[name] == 'function') { // 如果目标是可访问的 var original = window[' __' + 名称] = 窗口[名称]; // 记住原来的一个 window[name] = function() { // 并用包装器替换 var result = original.apply(this, arguments); // 调用原始 Interceptor.reportCall(name, result.toString()); // 向拦截器报告返回结果; // 像往常一样返回结果 } } } 和 wrapFunction('myFunction');我在哪里添加这段代码?
  • 是的......我在 webview 中运行我的页面,我知道我想要拦截的函数名称,是的,它们在 js 代码的公共范围内
  • 我添加了完整的解决方案。如果事情还不清楚,请提出一个具体的问题。
【解决方案2】:

我做了一个不同的方法,它很容易工作。我使用了 window.external.notify(String message)。 在我的java中,我使用了 webview.addJavascriptInterface(new JSInterface(),"external");在我的 JSInterface 类中,我创建了一个函数 public void notify(String messg).messg 包含我来自 javascript 的响应。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-03
    • 2012-10-05
    • 1970-01-01
    相关资源
    最近更新 更多