一,认识混合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的消息内容。