最近的Cordova項目中,采用了将前端項目放到伺服器,App直接跳轉到連結的方式開發。這樣的目的是為了能頻繁的更新,而不用釋出新的版本。但是在開發中,前端項目調用本地的Cordova插件卻出了問題,困擾了我好幾天,不過最終還算是成功解決了,下面來分享一下正确姿勢(如何在Cordova中打開遠端連結,就不再多說,如需了解,可自行百度)。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwQjMx8CX39CXy8CXycXZpZVZnFWbpN0NlAXayR3cvwFduVWay9WLvRXdh9CXyI3Zv1UZnFWbp9zZuBnLzkDNkVWZ1QjYyM2YhlzMk1SMzgzM1YTNvw1cldWYtl2XkF2bsBXdvw1bp5SdoNnbhlmauMXZnFWbp1CZh9GbwV3Lc9CX6MHc0RHaiojIsJye.png)
首先呢,在前端項目的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插件,如有疑問可留言。
本文參考:(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");
}
}
這下應該不會導緻卡頓了!