前端菜菜一枚,寫下關於h5 和native 互動那些事情。偏前端,各種理論知識,不在贅述。之前有各位大牛已經寫過。我只寫程式碼,有問題,下面留言
/* 關於h5 和native 之間的互動 JSBridge 解決問題,偏向前端
* 使用URL 攔截方式,借用iframe
*/
/**
* ios,使用自有shouldStartLoadWithRequest 方法
* 安卓:shouldOverrideUrlLoading
* html5:掛載到window 物件上
*
*/複製程式碼
html5部分:
dom:
<button onclick="showLoading()"> showLoading</button>
<button onclick="closeLoading()"> closeLoading</button>
<button onclick="showAlert()">showAlert</button>
<button onclick="toast()">toast</button>
<button onclick="pending_payment()">pending_payment</button>
script:
var bridge = {
'linkNative': function (func, type, params, callback) {
var funcId = 'cb_' + +new Date()
window[funcId] = callback || function () { }
params = params || {}
var req = {
handler: func,
params: params || undefined,
callback: callback && funcId
}
var src = 'test://' + type + '?' + JSON.stringify(req)
var frag = document.createElement('iframe')
frag.style.display = 'none'
frag.src = src
document.body.appendChild(frag);
setTimeout(function () {
document.body.removeChild(frag)
}, 1000)
},
'showLoading': function () {
this.linkNative('showLoading', 'functional')
return this
},
'closeLoading': function () {
this.linkNative('closeLoading', 'functional')
return this
},
'showAlert': function (params) {
this.linkNative('showAlert', 'functional', params)
},
'toast': function (params) {
this.linkNative('toast', 'functional', params)
return this
},
// 發起支付請求
'pending_payment': function (params, callback) {
this.linkNative('pending_payment', 'business', params, callback)
}
}
//開啟loading
function showLoading() {
console.log('a')
bridge.showLoading()
}
function closeLoading() {
bridge.closeLoading()
}
function showAlert() {
bridge.showAlert('我點選了showAlert')
}
function toast() {
var params = {
data: "我是toast"
}
bridge.toast(params)
}
function pending_payment() {
var params = {
orderId: '12uroi2u4oifjidsafj',
time: '1234234392483294829',
name: '張三'
}
bridge.pending_payment(params, function () {
bridge.showAlert('支付的回撥函式')
//其他業務程式碼
})
}複製程式碼
這是在和native端約定好的協議和方法 test,functional,buness
複製程式碼
參考:https://juejin.im/post/5bda6f276fb9a0226d18931f
安卓demo:
JSonUtils.java
package com.example.zhangyuke.mywebview;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import com.alibaba.fastjson.JSONObject;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private WebView wb;
private String URL_HOST_STARTWITH_FUNCATIONAL = "test://functional";
private String URL_HOST_STARTWITH_BUSINSS = "test://business";
private String URL_QUERY_KEY_HANDLER = "handler";
private String URL_SHOW_LOADING = "showLoading";
private String URL_CLOSE_LOADING = "closeLoading";
private String URL_SHOW_ALERT="showAlert";
private String URL_TOAST="toast";
private String URL_PENDING_PAYMENT="pending_payment";
private String URL_QUERY_KEY_CALLBACK="callback";
private String URL_QUERY_PARAMS="params";
private String URL_DATA="data";
private String ORDER_ID="orderId";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wb = findViewById(R.id.wb);
//支援js語言
wb.getSettings().setJavaScriptEnabled(true);
//縮放至螢幕的大小
wb.getSettings().setLoadWithOverviewMode(true);
//支援縮放
wb.getSettings().setSupportZoom(true);
//webview去載入網頁
wb.loadUrl("http://www.jiaxinying.cn./bridge/");
//設定用自己的瀏覽器開啟
wb.setWebViewClient(new MyWebViewClient());
}
private boolean baseParseShouldOverrideUrlLoading(WebView view, String url, Uri uri) {
if (url.startsWith(URL_HOST_STARTWITH_FUNCATIONAL)) {
JSONObject queryObject = JSonUtils.parseObjectWithoutException(uri.getQuery());
String jsCallback = queryObject.getString(URL_QUERY_KEY_CALLBACK);
String action = queryObject.getString(URL_QUERY_KEY_HANDLER);
Log.d(TAG, "test://functional: handler: " + action);
if (URL_SHOW_LOADING.equals(action)) {
Toast.makeText(this, "載入進度條", Toast.LENGTH_SHORT).show();
return true;
} else if (URL_CLOSE_LOADING.equals(action)) { // 設定標題
Toast.makeText(this, "關閉進度條", Toast.LENGTH_SHORT).show();
return true;
}else if (URL_SHOW_ALERT.equals(action)){
String params = queryObject.getString(URL_QUERY_PARAMS);
if (!TextUtils.isEmpty(params)) {
Toast.makeText(this, params, Toast.LENGTH_SHORT).show();
}
}else if (URL_TOAST.equals(action)){
String params = queryObject.getString(URL_QUERY_PARAMS);
if (!TextUtils.isEmpty(params)){
JSONObject paramsObject=JSonUtils.parseObjectWithoutException(params);
if (paramsObject!=null){
String data = paramsObject.getString(URL_DATA);
Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
}
}
}
} else if (url.startsWith(URL_HOST_STARTWITH_BUSINSS)){
JSONObject queryObject = JSonUtils.parseObjectWithoutException(uri.getQuery());
String jsCallback = queryObject.getString(URL_QUERY_KEY_CALLBACK);
String action = queryObject.getString(URL_QUERY_KEY_HANDLER);
if (URL_PENDING_PAYMENT.equals(action)){
String params = queryObject.getString(URL_QUERY_PARAMS);
if (!TextUtils.isEmpty(params)){
JSONObject paramsObject=JSonUtils.parseObjectWithoutException(params);
if (paramsObject!=null){
String order = paramsObject.getString(ORDER_ID);
// Toast.makeText(this, order, Toast.LENGTH_SHORT).show();
}
}
callBackToJs(jsCallback,"");
}
}
return false;
}
//js回撥
private void callBackToJs(String callbackFunc, String callbackParam) {
if (TextUtils.isEmpty(callbackFunc)) {
Log.e(TAG,"callback Func is Null");
} else {
wb.loadUrl("javascript:" + callbackFunc + "(" + callbackParam + ")");
}
}
class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i(TAG,"webView shouldOverrideUrl: " + url);
Uri uri = Uri.parse(url);
return baseParseShouldOverrideUrlLoading(view, url, uri);
}
}
}
複製程式碼
MainActivity.java
package com.example.zhangyuke.mywebview;
import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.text.DateFormat;
import java.util.logging.Logger;
/**
* Created by zhangyuke on 2018/11/6.
*/
public final class JSonUtils {
private static final String TAG = JSonUtils.class.getSimpleName();
private JSonUtils() {
//Utility classes should not have a public or default constructor.
}
public static <T> T parseObjectWithoutException(String text, Class<T> clazz) {
try {
return JSON.parseObject(text, clazz);
} catch (Exception ex) {
Log.e(TAG, "parseObjectWithoutException, exception = " + ex.getMessage());
return null;
}
}
public static JSONObject parseObjectWithoutException(String text) {
try {
return JSON.parseObject(text);
} catch (Exception ex) {
Log.e(TAG, "parseObjectWithoutException, exception = " + ex.getMessage());
return null;
}
}
}
複製程式碼
最後,感謝我司阿珂。提供安卓demo文件。