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/开头的请求,手动返回对应文件的具体内容。
最后重新打包就可以了。。。