Native/JS交互方案
標簽(空格分隔): Hybird
1. 方案一 scheme攔截(JSBridge)
客戶端通攔截H5的url豌习,判定之后執(zhí)行約定的邏輯狂票。
1.1 使用方法
1.創(chuàng)建全局橋對象jsBridge
贡珊。
2.js向native注冊js方法竹观。
Android:jsBridge.registerHandler(String funcName,Function func)
iOS :` [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
responseCallback(@"Response from testObjcCallback");
}];`
3.JS調用Native阿弃。
Android: jsBridge.callHandler(String funName,JSON data,Function callbackFunc)
iOS :` [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }];
4.native攔截調用
Android在
shouldOverrideUrlLoading
中捕獲url石洗。iOS在
shouldStartLoadWithRequest
中捕獲url谦絮。
5.url的參數格式
需要解析api名题诵、api使用的參數、回調函數id等挨稿。
6.native回調js的參數
封裝成JSON格式回調仇轻,比如
{ "callbackKey": "key", "callbackData": "data" }
然后通過jsBridge
通知H5頁面回調。
7.Native調用js
jsBridge._handleMessageFromNative(JSON params)
通過JSON中的數據格式區(qū)分是回調還是主動調用奶甘。
- 比如主動調用就是
{ "handlerKey": "key", "handlerData": "data" }
- 回調就是
{ "callbackKey": "key", "callbackData": "data" }
1.2 優(yōu)點
- 兼容性好篷店,適配各個系統(tǒng)版本,Android和iOS通用臭家。
- 實現(xiàn)簡單疲陕,容錯率高。
- 兼容現(xiàn)有方案钉赁,需少量修改蹄殃。
1.2 缺點
- 現(xiàn)存
flowpay
和jsflowpay
兩套協(xié)議。 - 現(xiàn)存的native調用js方式需要修改(原為
loadUrl("javascript:params")
)你踩。
1.3 最終調用流程
2. 方案二 Native向JS注入對象
Native在適當的時機向瀏覽器注入jsInterface
對象诅岩,所有通過此瀏覽器打開的網頁均能使用該對象提供提供的native能力。
2.1 使用方法
1.鑒權并注入jsInterface
對象带膜。
webview.addJavascriptInterface(Object jsInterface,String objName);
2.js調用native能力吩谦。
window.jsInterface.xxx(params);
結果分文同步和異步返回。
2.1 同步返回可以直接拿到結果膝藕。`result=window.jsInterface.xxx(params);`
2.2 異步返回需要重新加載頁面?zhèn)魅雲凳酵ⅲ换蛘哒{用約定好的js方法。
3.native調用js能力
- Android芭挽。
4.4版本之前用webview.loadUrl("javascript:(params)");
滑废。會刷新頁面蝗肪。無返回值,如果要求返回結果蠕趁,需要H5頁面異步回調朴译。
4.4版本之后用webview.evaluateJavascript("javascript:params",Callback callback);
懈息。在callback
中可以獲取js的返回結果昔驱。
- iOS
WKWebview 使用
(void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler
結果異步返回欧引,目前Stack Overflow上有使用category添加一個同步的返回函數,該函數就用while()不斷的輪詢倔韭,對UI界面有影響,有可能會卡住瓢对。
2.2 優(yōu)點
- 使用簡單寿酌。有業(yè)務變更時native端只負責提供能力。
2.3 缺點
- Android在4.2版本以下有webview遠程執(zhí)行js漏洞硕蛹〈继郏可以參考這里。
- 在js里法焰,兩端的調用方式不同秧荆,需要區(qū)分。也可能是有統(tǒng)一的寫法但我不知道埃仪。
3. 通過Webkit彈窗通知的回調實現(xiàn)交互
通過webChromeClient
的onJsAlert()
乙濒、onJsConfirm()
、onJsPrompt()
方法回調攔截JS對話框alert()
卵蛉、confirm()
颁股、prompt()
消息
3.1 使用方法
1.js調用prompt
方法
unction clickprompt(){
// 調用prompt()
var result=prompt("js://demo?params");
alert("demo " + result);
2.在客戶端的WebChromeClient()
重寫onJsPrompt()
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
// 根據協(xié)議的參數,判斷是否是所需要的url
// 一般根據scheme(協(xié)議格式) & authority(協(xié)議名)判斷(前兩個參數)
Uri uri = Uri.parse(message);
if (uri.getScheme().equals("js")) {
if (uri.getAuthority().equals("demo")) {
// 執(zhí)行JS所需要調用的邏輯
System.out.println("js調用了Android的方法");
// 可以在協(xié)議上帶有參數并傳遞到Android上
HashMap<String, String> params = new HashMap<>();
Set<String> collection = uri.getQueryParameterNames();
//參數result:代表消息框的返回值(輸入值)
result.confirm("js調用了Android的方法成功啦");
}
return true;
}
return super.onJsPrompt(view, url, message, defaultValue, result);
}
3.2 優(yōu)點
- 本質也是協(xié)議攔截傻丝,不存在兼容性問題甘有。
3.3 缺點
- native層面與現(xiàn)有的協(xié)議不兼容,需要重做葡缰。
4. 總結
參考
Carson_Ho-最全面總結 Android WebView與 JS 的交互方式
不會寫代碼的IT男-WebView 安全之 addJavascriptInterface
lzyzsd-JsBridge