Hybrid APP基础篇(三)->Hybrid APP之Native和H5页面交互原理
本文已经不维护,新地址:
http://www.cnblogs.com/dailc/p/8097598.html
说明
Hybrid模式原生和H5交互原理
目录
前言
参考来源
前人栽树,后台乘凉,本文参考了以下来源
- JSBridge-Web与Native交互之iOS篇
- Ios Android Hybrid app 与 Js Bridge
- Hybrid APP架构设计思路
- Android4.2下 WebView的addJavascriptInterface漏洞解决方案
- WebView---Android与js交互实例
前置技术要求
阅读本文前,建议先阅读以下文章
楔子
Hybrid APP的关键是原生页面与H5页面直接的交互,本文做简单介绍
Android、iOS原生和H5的基本通信机制
在Hybrid APP中,原生与H5的交互方式在Android和iOS上的实现是有异同的,原因是Android、iOS的通信机制有所区别,下面介绍原生和H5相互调用的方法
Android端
Native调JS
4.4版本之前
// mWebView = new WebView(this); //即当前webview对象
mWebView.loadUrl("javascript: 方法名('参数,需要转为字符串')"); //ui线程中运行
runOnUiThread(new Runnable() {
@Override
public void run() {
mWebView.loadUrl("javascript: 方法名('参数,需要转为字符串')");
Toast.makeText(Activity名.this, "调用方法...", Toast.LENGTH_SHORT).show();
}
});
4.4以后(包括4.4)
//异步执行JS代码,并获取返回值
mWebView.evaluateJavascript("javascript: 方法名('参数,需要转为字符串')", new ValueCallback() {
@Override
public void onReceiveValue(String value) {
//这里的value即为对应JS方法的返回值
}
});
如上所示,Native用H5页面中的JS方法,有如下特点
- 4.4之前Native通过loadUrl来调用JS方法,只能让某个JS方法执行,但是无法获取该方法的返回值
- 4.4之后,通过evaluateJavascript异步调用JS方法,并且能在onReceiveValue中拿到返回值
- 不适合传输大量数据(大量数据建议用接口方式获取)
- mWebView.loadUrl("javascript: 方法名('参数,需要转为字符串')");函数需在UI线程运行,因为mWebView为UI控件(但是有一个坏处是会阻塞UI线程)
JS调Native
WebSettings webSettings = mWebView.getSettings();
//Android容器允许JS脚本,必须要
webSettings.setJavaScriptEnabled(true);
//Android容器设置侨连对象
mWebView.addJavascriptInterface(getJSBridge(), "JSBridge");
Android中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;
}
Html中JS调用原生的代码
//调用方法一
window.JSBridge.foo(); //返回:'foo'
//调用方法二
window.JSBridge.foo2('test');//返回:'foo2:test'
如上所示,Native中通过addJavascriptInterface添加暴露出来的JS桥对象,然后再该对象内部声明对应的API方法,有如下特点:
- 在Android4.2以上(api17后),暴露的api要加上注解@JavascriptInterface,否则会找不到方法。
- 在api17以前,addJavascriptInterface有风险,hacker可以通过反编译获取Native注册的Js对象,然后在页面通过反射Java的内置 静态类,获取一些敏感的信息和破坏
所以,也就是为什么Android中也会使用JSBridge来进行交互,而不是addJavascriptInterface直接暴露api
- JS能调用到已经暴露的api,并且能得到相应返回值
iOS端
Native调JS
//可以取得JS函数执行的返回值
//方法必须是Html页面绑定在最顶层的window上对象的
//如window.top.foo
//Swift
webview.stringByEvaluatingJavaScriptFromString("方法名(参数)")
//OC
[webView stringByEvaluatingJavaScriptFromString:@"方法名(参数);"];
如上所示,Native通过stringByEvaluatingJavaScriptFromString调用Html绑定在window上的函数,有如下特点
- Native调用JS方法时,能拿到JS方法的返回值
- 不适合传输大量数据(大量数据建议用接口方式获取)
JS调Native
引入官方的库文件
#import <JavaScriptCore/JavaScriptCore.h>
Native注册api函数(OC)
//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];
}; }
Html中JS调用原生的代码
//调用方法,用top是确保调用到最顶级,因为iframe要用top才能拿到顶级
window.top.foo('test'); //返回:'foo:test'
如上所示,Native中通过引入官方提供的JavaScriptCore库(iOS7中出现的),然后可以将api绑定到JSContext上(然后Html中JS默认通过window.top.***可调用)。有如下特点
- iOS7才出现这种方式,在这之前,js无法直接调用Native,只能通过JSBridge方式简介调用
- JS能调用到已经暴露的api,并且能得到相应返回值
- iOS原生本身是无法被JS调用的,但是通过引入官方提供的第三方"JavaScriptCore",即可开放api给JS调用
原生和H5的另一种通讯方式:JSBridge
实际上,Native与H5通信,除了前面提到的用基本方法外,还有一种广为流行的方法:JSBridge
什么是JSBridge
JSBridge是广为流行的Hybrid开发中JS和Native一种通信方式,各大公司的应用中都有用到这种方法
简单的说,JSBridge就是定义Native和JS的通信,Native只通过一个固定的桥对象调用JS,JS也只通过固定的桥对象调用Native,基本原理是:
H5->通过某种方式触发一个url->Native捕获到url,进行分析->原生做处理->Native调用H5的JSBridge对象传递回调。如下图
上图简单的介绍了下JSBridge的核心原理,具体详细实现请参考后面详解。
为什么要用JSBridge
在上文中我们有提到Native和原生之间的基本通信,既然Native和原生已经能够实现通信了,那为什么还要这种通过url scheme的JSBridge方式呢,原因大致如下
- Android4.2以下,addJavascriptInterface方式有安全漏掉
- iOS7以下,JS无法调用Native
- url scheme交互方式是一套现有的成熟方案,可以完美兼容各种版本,不存在上述问题
另外,请注意,可以理解为JSBridge是一种交互理念,而上述的url scheme则是其中的一种实现,所以也就是说,就算后面实现变为了addJavascriptInterface,JavaScriptCore,也一样是JSBridge交互
JSBridge交互的一个很大特点就是便于拓展,而且没有重大的安全性问题,所以也就是为什么它广为流行
JSBridge原理以及实现
JSBridge的原理和实现请参考 JSBridge实现原理
Hybrid APP基础篇(三)->Hybrid APP之Native和H5页面交互原理的更多相关文章
- Hybrid APP之Native和H5页面交互原理
Hybrid APP之Native和H5页面交互原理 Hybrid APP的关键是原生页面与H5页面直接的交互,如下图,痛过JSBridge,H5页面可以调用Native的api,Native也可调用 ...
- Hybrid APP基础篇(四)->JSBridge的原理
说明 JSBridge实现原理 目录 前言 参考来源 前置技术要求 楔子 原理概述 简介 url scheme介绍 实现流程 实现思路 第一步:设计出一个Native与JS交互的全局桥对象 第二步:J ...
- Hybrid APP基础篇(二)->Native、Hybrid、React Native、Web App方案的分析比较
说明 Native.Hybrid.React.Web App方案的分析比较 目录 前言 参考来源 前置技术要求 楔子 几种APP开发模式 概述 Native App Web App Hybrid Ap ...
- Hybrid APP基础篇(一)->什么是Hybrid App
最新更新 一个开源的快速混合开发框架:https://github.com/quickhybrid/quickhybrid Android.iOS.JS三端内容初步都已经完成,有完善的设计思路.教程以 ...
- Hybrid APP基础篇(五)->JSBridge实现示例
说明 JSBridge实现示例 目录 前言 参考来源 楔子 JS实现部分 说明 实现 Android实现部分 说明 JSBridge类 实现 Callback类 实现 Webview容器关键代码 实现 ...
- docker+k8s基础篇三
Docker+K8s基础篇(三) kubernetes上的资源 A:k8s上的常用资源 Pod的配置清单 A:Pod上的清单定义 B:Pod创建资源的方法 C:spec下其它字段的介绍 Pod的生命周 ...
- NIO相关基础篇三
转载请注明原创出处,谢谢! 说在前面 上篇NIO相关基础篇二,主要介绍了文件锁.以及比较关键的Selector,本篇继续NIO相关话题内容,主要谈谈一些Linux 网络 I/O模型.零拷贝等一些内容, ...
- Python基础篇(三)_函数及代码复用
Python基础篇_函数及代码复用 函数的定义.使用: 函数的定义:通过保留字def实现. 定义形式:def <函数名>(<参数列表>): <函数体> return ...
- iOS原生App与H5页面交互笔记
文/MikeZhangpy(简书作者)原文链接:http://www.jianshu.com/p/4ed3e5ed99c6著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 最近在做一个项 ...
随机推荐
- 关于iOS Block当中为什么要用weakSelf和strongSelf的思考
场景:当你在某个界面请求网络数据的时候,用户不愿意等待点击了返回按钮,此时在Block当中用如下的方式使用weakSelf的话,有可能会奔溃(因为在并发编程的情况下,虽然在if判断的时候weaksel ...
- js怎样得出数组中某个数据最大连续出现的次数
1:js怎样得出数组中某个数据最大连续出现的次数 var test=[1,2,3,3,2,2,2,3,3,3,3,5,3,3,3,3,3] ; var j = 0 ; var max ...
- Linux Centos平台下安装Nginx
以home下安装为例,切换到home目录下 cd /home 安装依赖 nginx相关依赖 yum -y install make gcc gcc-c++ openssl openssl-devel ...
- opacity(透明度)属性设置
1.opacity:是属性,整个元素包含子元素全部都会透明,取值范围0-1; 2.background-color:rgba(0,0,0,.5)rgba是值,用于背景,取值范围0-1. 补充:a-al ...
- 一条常用的 Sql
select * from table where 条件1 .... group by 字段...... Having 条件1.....Limit 0,10; 1. 根据where ...
- STM32 HAL库学习系列第3篇 常使用的几种延时方式
1 自带的hal_delay 函数 毫秒级延迟 void HAL_Delay(__IO uint32_t Delay) { uint32_t tickstart = HAL_GetTick( ...
- POJ_1679_The Unique MST(次小生成树)
Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definit ...
- 【代码沉淀】 - EPPlus - 操作xlsx表格文件
EPPlus - Create advanced Excel spreadsheets on the server.web: http://epplus.codeplex.com/nuget: Ins ...
- High Water Mark 图示
+---- high water mark of newly created table | V +-------------------------------------------------- ...
- dsp6657的helloworld例程测试-第二篇-CFG文件
1. 上一篇疑问,int StackTest()这个函数是怎么运行的,后来在.cfg文件找到了答案,.cfg包含丰富的信息,对于用惯C语言的,确实不太习惯 var Memory = xdc.useMo ...