iOS 13.0 通用链接新功能 Universal Links

概念

通用链接Universal Links :是HTTPHTTPSURLs(统一资源定位符),Apple的操作系统会将这些URL识别 为指向网络或App中的资源。无论是在网上还是在App中,这意味着无论用户是否下载安装了我们的App,此URL都可以表示该内容。

iOS 9.0中引入了通用链接,通用链接在我们的App和网站之间是安全关联的。AppXcode中采用了一个权限,来指示该App通用链接涉及哪些域。
我们的WEB服务器采用了一个JSON文件,该文件描述了我们App,也描述了如何过滤域对应的URL,使得我们期望的URL可以在App中打开。这种双向安全握手确保没有人可以将用户重定向到其他的App而不是我们的App

关于使用苹果强烈建议使用通用链接代替之前自定义的URL schemes。因为自定义的URL schemes的方式本质上是不安全的,可能被恶意开发人员滥用。

配置

配置WEB服务器

WEB服务器必须有一个有效的HTTPS证书。HTTP不安全,不能用于验证App和网站之间的关联。用于签名HTTPS的根证书必须被操作系统识别,不支持自定义的根证书。生成证书并配置服务器之后,需要添加Apple-app-site-association文件,这是一个JSON文件,文件的格式我们稍后讨论。当我们App安装在苹果的设备上时,苹果的操作系统将会下载该文件,以确定服务器允许我们的App使用那些服务。系统还会定期下载此文件的更新。通用链接是这个文件中可能包含的众多服务之一。

通用链接示例:https://example.com/.well-known/Apple-app-site-association
Apple-app-site-association这个文件应该位于我们的域名example.com/.well-known下并且苹果不推荐使用其他路径。
过去,苹果讨论过对Apple-app-site-association这个文件是否签名,觉得签名从来不是支持普遍联系的必要步骤,所以被弃用了,因此可以不用对Apple-app-site-association这个文件签名啦。支持已签名的文件,处在其他路径的JSON文件将在将来的版本中取消对其的支持。

Apple-app-site-association文件格式:

顶层字典其KEY是服务类型,对于通用链接,KEYapplink,但是也可以使用其他服务的关键字。聚焦于通用链接,在applink下面的KEYapps,details

apps:如果是在iOS 13上我们是不需要apps的,所以可以删除。如果对于iOS 13以前的版本需要继续提供支持,则仍然需要保留apps。对于通用链接来说apps应该总是一个空数组。

detailsdetails键对应的值是一个包含字典类型的数组,每个字典代表一个特定App的通用链接配置。过去此处我们支持使用字典结构,而不是数组结构,但是这种配置方式已经过时了。

details键下面的appID对应的值是我们的App标识符。我们的App标识符由Apple提供的字母数字(10个字符)前缀和AppbundleId组成。前缀可能等于也可能不等于我们的团队标识符,检查Apple developer门户网站确认App标识符。如果我们的App具有多个相同通用链接配置,我们可能不想重复关联JSON文件,若是iOS 13,则可以使用appIDs键,来减少该文件的大小。appIDs键的值是一个App标识符数组。

若需要支持以前的版本,则应该继续为每个App使用单一的appID键。

details键下面的paths键对应的值是路径模式数组。模式匹配与在终端中执行方式相同。*表示通配符,?匹配一个字符。

2019年也就是iOS 13开始,苹果用components键替换了paths键。components键的值是一个字典数组,每个字典称为一组URL的匹配模式,也称为一个组件,每个组件都包含零个或多个匹配URL不同组成部分语句,来模式匹配URL。与先前路径模式数组一样组件也可以匹配URL的路径。在组件中匹配URLpath部分的键是"/",值(示例)为:/path/*/filename。如果需要支持以前的版本可以保留paths键,在iOS 13中如果components键存在将忽略paths键。
新增匹配项:
每个组件新增匹配URLFragment部分,在组件中匹配URLFragment部分的键是"#",值(示例)为:"*fragment"
每个组件新增匹配URLQuery部分,在组件中匹配URLQuery部分的键是"?",值(示例)为:"*widget=?*"或指定为字典:{"widget":"?*","grommet":"please"}

要使组件字典匹配候选的URL,则组件中的匹配项都必须匹配。如果不指定组件某个匹配项:路径,Fragment等,操作系统默认行为便是忽略匹配URL对应的那一部分。例如我们的App不关心URLFragment则不需要在组件中指定Fragment的模式匹配项。我们的网站可能有一些部分,还不能在App中显示,我们可以在组件中通过指定exclude键对应的的布尔值为true来排除这些子部分,此组件匹配到的URL将不会作为通用链接在App中打开。此键具有与在旧的paths键中使用Not关键字相同的行为,在使用组件字典时,不支持Not关键字。
这里有一些URL使用组件进行模式匹配的例子:

注意点:

  1. URL必须始终使用ASCII编码,组件模式匹配也是用ASCII码完成的。
  2. 国际化时为减少Apple-app-site-association文件的下载大小,可以使用更灵活的匹配方式。
  3. 操作系统会根据用户最可能浏览的位置(域)对Apple-app-site-association文件下载进行优先级排序。虽然在安装App时都会下载它们,但是优先级不同,顶级域名.com.net.org是高优先级的域,因为用户流量大。还有用户的ccTLD(国家代码TLD),若国际化的TLD与用户当前语言环境匹配,也会被优先下载。

配置App

Xcode 13中导航到Signning&Capabilities添加Associated Domains功能。

处理通用链接

激活通用链接,iOS将启动App并且向它发送NSUserActivity对象。我们需要解析这个对象,确定启动方式,决定如何处理。

  • 在您的应用程序和网站之间创建双向关联,并指定应用程序处理的URL

  • App收到NSUserActivity对象并且对象的属性ActivityTypeNSUserActivityTypeBrowsingWeb时,及时做出响应。

当iOS通过通用链接打开我们的应用程序时,应用程序会收到一个NSUserActivity对象,其属性activityType值为NSUserActivityTypeBrowsingWeb。对象的webpageURL属性包含用户访问的HTTPHTTPS URL。使用NSURLComponents 提取URL的组件。

//https://dev-api.yidux.cn/path/wally/test?name=Wally&age=1
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
        let webpageUrl = userActivity.webpageURL,
        let components = NSURLComponents.init(url: webpageUrl, resolvingAgainstBaseURL: true),
        let path = components.path
        else {
        return false
    }
    
    print("URL是\(webpageUrl.absoluteString),URL的组件:\(components)")
    print("PATH:\(path)")
    print("QUERY:\(String(describing: components.queryItems))")
    if let queryItems = components.queryItems , let name = queryItems.first(where: {$0.name == "name"})?.value, let age = queryItems.first(where: {$0.name == "age"})?.value {
        print("QUERY部分,name = \(name),age = \(age)")
    }
    
    return true
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,585评论 4 365
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,923评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,314评论 0 248
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,346评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,718评论 3 291
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,828评论 1 223
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,020评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,758评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,486评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,722评论 2 251
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,196评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,546评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,211评论 3 240
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,132评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,916评论 0 200
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,904评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,758评论 2 274