Universal Links

Universal Links是iOS9推出的一项功能,使你的应用可以通过http或者https协议来启动。如果是已经安装了app,则直接打开,如果没有安装,则打开网页(网页的内容一般是公司主页)。

其实在iOS9之前,从外部唤醒app的方式有scheme。但是这种方式需要提前判断系统中是否安装了能够响应此scheme的app,而且这种方式在微信中是禁止的。

  • 唯一性:不像自定义的schemeUniversal Links不会被其它的app所使用。(你的域名总归不会被其它公司使用吧)
  • 安全性:当用户第一次打开app的时候,iOS会检查apple-app-site-association文件以确保你的网站允许app以其名义打开网址,这个文件的上传是有权限控制的,所以网站和app的关联是安全的。
  • 灵活性:当手机中没有安装app的时候,当你点开链接时,也会在safari中打开网页来展示你网站的内容。
  • 安全&灵活:避免别的app检测你是否安装。

如何使用Universal Links?

  1. 首先得准备一个域名,要求这个域名支持https协议
  2. 需要在开发者中心做配置:找到对应的App ID,在Application Services列表里有Associated Domains一条,把它变为Enabled就可以了。
  1. Xcode配置:将Associated Domains打开(注意xcode10.0以下是图一所示,xcode10.0以上需要手动添加,如图二所示)。同时填写我们的域名,必须以applinks:为前缀,比如你的域名为test.com,那么填写的就是applinks:test.com。app会在第一次启动的时候通过填写的域名来下载apple-app-site-association文件。

图一:

图一

图二:

图二
  1. 创建apple-app-site-association文件(服务端工作),格式如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMIDSHSAUX.com.test.bundle",
"paths": [ "*" ]
},
{
"appID": "TEAMIDSHSAUXANOTHER.com.test.bundle",
"paths": [ "*" ]
}
]
}
}
相关参数说明
  • appID:由TeamID.BundleID组成。TeamID可在开发者中心查看,BundleID可在Xcode中查看。
  • paths:设定一个App的路径支持列表,只有这些指定的路径链接才会被App所处理。(paths是大小写敏感,*是通配符表示任意路径,一般填写这个就可以)
  1. 上传文件到域名所对应的根目录,这是为了苹果能获取到你上传的这个文件。(服务端工作)

Universal Links验证

一般通常在备忘录中输入一个链接,一般类似

https://你的域名/填写的paths

如果paths中填写的是通配符 * ,那paths就不用带上。

点击此链接,就会直接跳转到对应的app,这就算成功了。

备忘录中

或者你将要测试的链接放在safari中打开,在出现的网页上下滑,可以看到有在xx应用中打开

safari中

在微信的网页浏览器里也是可以的。虽然微信屏蔽了所有的scheme方式跳转到其它app,但是Universal Links是由系统直接处理的,这也就实现了从微信跳转到我们的app。

进入app的处理

当用户点击某个链接,直接进入到我们的app,会触发下面的api。在这儿我们可以处理相关的逻辑,比如你们的app支持router跳转,根据传过来的参数,就可以跳转到具体的页面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
NSURLComponents *comps = [[NSURLComponents alloc] initWithString:userActivity.webpageURL.absoluteString];
if ([comps.host isEqualToString:@"你们的域名"]) {
/// universal links 处理
for (NSURLQueryItem *item in comps.queryItems) {
if ([item.name isEqualToString:@"url"]) {
self.linksRouteUrlString = item.value;
break;
}
}
if (self.isUniverlinksFromLanch) {
/// 避免冷启动执行两次 handleURL
self.isUniverlinksFromLanch = NO;
self.isNeedHandleUniversalLinks = YES;
} else {
// 热启动
[self p_handleUniversalLinks:nil];
return YES;
}
}
return NO;
}

注意这儿的逻辑:

  1. 建议使用 NSURLComponents 类去处理url逻辑。
  2. 这儿的query中value中的值,建议encode,否则解析出来的可能出错。
  3. 这个回调的处理建议是热启动,如果是冷启动,建议放到homeVCviewDidAppear:函数中,这儿的考虑是时机加载问题,所以冷启动的情况下,只是处理标记位。
  4. 既然区分了冷热启动,最好就把冷启动这个方法的实现屏蔽掉,避免执行两遍。

注意事项

  1. 必须要求跨域:即你当前webView的url域名,与你跳转的app域名不一致时,才生效。
  2. 当我们的app在手机上第一次运行时,如果会支持Associated Domains功能,那么iOS会自动GET定义的Domain下的apple-app-site-association文件
  3. iOS会先请求https://domain.com/.well-known/apple-app-site-association,如果请求不到,再去请求https://domain.com/apple-app-site-association,所以如果想要避免服务器接收过多GET请求,可以直接把apple-app-site-association文件放在./well-know目录下
  4. 服务器上的apple-app-site-association文件更新不会让iOS本地的apple-app-site-association文件同步更新,即iOS只会在app第一次启动时请求一次,以后除非app更新或者重新安装,否则不会在每次打开时去请求apple-app-site-association文件