背景介绍
- 移动端占大部分流量,已经远远超过PC端
- 一线互联网公司都有自己的APP
- 这些APP中有很大比例的前端代码
- 不要指望一个APP都是客户端开发,有很大一部分是JS、HTML、css前端的语言
- 那微信举例,你每天浏览微信的内容,多少是前端
移动应用分类:
原生应用
使用某一个移动平台所特有的语言HTML5应用
使用标准的web技术
优势:跨平台
劣势:访问原生设备功能混合应用
即使用了移动原生语言,又使用了web技术
使用技术
苹果手机
IOS系统,由swift和C++/object-c语言编写,后缀名为ipa安卓手机
安卓系统,由Java + 安卓语言编写,后缀为apkwp手机
windowphone系统
由C#语言编写,后缀分为两类(wp7 wp8的是xap,wp8.1以后用8.1的SDK开发后缀为appx)混合开发
原生语言 + JS
因为JS无法调用系统的原生功能,拍照、短信、打电话、通讯录等,但是原生(IOS、Android、wp)可以。原生有很大的适配问题(特别是Android),JS可以很好的解决这个问题。
术语
-
hybird
JS + 安卓/IOS -
webAPP
m站、手机网站 -
nativeapp
纯IOS/android
题目
- hyBird是什么?为什么用?
- 介绍一下hybird更新和上线的流程
- hybird和h5的区别
- 前端JS和客户端如何通讯
知识点
概念
- hybird既混合,即前端和客户端的混合开发
混合动力的汽车
- 需前端开发人员和客户端开发人员配合完成
- 某些环节也可能涉及到server端
- PS:不要以为自己是前端就可以不理会客户端的知识,同样也不要不理会server端知识,现在是大前端的时代
存在价值
- 可以快速迭代更新【关键】,(无需app审核)
客户端都需要应用市场审核,安卓的还好审核周期可能是一两天,苹果的就会很慢, 你不可能一天一更新迭代,小步快跑的时代,审核时间耗不起的。 APP需要审核是因为安卓的Java代码,IOS的swift,这些代码或开发环境都有权利访问 到手机的一些比较安全比较隐私的一些东西或者是一些比较深层次的API, 比如获取地理位置、相机等,用这些功能开发出来的APP肯定需要审核,你有这么高的权限 我如果不审核你,如何保证用户的合法权益。 hybird是纯前端代码,没有那么高的权限,所以无需审核
- 体验更流畅(和NA的体验基本类似,不抠细节)
- 减少开发和沟通成本,双端共用一套代码
webview
- 浏览器的内核,可以承载一个HTML页面并且显示出来
- 是APP中的一个组件(APP中可以有,也可以没有)
- webview是一个统称,每个APP中可能叫法不同
-
浏览器中的webview
-
微信中的webview
file协议
- 其实一开始接触HTML开发,就已经使用了file协议
- 只不过你当时没有“协议”、“标准”这些概念
HTTP(s)和file协议的区别
-
file协议:本地文件、快
-
http(s):网络加载、慢
hybird不能用http协议只能用file协议,太慢受不了,要快,要做到和NA一样的体验,
要极致的快要变态的快
使用场景
- 不是所有的场景都适合使用hybird
- 使用NA:体验要求极致,变化不频繁(头条首页)
- 使用hybird:体验要求高,变化频繁(头条详情)
- 使用h5:体验无要求,不常用的(举报、反馈)
具体实现
- 前端做好静态页面,将文件交给客户端
- 客户端拿到前端静态页面,以文件形式存储在APP中
- 客户端在一个webview中
-
使用file协议加载静态页面
hybird和h5的区别
优点
- 体验更好,和NA差不多
- 无需审核,迭代快
缺点
- 开发成本高,联调、测试、查bug都比较麻烦
- 运维成本高,(更新上线流程)
适用场景
hybird - 适合产品型
- 产品的稳定功能,体验要求高,迭代频繁
h5 - 适合运营型
- 单次的运营活动(如,红包)或不常用功能
webview组件介绍
webview组件是我们原生开发中最核心的组件,可以理解为一个轻量级的浏览器。
这个轻量级的浏览器就能捕获到网页中发送出来的所有请求,在捕获到的请求中,我们就可以进行过滤拦截,那么我就可以在JS中伪装一个请求,来让原生进行拦截从而截取到原生所需要的JS传递过来的数据信息
JS和客户端通信的基本形式
微信公众平台:JS-SDk(微信公众平台封装的,h5前端和客户端的一个桥)
- JS访问客户端能力,传递参数和回调函数
-
客户端通过回调函数返回内容
Android
注入API方式
通过 WebView 提供的接口,向 JavaScript 的 Context(window)中注入对象或者方法,让 JavaScript 调用时,直接执行相应的 Native 代码逻辑,达到 JavaScript 调用 Native 的目的。
JavaScript调起Android的toast示例
// Android部分
class MJavascriptInterface {
private Context context;
public MJavascriptInterface(Context context) {
this.context = context;
}
// andorid版本升级时必须加上@JavascriptInterface
@JavascriptInterface
public void showToast() { // 可以由前端调用 window.ToastFunc.showToast()
Toast.makeText(MainActivity.this, "js调起了android的Toast功能", Toast.LENGTH_SHORT).show();
}
}
// 添加JS调用Android(Java)的方法接口
wv.addJavascriptInterface(new MJavascriptInterface(getApplicationContext()), "ToastFunc");
--------------------------------
// JavaScript - 前端部分
window.ToastFunc.showToast()
Android调用JavaScript前端示例
// JavaScript - 提供给Android使用的方法
function getData (str) {
$('#msg').html(str)
}
// Android端
wv.loadUrl("javascript:getData('我是一个android传递过来的值')");
IOS
schema协议简介和使用
- 之前介绍了http(s)和file协议
- schema协议 - 前端和客户端通讯的约定
// 微信的schema协议(部分) weixin://dl/general weixin://dl/favorites 收藏 weixin://dl/scan 扫一扫 weixin://dl/feedback 反馈 weixin://dl/moments 朋友圈 weixin://dl/settings 设置 weixin://dl/notifications 消息通知设置 weixin://dl/chat 聊天设置 weixin://dl/general 通用设置 weixin://dl/officialaccounts 公众号 weixin://dl/games 游戏 weixin://dl/help 帮助 weixin://dl/feedback 反馈 weixin://dl/profile 个人信息 weixin://dl/features 功能插件 // 像HTTP或file协议都是定好的,不能改只能是HTTP或file 而schema协议可以根据自己的APP名称进行修改比如:weixin里面我们叫weixin、qq里面叫qq、这个都是APP自己定的。一般都会叫和自己APP相关的,不能瞎取, // 这个名字取完以后就成了协议的一部分了,客户端和前端必须 遵守这么一个协议
拦截 URL SCHEME
先解释一下 URL SCHEME:URL SCHEME是一种类似于url的链接,是为了方便app直接互相调用设计的,形式和普通的 url 近似,主要区别是 protocol(协议) 和 host(域名) 一般是自定义的,例如: qunarhy://hy/url?url=ymfe.tech,protocol 是 qunarhy,host 则是 hy。
拦截 URL SCHEME 的主要流程是:Web 端通过某种方式(例如 iframe.src)发送 URL Scheme 请求,之后 Native 拦截到请求并根据 URL SCHEME(包括所带的参数)进行相关操作。
拦截 URL SCHEME 的主要流程是:Web 端通过某种方式(例如 iframe.src)发送 URL Scheme 请求,之后 Native 拦截到请求并根据 URL SCHEME(包括所带的参数)进行相关操作。
在时间过程中,这种方式有一定的 缺陷:
使用 iframe.src 发送 URL SCHEME 会有 url 长度的隐患。
创建请求,需要一定的耗时,比注入 API 的方式调用同样的功能,耗时会较长。
但是之前为什么很多方案使用这种方式呢?因为它 支持 iOS6。而现在的大环境下,iOS6 占比很小,基本上可以忽略,所以并不推荐为了 iOS6 使用这种 并不优雅 的方式。
【注】:有些方案为了规避 url 长度隐患的缺陷,在 iOS 上采用了使用 Ajax 发送同域请求的方式,并将参数放到 head 或 body 里。这样,虽然规避了 url 长度的隐患,但是 WKWebView 并不支持这样的方式。
【注2】:为什么选择 iframe.src 不选择 locaiton.href ?因为如果通过 location.href 连续调用 Native,很容易丢失一些调用。
示例 - 原理 - JS调用native
// JS
<button onclick="btnAction()">JS调用Native</button>
function btnAction() {
// 这里伪装一个请求,让native拦截
window.location.href = 'test://hello world'
}
// IOS
if(拦截的路径有test://) {
// 这是伪装的请求
return 不发送
} else {
// 不是伪装的请求
return 正常发送
}
示例 - 原理 - native调用JS
// JS
// 在window上提供一个方法,为了能够让native调用起来,处理原生传递过来的数据
window.handleVal = function(val) {
document.querySelector('#valInfo').innerText = val
}
// IOS
webVIew.stringByEvaluatingJavaScriptFormString:@"handleVal('hello,1810')"
// 在Android是使用loadUrl执行
IOS JS -> native实战
// JS
function takePicture() {
window.location.href = 'wyunfei://tackPicture'
document.getElementById('img').src = ''
}
function getRQCode() {
window.location.href = 'wyunfei://getRQCode'
}
// IOS
通过webView组件提供的方法,取到地址,获取协议
判断是伪装的还是真实的
定义和截取协议后面的字符串一致的方法,最后做出对应的逻辑处理
,这样前端和客户端就能通过这个协议通讯了。