遗留了很久的一个学习任务,最近正好在总结归纳小程序在 App 之间的交互,顺便拾起一些学过的和没学过的知识。主要涉及的知识点:URL Scheme、Webview、H5 与 App 之间的通信以及 JSBridge 的概念。
H5 唤起 App
唤起方式
H5 可以通过 location.href、iframe、a 标签三种方式来调用 URL Scheme 来实现唤起 App。
URL Scheme 是系统提供的一种机制,它可以由应用程序注册,然后其他程序通过 URL Scheme 来调用该应用程序,其基本格式为 scheme://[path][?query]
。
- scheme :应用标识,已安装的APP注册在系统中的标识;
- path :应用行为,表示应用某个页面或功能;
- query :应用参数,标识应用页面或者应用功能所需的条件参数;
但是此方式无法得知 App 是否唤起成功,有可能存在 App 未下载的情况。通常用计时器,监听页面是否已隐藏(监听页面 visibilityChange),若未曾隐藏则认为打开失败,再根据不同的平台跳转不同的渠道下载页。
除此之外,还有一种链接叫:Universal Link (通用链接) , 是 Apple 在 iOS9 推出的一种能够通过 HTTPS 链接来启动 APP 的功能。当应用支持此链接时,则会无缝跳转到 APP,而不需要其他判断;但需要注意的是,这个链接是可以访问的,直接在浏览器中打开并不会跳转 App,需要跨域访问才可以。
一个完善的唤起流程如下:
若在小程序的 Webview 中尝试唤起 App 会怎么样?
(以下的逻辑参照上图的流程)
由于微信拦截了 URL Scheme,所以并不会打开 App;此时就会判断 Webview 环境,跳转对应的下载页:
如:在 Mac 上的开发者工具中会跳转 App Store:
而在安卓手机的微信小程序中则会跳转(腾讯的安装渠道):
但是由于这两个地址的域名都没有在微信后台配置,所以都会被微信认成不可信的域名,只会跳转到一个空白页面,然后提示域名不可信。
PS:主要禁止的原因是,小程序不允许将流量导出到 APP 之外;
2021.4.12 不过网上还有一种说法就是将 App 关联到腾讯的应用宝上,到时候就会自己跳转到 App Store (参考)
2021.4.13 经验证,此方法不可行,在信任应用宝域名的前提下(sj.qq.com),依旧无法唤起下载/跳转:
- 安卓表现为停止在当前 H5 并提示使用浏览器打开;
- IOS 表现为卡在当前 H5,点击下载按钮无反应;
H5 与 App 之间的通信
关于 Webview 能力
Webview 是 Android / IOS 操作系统的一个组件,它可以让应用程序直接显示网页内容。
它提供了很多能力,其中最重要的一项就是 添加 JS 和执行 JS 的能力。H5 与 App 之间的通信正是依赖于此。
还有很多通用能力如 注入 Cookie 、添加/移除响应头 、监听页面返回操作 、拦截 Url 、拦截弹窗 、获取/放置证书、监听下载事件 等等。更多 API 可以查阅 官方文档。
通信方式
通信过程主要依赖 Webview 提供的 JS API,可以简单的看成两个方向:
- App 调用 JS 代码
- JS 调用 App 代码
接下来示例的方法均以 Android API 为例。
App 调用 JS 代码
在 Webview 中是可以获取到 window 对象的,所以 App 可以访问挂载在全局对象上的方法。只需告知 App 方法名即可。
Andiroid 中使用这两个方法执行 JS:
- 使用 WebView 的
loadUrl()
方法:参数 为 js 文件路径; - 使用 WebView 的
evaluateJavascript()
方法:参数为 js 方法名,以及回调函数;
JS 调用 App 代码
JS 调用 App 代码主要有两种方式,一种是页面发起行为,App 拦截 行为解析语义响应操作;另一种是 App 提前将方法映射成 JS,注入 到 window 对象上供 JS 调用。
- 通过 WebChromeClient 的
onJsAlert()
、onJsConfirm()
、onJsPrompt()
方法回调 拦截 JS 对话框alert()
、confirm()
、prompt()
消息;- 得到消息内容后解析,再做相应的处理;
- 通过 WebViewClient 的
shouldOverrideUrlLoading()
方法回调 拦截 url ;- 一般使用这种方法拦截事先约定好 URL Scheme 上的挂载参数,再执行不同的逻辑;
- 通过 WebView 的
addJavascriptInterface()
进行对象映射;- 此方法可以将 Java 对象映射映射成 JS 对象,JS 直接调用即可。
关于 JS Bridge
JS Bridge 只是 Native 和 H5 交互方案的一种统称,犹如它的名字一样,Webview 和 H5 将 JS 用作沟通的桥梁。它赋予了 JavaScript 操作 Native 的能力,同时也给了 Native 调用 JavaScript 的能力。上述的通信方案都可以称之为 JS Bridge 的实现。
联调注意事项
- 同一方法,若确定方法名、参数等没有问题,但是调用结果与预期不一致,注意同时对比 IOS 端和 Android 端表现是否一致,若表现不一致,则应找对应的客户端同事去修改;
- 注意测试 App 版本号,以及 H5 中引用的 sdk 版本号,排查问题时考虑是否是版本过旧导致的;
- 对于用作工具的测试页面出现问题,即时反馈,有可能是测试页面未更新。