WWDC2019中有很多session提到了 universal link,比如 new in authentication。
Universal link
Universal link 是一种提升用户体验的方式,它主要用于当用户点击一个指向你的网站链接。如果设备上安装了你的应用就可以直接打开应用;如果没有安装的话,就用safari打开链接。它有如下的特点:
- 链接唯一性:之前有某个应用拦截了某大厂的schema,而 universal link 不会出现这个问题
- 安全性: iOS 会检查app对应的服务器上的某个文件来判断是否允许app打开链接;这个文件只有开发者才能创建,因此是安全的
- 灵活性: 即使app没有安装,点击了链接也能工作
- 简单: 一个链接既适用于网页也适用于app
- 隐私性: 其它app只需要知道链接就可以和你的app通信
WWDC2019中介绍了uniersal link 更新的部分,但基本的实现步骤没有改变,下面简单介绍一下iOS上的实现。
实现步骤
主要有三个步骤:
- 准备文件名为:
apple-app-site-association
的 JSON文件 - 将 JSON 文件放置到部署了 https 的服务器
.well-known
子目录 - 在App中实现相关的协议
WWDC2019中特地提到不需要对JSON文件签名。
JSON 关联文件 association file
为了保证app和网页之间的安全链接,需要:
- 在网站上配置名为
apple-app-site-association
的文件,注意不需要后缀 - 在App中的entitlement文件添加
com.apple.developer.associated-domains
先来看下网站配置文件格式:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "9JA89QQLNQ.com.apple.wwdc",
"paths": [ "/wwdc/news/", "NOT /videos/wwdc/2015/*", "/videos/wwdc/201?/*"],
"appIDs": ["9JA89QQLNQ.com.apple.wwdc", "ABCDE12345.com.example.app"],
"components": [
{
"/": "/path/*/filename",
"#": "*fragment",
"?": {"widget": "?*", "grommet": "please"},
"exclude": true
}
]
},
{
"appID": "ABCD1234.com.apple.wwdc",
"paths": [ "*" ]
}
]
}
}
details 中则是app的详细信息,数组顺序决定了app匹配的优先级。其中,appID 的组成是
team id or app ID prefix + app_bundle_ID
paths是一组URL规则,允许或者不允许app打开的链接。而在WWDC2019中,JOSN数据更新了规则,新增 appIDs 和 components。 appIDs 是一个数组,允许把多个 appID 添加到一块; componets 也是一个数组,数组元素是一系列模式匹配规则;匹配的优先级取决于数组中的顺序。
另外,网站必须配置了 https,而且得是浏览器能识别的根证书签署的,而不能是自定义的证书。
App中的设置
首先配置entitlement文件,把网站的link添加进去,这一步通过Xcode的Capability操作。可以添加20~30个域名,域名的格式:
applink: domain_name
domain_name
支持 *
通配符,支持子域名。匹配的时候,越详细的子域名,拥有更高的优先级。此外,对于 domain.com
,规则 *.domain.com
是不能匹配的。
如果域名中包含非 ASCII 字符,那么需要使用 PonyCode 转译,如:
上海海.example.中国 ->
xn--fhqz97e.example.xn--fiqs8s
当用户点击了链接并且满足iOS唤醒App的情形时,iOS会生成 NSUserActivity 实例,并发送给 App Delegate,因此需要在程序中实现响应的协议, 如:
func application(_ application:UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([ UserActivityRestoring]?) -> Void) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL,
let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
return false
}
for queryItem in components.queryItems ?? [] {
// your handler
}
return true
}
其它说明
Universal link现在支持 macOS,TVOS,上面只对iOS说明。鉴于不同系统的人机交互有差异,因此不同系统上存在差异。在macOS上的差异主要有:
- 点击链接,默认从浏览器打开
- App必须按照在本地的磁盘上
- 最好使用从App Store下载的app:因为下载后,系统会自动去你的服务器下载JSON文件
- Developer ID-Signed的app必须运行过一次,才能很好地支持 universal link
Comments