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