在 H5 页面打开 APP 的方法一般有两种, 在 IOS 9 以前, 一般使用的技术是 URL Scheme. 这种方式虽然可自定义程度很高, 能够巧妙地实现很多跳转, 但弊端也很明显: 我们只能通过 scheme://example 这种格式的链接来实现跳转, 而且现在苹果还对这种方式的跳转加了一个提示框:"是否打开 XXX". 对于对 web 和原生 App 交互的场景需求量很大的产品来说, 这样的跳转方式显然是步骤冗杂的, 用户体验并不好.
iOS 9 以后, Universal Links 的出现完美的解决了这个问题. 它所提供的直接, 顺畅, 无缝衔接的跳转能够让用户体验提升一个很大的级别. 用户可以点击开发者指定的类似于 https://example.com/t 的 URL 直接唤醒 App, 而不需要在浏览器打开再点击其他按钮, 实现真上的一键直达, 无缝链接.
但是 Universal Links 只能在 IOS 9 + 的平台才可以使用, 我们还需要兼容微信, 安卓和 IOS 9 以前的版本, 所以项目中, 我们会采用 URL Scheme 和 Universal Links 两个结合的方式.
1. 技术介绍
1.1 URL Scheme
项目中需要配置 URL Scheme 以用于场景恢复时跳转到应用中 (这里的 scheme 要唯一确定, 不要与其他应用一致, 建议使用项目名称作为 scheme, 不然有可能会跳转到其他的应用里).
在 iOS 工程中选择工程 Target, 选择 Info 选项, 然后打开 URL Types, 添加 URL Scheme. 可以自定义协议名称, 如 moblink. 这个形式的 URI 就会关联跳转到工程中.
配置好后安装 APP 后, 直接在访问设置好的 URL Scheme 可以直接打开 APP, 如平时我们用的比较多的 APP, 默认的 URL Scheme 如下:
QQ: mqq://
微信: weixin://
腾讯微博: TencentWeibo://
淘宝: taobao://
支付宝: alipay://
微博: sinaweibo:// 使用方式:
<a href="weixin://"> 打开微信 </a>
点击 a 标签就可以打开了微信 (如果安装了微信). 这种方式访问是比较简单的, 安卓和 IOS 都可以使用, 但是在微信端就不行了, 微信端设置了白名单, 完全屏蔽了 URL Scheme 用法, 除非加入了白名单, 像京东就可以直接打开, 否则是不可能的, 那我们还有下面的办法来解决这个办法.
1.2 Universal Links
用 URL Scheme 不能在微信里打开 APP, 但是在 IOS 9 + 的系统上还是有解决办法的, 那就是用 Universal Links, 官方网站 https://developer.apple.com/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html , 这里都是英文的, 网上也有很多文章. 开篇就说了, 如果你单纯为了能让 H5 打开 App,Schema 就能做到了, Universal Links 的意义则是把普通 url, 也赋予了能打开 App 的能力, 而不必编写专门的 Schema Url 去唤起 App, 在没装 App 的时候, Universal Links 他也是一个合法的 url 链接, 浏览器可以正常跳转, 因此不会出现在 iOS 上讨人厌的框. 而且 Universal Links 目前还没有基于 iOS 的 UI/WKWebView 的应用进行拦截, 所以目前看还是能突破微信 / 手百的封锁.(以后, 不好说啊~)
2.DEMO 示例 (IOS 篇)
2.1 IOS 平台配置
在苹果开发者账号下, 将本项目的 Associated Domains 开关 Enable;
在工程中选择好本项目的证书和描述文件; 如果是已存在的项目, 请完成步骤 1 后重新下载新的描述文件;
在工程中打开 Associated Domains 开关, 并设置域名
测试一级域名: aa.tk 测试二级域名: sit.aa.tk
Domains 域名 | 作用 |
---|---|
applinks:aa.tk | 服务器主域名 |
applinks:www.aa.tk | |
applinks:sit.aa.tk | 服务器子域名, 用于点击自定义按钮跳转 app, 需要跨域才能生效 |
注: 用于跳转打开 app 的域名需要支持 https, 如果是一级域名页面有个按钮, 点击按钮跳转二级域名来打开 app, 那么二级域名需要支持 https. 这里 DEMO 的二级域名不支持 https, 所以采用的方案是二级域名跳转到一级域名来打开 APP.
相关代码:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler{
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
NSURL *webpageURL = userActivity.webpageURL;
NSString *host = webpageURL.host;
// 在这里写需要的逻辑, 比如跳转到某个详情页
if ([host isEqualToString:@"www.aa.tk"]) {
NSString *url = [userActivity.webpageURL.description substringFromIndex:23];
NSArray *mat = [url componentsSeparatedByString:@"/"];
if (mat.count == 2) {
NSString *type = [mat objectAtIndex:0];
NSString *key = [mat objectAtIndex:1];
if ([type isEqualToString:@"goods"]) {
[self openGoodsView:key];
}
}
}
else{
[[UIApplication sharedApplication] openURL:webpageURL];
}
}
return YES;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
当通过 Universal Link 进入 app 时, 会触发此代理, 可以从前端传递参数, 这里做相应处理, 理论上可以跳转到 APP 的任何一个页面.
2.2 配置文件 apple-app-association
配置文件的位置放在跳转域名的根目录, DEMO 将一级域名设置为打开 APP 的地址, 所以上传到主域名对应服务器的根目录. 判断位置是否正确可以访问 "https://www.aa.tk/apple-app-site-association" 查看, 如果正确显示则正确.
配置文件的内容如下:
{
"applinks": {
"apps": [],
"details": [{
"appID": "xxx",
"paths": ["/testlinkapp/*"]
}]
}
}
1
2
3
4
5
6
7
8
9
"appID" 是团队 ID 的值或应用程序 ID 前缀, 紧随其后的是 boundle ID.(appID key 就是在你的应用程序的 "application-identifier"), 苹果开发者账号》merbership 下查看 teamid,bundle id 为项目自己定义的唯一标识.
"paths" 是一个字符串数组, 指定你的网站的哪些部分支持跳转到应用程序和哪些网站的部分不想跳转到应用. 指定一个域名, 不应该作为一个通用的链接处理, 在域名 paths 字符路径的前部添加 "NOT"(包括空间 T).
这里设置了 "/testlinkapp/*", 也就是说访问 "/testlinkapp/" 文件夹下任何文件 (不管是否存在) 都可以, 例如 "https://www.aa.tk/testlinkapp/xxx". 如果没有跨域, 就不能跳转, 不过下滑可以显示横幅, 点击打开也可以打开.
2.3 下载安装 APP 并测试
如果配置文件发生更改, 则需要重新下载 APP. 这里一级域名和二级域名对应的是同一个文件根目录.
测试案例:
环境 | 访问 url | 点击跳转 url | 是否跨域 | 结果 |
---|---|---|---|---|
浏览器 | https://www.aa.tk/testlinkapp/xxx | 否 | 页面不存在, 下滑出现 "打开 APP" 横幅, 点击打开会打开 APP | |
浏览器 | http://sit.aa.tk/testlinkapp2/demo.html | https://www.aa.tk/testlinkapp/zzz | 是 | 点击 demo 页的按钮, 直接打开了 APP |
浏览器 | https://www.aa.tk/testlinkapp/xxx | 否 | 直接打开 APP | |
浏览器 | http://sit.aa.tk/testlinkapp2/demo.html | https://www.aa.tk/testlinkapp/zzz | 是 | 点击 demo 页的按钮, 直接打开了 APP |
2.4 没有安装跳转到 APP Store
使用 Universal Links 时将跳转的页面设置为下载页面, 如果 APP 已经安装就直接打开 APP, 如果没有安装则进入下载页面.
使用 URL Scheme 时用延时, 超过三秒没有打开 APP, 则打开下载页面, 具体实现后面源码部分.
3.DEMO 示例 (AOS 篇)
安卓不能采用 Universal Links 的方法, 这里使用的是 URL Scheme+intent.
3.1 安卓配置文件
var AppConfig = {
"scheme": "xxx",
"package": "com.xxx",
"action": "android.intent.action.VIEW",
"category": "android.intent.category.BROWSABLE",
"host":"www.xxx.com",
"FAILBACK_ANDROID":"https://www.xxx.com/xxxx",
"FAILBACK_IOS":"itms://itunes.apple.com/hk/app/bochk/xxx?mt=8"
};
1
2
3
4
5
6
7
8
9
这里的参数由安卓同事提供,"FAILBACK_ANDROID" 是 AOS 没有打开 app 跳转到下载页面的链接
"FAILBACK_IOS" 是 IOS 没有打开 app 跳转的下载链接, 这两个是前端配置的.
在 Chrome 浏览器中使用 intent 方法, 在非 Chrome 浏览器使用 URL Scheme,Chrome 中使用 intent 的好处: Chrome 可以识别 S.browser_fallback_url 参数, 如果没有安装 app, 则直接跳转, 而不用我们自己判断是否安装 app, 在非 Chrome 中通过延时判断是否安装 app 会有弊端:(用 schema 方法实现) 点击打开 app, 会有提示 "是否用 XXX 应用打开" 的提示框, 如果用户没有点击按钮超过设置的时间, 页面就直接跳转了下载页, 体验不好. 具体实现看源码.
3.2 安卓端在微信端暂时没有办法, 只能跳转应用宝或者下载页面.
4.Universal Links 坑及建议
4.1 配置 apple-app-association
域名必须支持 https
域名根目录下放这个文件 apple-app-association, 不带任何后缀
文件为 json 格式保存为文本即可
json 按着官网的要求填写即可 测试是否正确, 直接访问域名 + 配置文件名如果能正确访问则放置的位置是正确的. 例如你想通过访问 "https://aa.test.com/xxx" 来打开 app, 那么你要把配置文件放在 "https://aa.test.com/" 对应服务器根目录, 通过访问 "https://aa.test.com/apple-app-association" 能直接访问配置文件则是正确的.
4.2 配置 Domains
开发者中心证书打开 Associated Domains
工程配置 Associated Domains
将你 apple-app-association 所在域名配置进去
给你的工程像 Schema 的 OpenUrl 一样, 编写 App 被唤醒后的处理逻辑
在配置 Domains 时, 我们需要将一级域名和二级域名都要添加进去, 这样做是为了通过自定义按钮打开 app, 而这种做法需要跨域, 所以需要配置两个, 如果用二级域名来打开 app, 则二级域名也需要支持 https.
4.3 Universal Links 基本运作流程
APP 第一次启动 or APP 更新版本后第一次启动
APP 向工程里配置的域名发起 Get 请求拉取 apple-app-association Json File
APP 将 apple-app-association 注册给系统
由任意 webview 发起跳转的 url, 如果匹配了 apple-app-association 注册过的通用链接 (path 字段配置)
打开 App, 触发 Universal Link delegate
没匹配, webview 继续跳转 url(当普通的 url 跳转)
4.4 跨域
Universal Links 必须要求跨域, 如果不跨域, 就不能实现自定义按钮打开 APP, 经测试如果不跨域, 直接输入配置的 url, 会跳转到 url, 下滑会出现如下的横幅, 点击打开也可以打开 app.
这里我们用跨域主要是用于自定义按钮打开 App, 如果打开一个页面 "http://www.aa.com/index.html", 这个页面里面有个 "打开 APP" 的按钮, 点击按钮去打开 APP. 我们用 Universal Links 技术就是点击按钮让页面跳转到我们在 apple-app-association 配置文件里配置好的路径里去, 不管访问的文件是否存在, 都能打开 APP. 例如我们设置的 Universal Links 的域名为二级域名 "https://bb.aa.com/", 配置文件的 path 为 "/demo/*", 我们将按钮的跳转链接设置为 "https://bb.aa.com/demo/xxx", 这时就可以打开 APP.
PS:
1. 这里配置文件就要放在二级域名的根目录
2.xxx 可以不存在, 也可以存在
3. 如果没有跨域的话, 会当普通的 url 跳转
4. 二级域名同样要添加到 Domain 里
5. 跨域最好使用二级域名的方式
4.5 Universal Links 会因为用户的行为而失效
Universal LInks 触发后打开 APP, 这时候 APP 的状态栏右上角会有文字提示来自 XXX App, 可以点击状态栏的文字快速返回原来的 APP, 如果用户点击了返回微信, 就会被 iphone 记住, 认为用户不需要跳出原 APP 打开新 APP, 因此这个 APP 的 Universal Links 会被关闭, 再也无效. 还有在备忘录里长按 Universal Links 链接会出现 "用 XXApp 打开" 的选项, 如果你点击了 "用 Safari 浏览器打开", 那么点击此链接也会默认用浏览器打开 url, 而不是打开 APP.
想要开启也不是不行, 让用户重新用 safari 打开, Universals Links 的页面, 然后会出现很像苹果 smart bar 的东西, 那个东西点了后就能打开.
4.6 判断是否安装了 APP 及跳转 APP Store
我们要做的时如果用户安装了 APP 就直接打开 APP, 如果没有安装就打开下载页面或者进入应用市场让用户下载应用, 但是在前端时无法通过 js 去判断是否已经安装了 APP, 解决办法:
1. 用 URL Scheme 时用延时. 设置 3 秒延时, 如果用户安装了 APP,3 秒内没有打开则进入下载页面或应用市场, 弊端是用 URL Scheme 会有询问框 "是否在 XXXAPP 中打开", 如果用户 3 秒内没有点击, 则页面就跳转到了下载页.
2. 安卓端 Chrome 浏览器可以用 intent 配置 S.browser_fallback_url 来使没有打开 app 时直接进入下载页面.
3. 用 Universal Links 打开的页面设置为下载页, 下载页里放置下载按钮, 点击下载按钮进入应用市场. 如果已经安装了 APP, 则直接打开 APP, 如果没有安装, 则这个下载 url 会被当作普通链接, 浏览器就能打开下载页, 点击下载按钮, 打开 APP Store.
5. 源码
源码地址: 点击下载
6. 实现的功能
IOS 实现功能:
1. 在浏览器中点击, 若没有安装 app, 会跳转到下载页, 点击下载按钮, 打开 itunes 应用市场;
2. 在浏览器中点击, 若安装了 app, 则直接打开 app;
3. 在微信页面中点击按钮, 若没有安装 app, 会跳转到下载页, 点击下载按钮, 打开 itunes 应用市场;
4. 在微信页面中点击按钮, 若安装了 app, 则直接打开 app;
5. 在微信消息中直接点击打开 app 的链接, 可以直接打开 app.(不是在微信浏览器中)
6. 在记事本, 短信, 邮件中直接打开 app
AOS 实现功能:
1. 在浏览器中点击, 若没有安装 app,3 秒会跳转到下载页;
2. 在浏览器中点击, 若安装了 app, 则直接打开 app;
3. 在 Chrome 浏览器, 没有 超过 3 秒后造成页面跳转到下载页 的问题
来源: http://www.bubuko.com/infodetail-2481640.html