

【quickhybrid】H5和Native交互原理
source link: https://dailc.github.io/2017/12/24/quickhybrid_native2h5interaction.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Hybrid
架构的核心就是JSBridge
交互,而实现这个交互的前提是弄清楚H5和Native端的交互
本文主要介绍Native端(Android/iOS)和H5端(泛指前端)的交互原理 (之前也整理过类似的文章,本系列重新梳理)
Native
与H5
交互的两种方式
原生和前端的交互有两种方式:url scheme
以及JavaScriptCore
(在Android中是addJavascriptInterface
)
url scheme适用于所有的系统设备(低版本Android和低版本iOS都适用)
但是url scheme毕竟是通过url拦截实现的,在大量数据传输,以及效率上都有影响
另一种方法则在低版本中会有这样或那样的问题
如JavaScriptCore不支持iOS7
以下,addJavascriptInterface在4.2
以前有风险漏洞
当然了,时至今日,这些低版本造成的影响已经慢慢不再
url scheme交互
这个是最广为流传的交互方式,起因是因为在hybrid刚出来时,很多低版本都需要兼容,因此几乎都用的这种
一些概念:
-
一般清空下,url scheme是一种类似于url的链接,是为了方便app直接互相调用设计的
-
具体为,可以用系统的OpenURI打开一个类似于url的链接(可拼入参数), 然后系统会进行判断,如果是系统的url scheme,则打开系统应用, 否则找看是否有app注册这种scheme,打开对应app
-
需要注意的是,这种scheme必须原生app注册后才会生效,如微信的scheme为(weixin://)
-
-
而本文中混合开发交互的url scheme则是仿照上述的形式的一种方式
-
具体为,由前端页面通过某种方式触发scheme(如用iframe.src), 然后Native用某种方法捕获对应的url触发事件,然后拿到当前的触发url, 根据定义好的协议,分析当前触发了那种方法,然后根据定义来执行等
-
协议类似于:
quickhybrid://xxx
-
一般这种交互的url没有必要在原生app配置中注册
-
-
注意⚠️: ️
iOS10
以后,urlscheme必须符合url规范,否则会报错,
基本原理:
H5 -> 触发一个url(每一个功能代表的url都不同)-> Native端捕获到url
-> Native端分析属于哪一个功能并执行 -> Native端调用H5中的方法将执行结果回调给H5

相比于其它方案的优点:
-
Android4.2以下,addJavascriptInterface方式有安全漏掉
-
iOS7以下,JavaScriptCore无法使用
所以如果需要兼容这类型低版本的机型,url scheme方案是不二选择
H5直接与Native交互
分别包括Android,iOS中H5和原生互相调用,总结如下:
-
H5调Android-原生通过
addJavascriptInterface
注册,然后H5直接调用 -
Android调H5-原生通过
loadUrl
来调用H5,4.4
及以上还可以通过evaluateJavascript
调用 -
H5调iOS-原生通过
JavaScriptCore
注册(需ios7
以上),然后H5直接调用 -
iOS调H5-通过
stringByEvaluatingJavaScriptFromString
H5调Android:
首先,原生webview需要先注册可供前端调用的JS函数
WebSettings webSettings = mWebView.getSettings();
// Android容器允许JS脚本,必须要
webSettings.setJavaScriptEnabled(true);
// Android容器设置侨连对象
mWebView.addJavascriptInterface(getJSBridge(), "JSBridge");
// Android4.2版本及以上,本地方法要加上注解@JavascriptInterface,否则会找不到方法。
private Object getJSBridge(){
Object insertObj = new Object(){
@JavascriptInterface
public String foo(){
return "foo";
}
@JavascriptInterface
public String foo2(final String param){
return "foo2:" + param;
}
};
return insertObj;
}
然后H5中即可调用原生中注册的函数
// 调用方法一
window.JSBridge.foo(); // 返回:'foo'
// 调用方法二
window.JSBridge.foo2('test'); // 返回:'foo2:test'
-
在Android
4.2
以上(api17后),暴露的api要加上注解@JavascriptInterface
,否则会找不到方法。 -
在api17以前,addJavascriptInterface有风险,hacker可以通过反编译获取Native注册的Js对象, 然后在页面通过反射Java的内置静态类,获取一些敏感的信息和破坏
Android调H5:
在4.4
版本之前
// 即当前webview对象
mWebView = new WebView(this);
mWebView.loadUrl("javascript: 方法名('参数,需要转为字符串')");
// ui线程中运行
runOnUiThread(new Runnable() {
@Override
public void run() {
mWebView.loadUrl("javascript: 方法名('参数,需要转为字符串')");
Toast.makeText(Activity名.this, "调用方法...", Toast.LENGTH_SHORT).show();
}
});
在4.4
及以后(包括)
// 异步执行JS代码,并获取返回值
mWebView.evaluateJavascript("javascript: 方法名('参数,需要转为字符串')", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
// 这里的value即为对应JS方法的返回值
}
});
-
4.4之前Native通过loadUrl来调用JS方法,只能让某个JS方法执行,但是无法获取该方法的返回值
-
4.4及之后,通过evaluateJavascript异步调用JS方法,并且能在onReceiveValue中拿到返回值
-
mWebView.loadUrl(“javascript: 方法名(‘参数,需要转为字符串’)”); 函数需在UI线程运行,因为mWebView为UI控件(但是有一个坏处是会阻塞UI线程)
H5调iOS:
以OC
为例
首先,需要引入JavaScriptCore
库
#import <JavaScriptCore/JavaScriptCore.h>
然后原生需要注册API
//webview加载完毕后设置一些js接口
-(void)webViewDidFinishLoad:(UIWebView *)webView{
[self hideProgress];
[self setJSInterface];
}
-(void)setJSInterface{
JSContext *context =[_wv valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 注册名为foo的api方法
context[@"foo"] = ^() {
//获取参数
NSArray *args = [JSContext currentArguments];
NSString *title = [NSString stringWithFormat:@"%@",[args objectAtIndex:0]];
//做一些自己的逻辑
//返回一个值 'foo:'+title
return [NSString stringWithFormat:@"foo:%@", title];
};
}
之后前端就可以调用了
// 调用方法,用top是确保调用到最顶级,因为iframe要用top才能拿到顶级
window.top.foo('test'); // 返回:'foo:test'
-
引入官方提供的JavaScriptCore库(iOS7中出现的),然后可以将api绑定到JSContext上 (然后Html中JS默认通过window.top.*(
iframe
中时需加top
)可调用) -
iOS7之前,js无法直接调用Native,只能通过urlscheme方式间接调用
iOS调H5:
// 可以取得JS函数执行的返回值
// 方法必须是Html页面绑定在最顶层的window上对象的
// 如window.top.foo
// Swift
webview.stringByEvaluatingJavaScriptFromString("方法名(参数)")
// OC
[webView stringByEvaluatingJavaScriptFromString:@"方法名(参数);"];
-
Native调用JS方法时,能拿到JS方法的返回值
-
有iframe时,需要获取顶层窗口的引用
返回根目录
github
上这个框架的实现
Recommend
-
127
超全面!聊聊交互设计背后的心理学原理 - 优设网 - UISDC 金蝶云之家...
-
104
Web 与 App 数据交互原理和实现 张小虎...
-
79
随手记Android JS与Native交互实践 Original...
-
68
开篇 开局一张图,其他全靠_? 目前flutter框架还比较新,又是谷歌家的东西,所以网上的文章基本都是讲安卓和flutter混合开发的,没有iOS和Flutter混合开发的比较详细的步骤实操。 混编的前提是你的电脑必须有flutter环境,不会配的请先谷歌
-
50
-
56
Dom Render UI的描述和呈现分离开了 html文本描述了页面应该有哪些功能,css告诉浏览器该长什么样。 浏览器引擎通过解析html和css,翻译成一些列的预定义UI控件, 然后UI控件去调...
-
18
1. 背景 从2018年开始,有赞移动团队使用Weex做为移动端跨平台动态性技术解决方案。自 Weex 引入之后需求推进速度得到很大提升,因此被开发同学使用到各个 App 和各个模块中,在使用过程中各个
-
12
React Native 原理与实践已认证的官方帐号React Native 介绍什么是 React Native?React Native 是一个由 Facebook 于 2015 年 9 月发布的一款开...
-
7
交互设计5大定律——奥卡姆剃刀原理...
-
9
React Native原理之跨端通信机制图片来源:
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK