H5与原生交互

前言

提到混合式开发的童鞋,是不是想到是指 React Native , Weex,或者流行的 Flutter, 有意观赏上类分享,那友情提醒误入文章的你,打开控制台输入 history.go(-1)。 本篇总结的混合式开发,指 原生AppH5 的互相传递参数或交互逻辑,场景就是H5嵌套于原生中,通过原生访问H5页面。

至于原生APP为什么采用H5,想必大家可能想到一个原因是,原生APP审核需要一定时间,营销推广活动比较频繁的公司,所以会选择H5开发。

本篇主要带领大家,熟悉了解 H5与原生交互 需求中,H5部门与原生部门这块相关协调工作,让大家有彼此工作大致了解。欢迎提补充建议或是错误指正。

安卓、H5之间传参交互

安卓 与 H5前端 协调工作较为简单,只需要安卓将交互方法注册到window的对象名,提供给H5。然后就是两边的自我代码开发。

安卓方面工作
  1. 搭建安卓与H5交互通道,定义提供原生通道名,并项目启动时调用。
  2. 书写安卓、H5,相互传参的方法
  3. 与H5联调方法,是否正常实现传参或功能逻辑

下面代码片段,通道名设置为 Flight, 交互方法在 Flight类实现

@SuppressLint("JavascriptInterface")
    private void initWebViewCallBack() {
        Log.e(TAG, "initWebViewCallBack: ");
        if (flightWv != null) {
            flightWv.addJavascriptInterface(new Flight(), "Flight");
        }
    }


    public class Flight {
        @JavascriptInterface
        public String getVersion() {
            H5Besn bean = new H5Besn();
            bean.setCity(Cfg.localityCityName);
            bean.setLat(Cfg.myLatitude);
            bean.setLon(Cfg.myLongitude);
            bean.setVersionName(AppUtils.getVersionName(FlightWebAcitvity.this));
            String json = GsonUtils.createJsonStr(bean);
            return json;
        }
    }
H5前端工作

在项目入口文件引入,与原生交互代码。当然考虑到与原生操作过多,避免入口文件臃肿,可在入口文件引入专门原生操作的分流的文件命名为 bride.js

  1. bridge.js 区分 IOS,安卓环境,或者其他环境等,便于安卓方法只注册在安卓设备下,避免冗余无用代码
  2. 安卓方法调用

下面前端代码相关片段:

import store from '@/store'
import { setupWebViewJavascriptBridge } from '@/utils'
// ...

// 判断环境,以下添加了 && u.indexOf('matafyApp')  此类并唯一标识哪个APP标识(找原生开发同学寻要)
const urlParams = urlParamsObj()
const u = navigator.userAgent
const isAndroid = (u.indexOf('Android') > -1 || u.indexOf('Adr') > -1) && u.indexOf('matafyApp') > -1 // Android终端且在原生app内
const isiOS = u.indexOf('iPhone') > -1 && u.indexOf('matafyApp') > -1 // iOS终端且在原生app内 !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
const isMobile = !!u.match(/AppleWebKit.*Mobile.*/) // 是否为移动终端
const isMiniprogram = urlParams['weixinId'] // 微信7.0.0开始,允许userAgent来判断小程序环境,兼容为携带weixinid的路径

// ......


// 判断处于哪个环境下,并存于vuex的store中,不过如果你项目未使用vuex,大可不必使用。
if (isMobile) {
  if (isAndroid) {
    store.dispatch('app/setDevice', 'android')
  } else if (isiOS) {
    store.dispatch('app/setDevice', 'ios')
  } else if (isMiniprogram || window.__wxjs_environment === 'miniprogram') {
    if (isMiniprogram) sessionStorage.setItem('weixinId', isMiniprogram)
    store.dispatch('app/setDevice', 'wx_program')
  } else {
    store.dispatch('app/setDevice', 'mobile')
  }
} else {
  store.dispatch('app/setDevice', 'mobile')
}

// 原生交互方法
switch (store.getters.device) {
  case 'android':
    // 获取token
    const setToken = (token) => {
      store.dispatch('app/setToken', token)
    }
    // 获取版本号信息
    const setVersion = (version) => {
      localStorage.setItem('sendVersion', version)
    }

    window.setVersion = setVersion // 注意:调用方法,定要注册在window对象下
    window.setToken = setToken
    break;
  // ...
}

IOS、H5之间传参交互

IOS 与 H5,不需要像安卓提前告知暴露的对象名。

IOS方面工作
  1. 安装与H5交互的通道
    pod 'WebViewJavascriptBridge', '~> 6.0'
  2. 以下IOS代码用法:

也可参考github代码,点击链接

  • Import the header file and declare an ivar property:
#import "WebViewJavascriptBridge.h"
  • Instantiate WebViewJavascriptBridge with a WKWebView, UIWebView (iOS) or WebView (OSX):
self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
  • Register a handler in ObjC, and call a JS handler:
[self.bridge registerHandler:@"ObjC Echo" handler:^(id data, WVJBResponseCallback responseCallback) {
    NSLog(@"ObjC Echo called with: %@", data);
    responseCallback(data);
}];
[self.bridge callHandler:@"JS Echo" data:nil responseCallback:^(id responseData) {
    NSLog(@"ObjC received response: %@", responseData);
}];
H5前端工作

前端工作也只有短短两步,第一步,就是将连接webview通道的方法,可存放于函数的文件,便于多么模块调用。第二步,调用通道方法,进行注册原生需要调用方法或主动调用原生方法。

函数库文件 src/utils/index.js 文件部分代码如下:

/**
 * @export ios与js建立连接基础方法
 * @param {Function} 调用方法的回调
 */
export function setupWebViewJavascriptBridge(callback) {
  if (window.WebViewJavascriptBridge) {
    return callback(window.WebViewJavascriptBridge)
  }
  if (window.WVJBCallbacks) {
    return window.WVJBCallbacks.push(callback)
  }

  window.WVJBCallbacks = [callback]
  var WVJBIframe = document.createElement('iframe')
  WVJBIframe.style.display = 'none'
  WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'
  document.documentElement.appendChild(WVJBIframe)

  setTimeout(() => {
    document.documentElement.removeChild(WVJBIframe)
  }, 0)
}

项目处理原生文件 src/utils/bridge.js,需项目入口文件引入,部分代码如下:

import store from '@/store'
import { setupWebViewJavascriptBridge } from '@/utils'
// ...

switch (store.getters.device) {
  // ...
  case 'ios':
    setupWebViewJavascriptBridge((app) => {
      app.registerHandler('sendToken', (token, responseCallback) => { // 获取IOS原生APP传递过来的token,存于前端数据池(仓库)
        store.dispatch('app/setToken', token)
      })
    }
    break;
  // ...
}

常见的H5与原生交互的应用场景

原生与H5交互传参的应用场景,情况分为两类。第一,原生传递H5参数或回调相关操作;第二,H5主动获取原生参数或进行回调相关操作。
各个公司各个项目需求不一致,例如,token传递,经纬度传递,APP版本信息传递,app设备Id的传递,设置原生系统栏的背景色字号色的传递,调用原生方法打开第三方浏览器或者内置浏览器的方法,h5控制原生返回键的逻辑等等

春雨如酒.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容