天天看点

Cordova项目中,Android端访问远程网站调用Cordova插件

最近的Cordova项目中,采用了将前端项目放到服务器,App直接跳转到链接的方式开发。这样的目的是为了能频繁的更新,而不用发布新的版本。但是在开发中,前端项目调用本地的Cordova插件却出了问题,困扰了我好几天,不过最终还算是成功解决了,下面来分享一下正确姿势(如何在Cordova中打开远程链接,就不再多说,如需了解,可自行百度)。

Cordova项目中,Android端访问远程网站调用Cordova插件

首先呢,在前端项目的index.html中添加如下的js引用,来加载cordova.js:

<script src="http://injection/www/cordova.js" type="text/javascript" charset="UTF-8"></script>
           

然后编辑Android工程

CordovaLib/src/org/apache/cordova/engine/

目录下的

SystemWebViewClient.java

,添加如下代码:

private static final String INJECTION_TOKEN = "http://injection/";
           

找到

shouldInterceptRequest

方法,添加如下代码:

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {

        // --------------新增------------------
        if (url != null && url.contains(INJECTION_TOKEN)) {
            String assetPath = url.substring(url.indexOf(INJECTION_TOKEN) + INJECTION_TOKEN.length(), url.length());

            try {
                return new WebResourceResponse(
                        "application/javascript",
                        "UTF-8",
                        view.getContext().getAssets().open(assetPath));
            } catch (IOException e) {
                e.printStackTrace();
                return new WebResourceResponse("text/plain", "UTF-8", null);
            }

        }
        // --------------end------------------
        try {
            // Check the against the whitelist and lock out access to the WebView directory
            // Changing this will cause problems for your application
            if (!parentEngine.pluginManager.shouldAllowRequest(url)) {
                LOG.w(TAG, "URL blocked by whitelist: " + url);
                // Results in a 404.
                return new WebResourceResponse("text/plain", "UTF-8", null);
            }
            ...
        }
    }
           

这几步的操作,是为了拦截webview的请求,实现加载本地的cordova.js。

最后就是在前端js中去调用插件了,我们采用

cordova.exec()

的方式去调用插件,但是在调用之前,需在import语句后添加如下声明:

declare let cordova: any;
           

因为在TypeScript中直接调用

cordova.exec()

会报错。

至此,便完成了Cordova项目访问远程网站调用Cordova插件,如有疑问可留言。

Cordova项目中,Android端访问远程网站调用Cordova插件

本文参考:(https://blog.csdn.net/ducp123/article/details/79768020#commentBox)

补充

经过测试发现,上面的方法会导致页面卡顿,所以采用了新的方式,如下。

放弃在前端页面声明script标签的方式,改为Android端在页面加载中注入script标签的方式。在

SystemWebViewClient

中添加如下代码:

public void onPageFinished(WebView view, String url) {
    ...
    ...

     //-------------新增------------
    // isCordovaInject标示是否注入script标签,避免重复注入
    if (!isCordovaInject && url.startsWith("这里为需要打开的链接地址,避免添加过早而不起作用")) {
        Log.e(TAG, "----------------inject cordova.js--------------");
        String jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document)";
        //在InAppBrowser WebView中注入一个对象(脚本或样式)。
        injectDeferredObject(view, INJECTION_TOKEN + "www/cordova.js", jsWrapper);
        isCordovaInject = true;
    }
    //-------------end------------

}
           

注入script标签的方法:

private void injectDeferredObject(WebView webView, String source, String jsWrapper) {
        if (webView != null) {
            String scriptToInject;
            if (jsWrapper != null) {
                org.json.JSONArray jsonEsc = new org.json.JSONArray();
                jsonEsc.put(source);
                String jsonRepr = jsonEsc.toString();
                String jsonSourceString = jsonRepr.substring(1, jsonRepr.length() - 1);
                scriptToInject = String.format(jsWrapper, jsonSourceString);
            } else {
                scriptToInject = source;
            }
            final String finalScriptToInject = scriptToInject;
            this.parentEngine.cordova.getActivity().runOnUiThread(new Runnable() {
                @SuppressLint("NewApi")
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
                        // This action will have the side-effect of blurring the currently focused element
                        webView.loadUrl("javascript:" + finalScriptToInject);
                    } else {
                        webView.evaluateJavascript(finalScriptToInject, null);
                    }
                }
            });
        } else {
            LOG.d(TAG, "Can't inject code into the system browser");
        }
    }
           

这下应该不会导致卡顿了!