H5調用原生的方式
方式可能有多種,根據我本人的開發經驗,我接觸過兩種方式。
第一種
1.首先對WebView進行初始化
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true); //允許在WebView中使用js
2.建立一個類JavaScriptMetod,專門用來給js提供可調用的方法
3.建立該類的構造方法,提供兩個參數,WebView對象和上下文對象
private Context mContext;
private WebView mWebView;
public JavaScriptMethod(Context context, WebView webView) {
mContext = context;
mWebView = webView;
}
4.建立一個字元串常量,作為android與js通信的接口,即字元串映射對象
public static final String JAVAINTERFACE = "javaInterface";
5.接下來就是建立給js調用的方法,方法的參數接收一個json字元串(注意:在Android4.2之後,為了提高代碼安全性,方法必須使用注解@JavascriptInterface,否則無法調用)
@JavascriptInterface
//andorid4.2(包括android4.2)以上,如果不寫該注解,js無法調用android方法
public void showToast(String json){
Toast.makeText(context, json, Toast.LENGTH_SHORT).show();
}
6.在WebView初始化代碼中執行如下代碼,
//建立上面建立類的對象
JavaScriptMetod m = new JavaScriptMetod(this, webview);
//其實就是告訴js,我提供給哪個對象給你調用,這樣js就可以調用對象裡面的方法
//第二個參數就是該類中的字元串常量
webview.addJavascriptInterface(m, JavaScriptMetod.javaInterface);
現在,在js中就可以調用JavaScriptMetod中的方法了,調用方式如下
//參數一般為json格式
var json = {"name":"javascript"};
//javaInterface是上面所說的字元串映射對象
window.javaInterface.showToast(JSON.stringify(json));
網絡上介紹js與android原生互動的文章裡,大部分都是上面這種方式,但是這種方式并不适用于ios,也就是說,window.javaInterface.showToast(JSON.stringify(json))這樣的js代碼并不适用于ios,如果用以上的方法,就得分别為android和ios各寫一套js代碼。這樣很顯然是不太合理的,是以在實際開發中,一般都使用接下來的第二種方法。
第二種
這種方法實作的思想是js發出一個url請求,并将所需的參數添加到該url中。android端通過webView.setWebViewClient()攔截url,解析url中攜帶的參數,并根據參數資訊進行相應的操作。
1.與方法一相同,首先都需要對webview進行初始化
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true); //允許在WebView中使用js
2.首先看js中的代碼是怎麼寫的,
$("#showtoast").click(function () {
var json = {"data": "I am a toast"};
window.location.href="protocol://android?code=toast&data="+JSON.stringify(json);
});
$("#call").click(function () {
var json = {"data": "10086"};
window.location.href="protocol://android?code=call&data="+JSON.stringify(json);
});
這裡定義兩個點選事件,分别控制android顯示吐司和打電話的操作。其中,protocol://android為自定義的H5與android間的通信協定,與http請求進行區分。code規定了要進行的操作,data為傳輸的資料。
2.android中的代碼
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
/**
* 通過判斷攔截到的url是否含有pre,來辨識是http請求還是調用android方法的請求
*/
String pre = "protocol://android";
if (!url.contains(pre)) {
//該url是http請求,用webview加載url
return false;
}
//該url是調用android方法的請求,通過解析url中的參數來執行相應方法
Map<String, String> map = getParamsMap(url, pre);
String code = map.get("code");
String data = map.get("data");
parseCode(code, data);
return true;
}
});
其中,getParamsMap()方法從攔截到的url解析出code,data參數,parseCode()方法将根據不同的code進行相應的操作,代碼如下:
private Map<String, String> getParamsMap(String url, String pre) {
Map<String, String> queryStringMap = new HashMap<>();
if (url.contains(pre)) {
int index = url.indexOf(pre);
int end = index + pre.length();
String queryString = url.substring(end + );
String[] queryStringSplit = queryString.split("&");
String[] queryStringParam;
for (String qs : queryStringSplit) {
if (qs.toLowerCase().startsWith("data=")) {
//單獨處理data項,避免data内部的&被拆分
int dataIndex = queryString.indexOf("data=");
String dataValue = queryString.substring(dataIndex + );
queryStringMap.put("data", dataValue);
} else {
queryStringParam = qs.split("=");
String value = "";
if (queryStringParam.length > ) {
//避免背景有時候不傳值,如“key=”這種
value = queryStringParam[];
}
queryStringMap.put(queryStringParam[].toLowerCase(), value);
}
}
}
return queryStringMap;
}
private void parseCode(String code, String data) {
if(code.equals("call")) {
try {
JSONObject json = new JSONObject(data);
String phone = json.optString("data");
//執行打電話的操作,具體代碼省略
PhoneUtils.call(this, phone);
} catch (JSONException e) {
e.printStackTrace();
}
return;
}
if(code.equals("toast")) {
try {
JSONObject json = new JSONObject(data);
String toast = json.optString("data");
Toast.makeText(this, toast, Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
return;
}
}
參考部落格:https://blog.csdn.net/so_huangbo/article/details/55522205?utm_source=itdadao&utm_medium=referral