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控制原生返回键的逻辑等等

H5与原生交互_第1张图片
春雨如酒.jpg

你可能感兴趣的:(H5与原生交互)