Js与安卓webview 和 IOS 交互通信

2,487 阅读4分钟

一,认识混合app (Hybrid App)

Hybrid APP指的是半原生半Web的混合类App。需要下载安装,看上去类似Native App,但只有很少的UI Web View,访问的内容是 Web 。

Hybrid App 凭借其迭代灵活、控制自如、多端同步的优势在应用市场上越发显得优胜,主要得力于,其将变更频繁的部分产品功能使用 H5 开发并在客户端中借助 WebView 控件嵌入应用当中。所以,开发中我们总会遇到原生 Java 代码与网页中的 Js 代码之间相互调用从而产生的交互问题。

优点:开发成本低,更新快,更新无需通知用户,不需要手动升级,能够跨多个平台和终端。

缺点: (1)临时性的入口(2)无法获取系统级别的通知,提醒,动效等等 (3)用户留存率低(4)设计受限制诸多 (5)体验较差

二,Hybrid App webview中Javascript 与 java间通信

1,查看webview是否支持Javascript

Java 与 Js 彼此调用的前提是否设置 WebView 支持 JavaScript 功能:

  mWebView.getSettings().setJavaScriptEnabled(true);

2,java 调用 Javascript

第一步,在网页中使用 Js 定义提供给 Java 访问的方法,就像普通方法定义一样,如:

<script type="text/javascript"> 

function javaCallJs(message){ alert(message); }

</script>

如果是使用了框架(如vue,react)等 需要把方法挂载到window 如:

// 用户登录结果
window["loginResult"] = function (data) {
  // 你的代码区域
};

或者 在组件中需要提供给java调用,需要在mounted时挂在到window‘’


  mounted() {
    //打开apk 方法名需要跟java约定好
    window.openApk = this.openApk;

  },
  openApk(res) {
       //res 是由java返回的参数 
       //你的操作
  },

3,javascript 调用java

直接调用


    function a(){
     window.jmjs.openFile(path_url);
    }

jmjs是java提供好的调用别名,需要根据自己内部java人员来定,上方由传参path_url,其实他跟js传参很像,只要往java提供的方法里传参就可以了。

有返回参数

如果java开发者在提供给前端的方法中有返回值,会说明,js只要直接调用并用变量去接收就可以了,如:

 let access_token = window.jmjs.getAccessToken();
 console.log("======接受的access_token=======",access_token)

三,优化封装集成你的代码

为了方便管理你项目中的js与webview java之间交互的代码,我们可以对代码进行优化处理一下,如:

在项目utils文件中新起一个 adapter.js (文件名自起),文件中写入所有调用,和挂载方法

/**
 * webview 调用java
 */
const jimiJS = {
  //用户登录
  jimiSdkLogin() {
    if (typeof window.webkit != "undefined") {
      window.prompt("jimiSdkLogin");
    } else if (typeof jimiJS !== "undefined" && jimiJS.jimiSdkLogin) {
      window.jmjs.login();
    }
  },
  //传递url参数 打开新的webview
  jimiSdktoWebview(url) { 
    if (typeof window.webkit != "undefined") {
      window.prompt("jimiSdktoWebview");
    } else if (typeof jimiJS !== "undefined" && jimiJS.jimiSdktoWebview) {
      window.jmjs.towebview(url);
    }
  },

  /**
   * 开始下载
   * @param {*} url 下载地址
   */
  jimiSdkStartDownApk(url) {
    console.log("🚀 ~ file: adapter.js ~ line 58 ~ jimiSdkStartDownApk ~ url", url)
    if (typeof window.webkit != "undefined") {
      window.prompt("jimiSdkStartDownApk");
    } else if (typeof jimiJS !== "undefined" && jimiJS.jimiSdkStartDownApk) {
      window.jmjs.startDownApk(url);
    }
  }
};

// 用户登录结果
window["loginResult"] = function (data) {
//你的业务代码
};

window["jimiJS"] = jimiJS;

export { jimiJS }; // 导出jimijs

在业务组件中使用

import { jimiJS } from "@/utils/adapter.js";
jimiJS.jimiSdkLogin() //调用登录

四,JS与IOS的相爱相杀

本身题主并不用与ios研发方进行对接,一切以为就这样结束了,没想到,最终还是抵不过产品的需求,应用需要调取ios的微信分享和登录方法。所以最后只能加上

前置条件:ios方使用的是WKWebView

为了兼容安卓,我们需要进行判断系统类型


import VueCookies from "vue-cookies";
// import router from "../router";
import store from "@/store";
/**
 * webview sdk调用
*/
 
/**
 * sdk分享 
 * @param type  2 qq 1 微信
 * @param text  分享内容
 */
export function jimiShareToText(type, text) {
  let phoneSys = phoneSystem()
  if (typeof window.webkit != "undefined" && phoneSys == 'ios') {
    let param = { type: type, text: text }
    window.webkit.messageHandlers.shareToText.postMessage(param);
  } else if (typeof jimiJS !== "undefined" && phoneSys == 'android') {
    window.jimiJS.shareToText(type, text);
  }
}
/**
 * toBindWx 绑定微信
 * @param wxappid 
 */
export function jimiToBindWx(wxappid) {
  let phoneSys = phoneSystem()
  if (typeof window.webkit != "undefined" && phoneSys == 'ios') {
    window.webkit.messageHandlers.toBindWx.postMessage(wxappid);
  } else if (typeof jimiJS !== "undefined" && phoneSys == 'android') {
    window.jimiJS.toBindWx(wxappid);
  }
}

/**
 * 判断手机系统类型
 * @returns phoneSys
 */
function phoneSystem() {
  var u = navigator.userAgent.toLowerCase();
  let phoneSys = ''
  if (/android|linux/.test(u)) {//安卓手机
    phoneSys = 'android'
  } else if (/iphone|ipad|ipod/.test(u)) {//苹果手机
    phoneSys = 'ios'
  } else if (u.indexOf('windows Phone') > -1) {//winphone手机
    phoneSys = 'other'
  }
  return phoneSys
}


对比之前代码,由之前的导出一个对象改为导出单独的方法去供页面调用 如:

import { jimiShareToText } from "@/assets/js/adapter";

//methods
inviteToWechat() {
  jimiShareToText(1, this.user_code);
},

值得注意的是这段代码

window.webkit.messageHandlers.shareToText.postMessage(param);

js 调用 oc 方法

window.webkit.messageHandlers.<方法名>.postMessage(<参数>);

<方法名>是和oc之间商量好的方法名(见上文),用于oc判断;

<参数>用于发给oc的消息内容。