一、h5傳遞給原生WebView的數(shù)據(jù)協(xié)議
傳遞的是個json字符串:
{
? ? "id": "random_value",
? ? "action": "action_name",
? ? "callback": "function_name", ?// optional
? ? "data": {...} ?// optional
}
id:這次操作的id,回調(diào)時會再傳回來。因為交互有可能是異步的,對同一個接口調(diào)用多次時,回調(diào)時以id來區(qū)分是哪一次。id由js自己定義保證唯一即可,簡單的做法是使用Math.random()
action:操作名稱,取名應該能反映其意義,例如getIp(獲取ip地址)
callback:可選,操作完成后的js回調(diào)函數(shù)名。不用回調(diào)就不傳此參數(shù)
data:可選,某些操作才需要。app會解析data中的數(shù)據(jù)使用。
例如:h5調(diào)用原生的網(wǎng)絡請求可以這么定義
{
? ? ?"id":100,
? ? ?"action":"doRequest",
? ? ?"callback","onResponse"
? ? ?"data":{
? ? ? ? ?"method":"get",
? ? ? ? ?"url":"",
? ? ? ? ?"body":""
? ? ? ? ?"header":""
? ? ? ? ?"type":"noCache"
? ? ?}
}
二、原生WebView傳遞給h5的數(shù)據(jù)協(xié)議
原生WebView傳給h5的也是個json字符串:
{
? ? "id": "random_value"
? ? "action": "action_name",
? ? "platform": "android"
? ? "data": {...} ?
}
id:與傳給WebView的一致。
action:與傳給WebView的一致。如果各種操作都用同一個回調(diào)函數(shù),則可以此區(qū)分是哪個操作。
platform:平臺
data:操作結果對應的數(shù)據(jù),是原生提供給h5的具體數(shù)據(jù)
三、h5通過js的調(diào)用方式
注入的對象在android是全局變量,也即是window的成員變量,android這邊會提供一個統(tǒng)一的調(diào)用方法入口,叫postMessage,注入的對象名叫nativeCaller,調(diào)用方式如下:
function callNative(object) {
? if (window.nativeCaller) {
? ? window.nativeCaller.postMessage(JSON.stringify(object))
? } else {
? ? alert("此功能需要在原生WebView中使用!")
? }
}
四、Android端的處理方式
創(chuàng)建BaseJsHandler的子類,例如獲取原生設備信息的處理
public class DeviceInfoHandler extends BaseJsHandler {
? ? @Override
? ? public String action() {
? ? ? ? return "getDeviceInfo"; //對應h5請求數(shù)據(jù)中action
? ? }
? ? //data是h5請求數(shù)據(jù)的data節(jié)點,callback是h5的回調(diào)函數(shù)方法名
? ? @Override
? ? protected JSONObject handleMessage(JSONObject data, String callback) {
? ? ? ? //這里返回的json數(shù)據(jù)最終會被包裝到data節(jié)點內(nèi),該過程是框架完成的,無需關心.
? ? ? ? JSONObject toJson = new JSONObject();
? ? ? ? try {
? ? ? ? ? ? toJson.put("isWifi", NetworkUtils.isWifiAvailable());
? ? ? ? ? ? toJson.put("isNetworkAvailable", NetworkUtils.isNetworkAvailable());
? ? ? ? ? ? if (null != AppUtils.getPackageInfo()) {
? ? ? ? ? ? ? ? toJson.put("packageName", AppUtils.getPackageInfo().packageName);
? ? ? ? ? ? ? ? toJson.put("versionCode", AppUtils.getPackageInfo().versionCode);
? ? ? ? ? ? ? ? toJson.put("versionName", AppUtils.getPackageInfo().versionName);
? ? ? ? ? ? ? ? toJson.put("screenWidth", PixUtils.screenWidth());
? ? ? ? ? ? ? ? toJson.put("screenHeight", PixUtils.screenHeight());
? ? ? ? ? ? ? ? toJson.put("statusBarHeight", PixUtils.statusBarHeight());
? ? ? ? ? ? ? ? toJson.put("deviceId", AppUtils.getDevId());
? ? ? ? ? ? }
? ? ? ? } catch (JSONException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return toJson;
? ? }
}
? 然后調(diào)用WebViewInject類的addHandler方法注入該處理類
WebViewInject.getInstance().addHandler("getDeviceInfo", DeviceInfoHandler.class)
五、app與內(nèi)嵌h5網(wǎng)頁(vue)交互(相互調(diào)用js)&&傳值
如何傳值?
例如:內(nèi)嵌的h5發(fā)請求也token參數(shù),怎么拿到token?
方法一:拼接法。最簡單的,app鏈入h5地址時在后面拼接上所需的參數(shù)(token),可行但不夠安全。
方法二:暴露法。也比較簡單,就是ios開發(fā)和安卓開發(fā)將所需的值暴露在window,我們直接window.xxx既可以拿到。(這個比較簡便,調(diào)用APP底座方法)
方法三:使用的是WebViewJavascriptBridge,轉載參考https://blog.csdn.net/weixin_44696379/article/details/103327042
H5與原生app交互,需要WebViewJavascriptBridge,廢話不多直接上代碼,下面是項目中的封裝bridge.js的全部代碼(示例代碼為vue)
//iOS 交互聲明
function connectWebViewJavascriptBridgeIOS(callback) {
? if (window.WebViewJavascriptBridge) {
? ? return callback(window.WebViewJavascriptBridge)
? }
? if (window.WVJBCallbacks) {
? ? return window.WVJBCallbacks.push(callback)
? }
? window.WVJBCallbacks = [callback]
? let WVJBIframe = document.createElement('iframe')
? WVJBIframe.style.display = 'none'
? WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'
? document.documentElement.appendChild(WVJBIframe)
? setTimeout(() => {
? ? document.documentElement.removeChild(WVJBIframe)
? }, 0)
}
?
?
//Android 交互聲明
function connectWebViewJavascriptBridgeANDROID(callback) {
? if (window.WebViewJavascriptBridge) {
? ? callback(WebViewJavascriptBridge);
? } else {
? ? document.addEventListener(
? ? ? "WebViewJavascriptBridgeReady",
? ? ? function () {
? ? ? ? callback(WebViewJavascriptBridge);
? ? ? },
? ? ? false
? ? );
? }
}
?
export default {
? //H5調(diào)用Native
? callhandler(name, data, callback) {
? ? //iOS的方法
? ? if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
? ? ? connectWebViewJavascriptBridgeIOS(function (bridge) {
? ? ? ? bridge.callHandler(name, data, callback)
? ? ? })
? ? }
? ? //Android方法
? ? if (/(Android)/i.test(navigator.userAgent)) {
? ? ? connectWebViewJavascriptBridgeANDROID(function (bridge) {
? ? ? ? bridge.callHandler(name, data, callback)
? ? ? })
? ? }
? },
? //Native調(diào)用H5
? registerhandler(name, callback) {
? ? //iOS的方法
? ? if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
? ? ? connectWebViewJavascriptBridgeIOS(function (bridge) {
? ? ? ? bridge.registerHandler(name, function (data, responseCallback) {
? ? ? ? ? callback(data, responseCallback)
? ? ? ? })
? ? ? })
? ? }
? ? //Android方法
? ? if (/(Android)/i.test(navigator.userAgent)) {
? ? ? connectWebViewJavascriptBridgeANDROID(function (bridge) {
? ? ? ? bridge.init(function (message, responseCallback) {
? ? ? ? ? if (responseCallback) {
? ? ? ? ? ? // responseCallback(data);
? ? ? ? ? }
? ? ? ? });
? ? ? ? bridge.registerHandler(name, function (data, responseCallback) {
? ? ? ? ? callback(data, responseCallback)
? ? ? ? })
? ? ? })
? ? }
? },
}
然后掛載到vue的原型方法上,在main.js中進行如下配置文章來源:http://www.zghlxwxcb.cn/news/detail-822377.html
import Bridge from "@/config/bridge.js" //此路徑根據(jù)實際bridge.js路徑填寫
Vue.prototype.$bridge = Bridge
完事兒,下面看一下在實際使用中的用法啊文章來源地址http://www.zghlxwxcb.cn/news/detail-822377.html
methods: {
?? ?// h5調(diào)用原生方法,testWebViewBridge為原生app定義的方法名。action為h5傳遞給原生app的參數(shù),可以為多個。data為原生app傳遞給h5參數(shù)
? ? goNative() {
? ? ? const vm = this;
? ? ? this.$bridge.callhandler(
? ? ? ? "testWebViewBridge",
? ? ? ? { action: "pick me" },
? ? ? ? data => {
? ? ? ? ? vm.ddd = data;
?
? ? ? ? ? // 處理返回數(shù)據(jù)
? ? ? ? }
? ? ? );
? ? },
? ? // h5注冊方法,供app調(diào)用
? ? iosToH5(){
?? ? ?
?? ?},
? },
?
? mounted() {
? ? // 原生app調(diào)用h5方法,iosToH5是methods中定義的方法名。
? ? const vm = this;
? ? this.$bridge.registerhandler("iosToH5", (data, responseCallback) => {
? ? ? // data是原生app傳遞給h5的參數(shù)
? ? ? vm.native_data = data;
? ? });
? }
到了這里,關于移動端 h5和原生交互的方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!