3

WebView在本机应用程序中使用了很多 JavaScript。如果 JS 端想调用原生函数,使用JavaScriptInterface. 但是,如果 native 想要调用 JS 函数,就不是那么容易了。到目前为止,我已经尝试了两种解决方案:

  • 使用 URL调用loadUrl方法javascript:something()- 不可接受,因为当用户在键盘上键入WebView内容时,函数执行后将其隐藏
  • String每 x 秒(由对象提供)向本机端询问函数并调用eval()结果 - 有时在设置间隔 1 秒后,我在 50-60 秒后收到这些请求!

我想知道是否还有其他方法可以完成这种通信模型。假设在 app 中创建本地Socket// HTTPsomething-else 服务器并为其授予访问权限WebView。我正在寻找如何(如果可能的话)做到这一点的任何提示。

4

2 回答 2

3

我有以下代码,它使用 java 反射从 Java 调用 JavaScript。它避免了以下 loadUrl 错误: 1. 当您将焦点放在输入中时,loadUrl 可能会隐藏键盘。2. loadUrl 不能调用太频繁。

希望这会有所帮助:

public class AdvancedWebView extends WebView {
    private static final int EXECUTE_JS = 194;
    Method sendMessageMethod;
    Object webViewCore;
    boolean initFailed = false;;
    InputMethodManager imm;


    public AdvancedWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        this.getSettings().setJavaScriptEnabled(true);
        this.initReflection();
    }

    @SuppressWarnings("rawtypes")
    private void initReflection() {
        Object webViewObject = this;
        Class webViewClass = WebView.class;
        try {
            Field f = webViewClass.getDeclaredField("mProvider");
            f.setAccessible(true);
            webViewObject = f.get(this);
            webViewClass = webViewObject.getClass();
        } catch (Throwable e) {
            // mProvider is only required on newer Android releases.
        }       

        try {
            Field f = webViewClass.getDeclaredField("mWebViewCore");
            f.setAccessible(true);
            webViewCore = f.get(webViewObject);
            if (webViewCore != null) {
                sendMessageMethod = webViewCore.getClass().getDeclaredMethod("sendMessage", Message.class);
                sendMessageMethod.setAccessible(true);      
                System.out.println("sendMessageMethod-----"+sendMessageMethod);
            }
            hasIntercepted = true;
        } catch (Throwable e) {
            hasIntercepted = false;
            //Log.e(LOG_TAG, "PrivateApiBridgeMode failed to find the expected APIs.", e);
        }finally{
            if(sendMessageMethod == null)
            {
                hasIntercepted = false;
            }
        }
    }

    private void loadJs(String url) {
        if (sendMessageMethod == null && !initFailed) {
            initReflection();
        }
        // webViewCore is lazily initialized, and so may not be available right away.
        if (sendMessageMethod != null) {
            //String js = popAndEncodeAsJs();
            Message execJsMessage = Message.obtain(null, EXECUTE_JS, url);
            try {
                sendMessageMethod.invoke(webViewCore, execJsMessage);
            } catch (Throwable e) {
                //Log.e(LOG_TAG, "Reflection message bridge failed.", e);
            }
        }
    }
}
于 2013-06-01T07:46:01.050 回答
1

我不知道如何使备用通信模型正常工作,但我想我已经找到了 loadUrl-hides-the-keyboard 问题的解决方法:https ://stackoverflow.com/a/18776064/513038 。这有帮助吗?

于 2013-09-19T02:57:12.853 回答