cordova 远程h5页面调用本地js

malonely 2019-06-28

如何在本地webview打开 远程h5页面;

有的时候,想要在app上直接调试样式,功能等,但是每次修改后都要重新部署,很是麻烦,因此,参考各方文档后,了解到个人认为最优的解决方案,方案如下:

默认情况下打开远程h5页面会调用本地浏览器打开;所以我们需要在cofig.xml添加代码;

<allow-navigation href="http://*/*" />
    <allow-navigation href="https://*/*" />
    
    <content src="url">//这个是启动是打开的页面

第一步就完成了。

h5页面调用本地插件接口

方法一:首先本地先安装好插件,然后就是简单粗暴将cordova.js plugin等所有js文件一起放在服务器上。h5页面只需要引用cordova.js即可(所需文件在platforms/andriod/assets/www/)亦或(platforms/andriod/platform_www);这种方法缺点很多,比如下载的流量会增加,无法通过appstore审核;

方法二:上面的js文件是放在服务器上的,那么我们是不是可以直接让h5使用本地cordova.js等文件,这样就不存在重新下那么多js文件的问题了。

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

不过遇到了一个错误:
Not allowed to load local resource: file:///android_asset/www/cordova.js
意思是http协议下禁止通过file://方式访问本地的文件。

不过如果cordova app就是访问的file://android_asset/www/index.html的话,加载其它file://资源是没问题的。

这是webview的一种安全机制。

解决办法是,通过拦截webview的请求,实现加载本地js,具体如下:

打开platforms/andriod/CordovaLibsrcorgapachecordovaengineSystemWebViewClient.java

public void clearAuthenticationTokens() {
    this.authenticationTokens.clear();
}

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

@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 {
            WebResourceResponse response = new WebResourceResponse(
                    "application/javascript",
                    "UTF8",
                    view.getContext().getAssets().open(assetPath)
            );
            return response;
        } catch (IOException e) {
            e.printStackTrace(); // Failed to load asset file
            return new WebResourceResponse("text/plain", "UTF-8", null);
        }
    }
    ---新增---
    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);
        }

        CordovaResourceApi resourceApi = parentEngine.resourceApi;
        Uri origUri = Uri.parse(url);
        // Allow plugins to intercept WebView requests.
        Uri remappedUri = resourceApi.remapUri(origUri);

        if (!origUri.equals(remappedUri) || needsSpecialsInAssetUrlFix(origUri) || needsKitKatContentUrlFix(origUri)) {
            CordovaResourceApi.OpenForReadResult result = resourceApi.openForRead(remappedUri, true);
            return new WebResourceResponse(result.mimeType, "UTF-8", result.inputStream);
        }
        // If we don't need to special-case the request, let the browser load it.
        return null;
    } catch (IOException e) {
        if (!(e instanceof FileNotFoundException)) {
            LOG.e(TAG, "Error occurred while loading a file (returning a 404).", e);
        }
        // Results in a 404.
        return new WebResourceResponse("text/plain", "UTF-8", null);
    }
}

注意:如果你用了cordova-plugin-crosswalk-webview插件,则需要打开cordova-plugin-crosswalk-webviewplatformsandroidsrcorgcrosswalkengineXWalkCordovaResourceClient.java

修改shouldInterceptLoadRequest方法。

最后我们把外链的h5页面中cordova.js路径改成下面的;

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

思路是:既然不允许访问"file://,那我就设法改为http://,然后拦截webview的请求,对http://injection/开头的请求,手动返回对应文件的具体内容。

最后重新打包就可以了。。。

cordova 远程h5页面调用本地js

相关推荐