原生代碼和JS交互說明
原則
1.接口不要定義返回值,JS有獲取數據需求的情況通過回調函數的方式實現
2.盡量保證iOS和Android端一致,簡化JS端的使用
iOS端
iOS端目前使用WKWebview加載前端Html。
JS調用OC接口WKWebView提供了postMessage的機制來讓JS調用OC接口:
window.webkit.messageHandlers[namespace].postMessage(JSON.stringify(wrap));
OC回調JS函數[self.webView evaluateJavaScript:js completionHandler:];
bridge.js為方便JS端調用,在注冊了OC方法后,需要再bridge.js中定義好JS函數,例如:
kf.getResourceInfo = function (callBackName) { calliOSFunction("kf","getResourceInfo","",callBackName); };
bridge.js 在webview加載頁面時會自動注入到頁面中,JS端可直接調用這里聲明的函數
Android端
Android使用QQ提供的X5內核WebView,但是該WebView在部分情況下可能會退化會系統的WebView內核,考慮到目前我們最低兼容到Android4.2版本,所有前端的代碼依然需要考慮兼容Android4.2的WebView
JS調用Java接口Android端只要調用: webview.addJavascriptInterface(obj, "kf");方法即可將obj對象中被@JavascriptInterface注解的方法提供給JS端調
Java調用JSwebview.loadUrl("javascript:" + function + "(\"" + data + "\")");通過此方法可以調用JS中的函數,該函數必須在window對象下。
帶回調函數的接口為方便JS端調用,目前要求所有帶回調函數的方法,允許傳入function對象,如:
kf.getResourceInfo = function (callback){ };
在調用時,調用方式如下:
kf.getResourceInfo(function(data){
console.log(data)
})
因為Java端並不能直接使用JS中函數對象,Java提供的接口只能接收String類型的回調函數名,所以為了支持在前端這樣調用,需要做如下的處理
bridge.js和iOS端一樣,帶回調的JS接口需要再bridge.js中重新聲明, 在assets下的android_bridge.js中:
kf.getResourceInfo = function(callback){
win.kf._getResourceInfo(wrapCallback("getResourceInfo", callback));
};
和iOS端不同的時,Android端僅需要重新聲明帶回調函數的方法,無返回值的不需要重新聲明
@CallbackFunction注解請注意上面bridge.js中出現的 _getResourceInfo 方法調用,該方法在Java的接口中並不存在,它是在編譯的時候自動生成的,實際的Java方法聲明如下: public class DetailJsFunction extends BaseJsFunction {
@CallbackFunction
public void getResourceInfo(final String callback) {
webView.callJsFunction(callback, resourceInfo);
}
}
所有被@CallbackFunction注解的方法,在編譯時,會自動生成一個新的代理類,該代理類中會自動追加一個 "_" + 原方法名的方法,所以在JS中可以直接以:
win.kf._getResourceInfo(wrapCallback("getResourceInfo", callback));的方式調用
使用JsFunctionProxy為了使上述方式生效,需要通過JsFunctionProxy來創建要注入給JS的對象, 如下: detailJsFunction = JsFunctionProxy.inject(DetailJsFunction.class, this, webView);
webView.injectJsObject(detailJsFunction, "kf");這里的DetailJsFunction不能是內部類了,必須是public的獨立類,所以有些情況可能會略有不便
其他
1.除了上述兩種原生和JS交互方案,Android和iOS都可以通過攔截特定的scheme的方式來和JS通信,這種方式效率較低,但是最通用,有興趣的同學可自行搜索相關資料。
2.Android和iOS的bridge.js代碼目前還需要手動維護,但是其實都是可以自動生成的,有興趣的同學可以搞一下。
3.Android端的實現現在有點復雜,有興趣的同學可以去了解下Java編譯時代碼生成。
/* H5和iOS 客戶端交互問題總結 1.Control + Alt + T 【讓標簽包裹一段內容】 2.直接返回值/回調【設置】 3.iOS 注入的時機 4.客戶端調用JS的過程 【A:Objective-C調H5、B:H5調Objective-C】 5.客戶端/前端自測->Remote device 6.JS 傳參數文檔說明 7.多次點擊會重復調用客戶端方法 8.交互過程中的細節問題未考慮 9.Android 方法名的下划線問題 10.難以判斷出現的問題 11.瀏覽器的兼容性問題 12.:ResultType Json kit WebStorm : *Remote Devices {Android} *W2 代理 *自測模板頁 *自升級HTML *加載WebView動畫 */