iOSer 必知必会的深度连接技术——WWDC2019更新

iOSer做为移动开发者中的一员,不得不说深度连接在当下这个“流量”时代已经成为咱们的必修课了,那么什么是深度连接呢?简单的说就是,能够经过一个简单的“连接”,打开App并直接进入该App中的内容页。前提是该手机上已安装该App,且该App须要支持深度连接。例如:在Safari里看到的澎湃新闻App的某一篇新闻 “中国又一新的世界遗产...” 点击下面滚动Banner上的“打开App”按钮即可直接进入澎湃新闻App(已安装)中对应的新闻页面:html

澎湃新闻1-1

可见在移动端采用深度连接技术,极大的省去了用户打开App、再搜索内容或者点击某处进入指定页面等繁琐的操做,直接点击网页上的打开按钮便可一键到达App内的指定页面。web

1、iOS上深度连接的由来

在介绍深度连接是怎么来的以前,有一个基础概念须要和你们同步一下:json

SandBox(沙盒)

SandBox(沙盒)是苹果官方规定的iOS系统强制应用程序只可以读取应用程序内部数据,不能够访问其余应用信息数据的一种机制。后端

  1. 在iOS系统的设备中每个App都有本身的储存空间;
  2. App只能访问本身沙盒目录下的内容,不能访问其它存储空间的内容;
  3. 应用程序的数据请求须要通过权限检测,检测不经过则不执行;

为何使用沙盒?

SandBox(沙盒)是安全体系中的一种机制,从而苹果公司在设计iOS系统时,考虑到应用之间的信息安全,对应用程序的访问权限设置了限制。api

SandBox(沙盒)的弊端

使用沙盒机制后App之间不能相互访问进行通讯,从而使得App成为一个个的信息孤岛。(弱小可怜又无助)数组

如何解决SandBox(沙盒)问题?

不能说苹果的初衷怎么样,可是带来的问题是显而易见的,那么其实苹果早在2010年 iOS 4 的时候就已经意识到App信息孤立的问题了,因此推出了 URL Scheme 技术,此技术使得iOS系统能够经过特定的URL方式传递参数给另一个App。例如:iOSer://userid=123456&name=sands 。浏览器

不得不认可,这个技术确实解决了当初比较棘手的问题,可是在突飞猛进的今天,URL Scheme的诟病也日渐显著,好比想要实现两个App之间的跳转则须要兼并开发,再好比URL Scheme可以打开App的前提是已经安装了App,若是没有安装则必定会报错,相信下面的错误你们必定都见的很多,更重要的是如今愈来愈多的浏览器已经再也不支持URL Scheme了,这必然让咱们不得不另辟蹊径。安全

IMG_0080

相信苹果也是深入的意识到了URL Scheme已经再也不是长久之计了,因此苹果在2015年 iOS 9 中隆重推出了 Universal Links(通用连接)bash

2、深度连接解决的问题

Universal Links(通用链接) 一种可以经过点击传统 HTTPS连接启动App 或者 打开对应网站 的技术。服务器

经过惟一的网址, 不须要特别的URI Scheme就能够连接一个特定App里面的视图 。好比:一个App分享内容到微信,用户在微信内置浏览器中看到H5页面内容,而后用户点击触发Universal Links连接后,便可直接打开App内相同的页面内容。(PS: 因为微信 6.5 版本以后作了 屏蔽操做 ,致使没法直接打开App了,但这并不影响系统引导。)

NOTE

Universal links let users open your app when they tap links to your website within WKWebView and UIWebView views and Safari pages, in addition to links that result in a call to openURL:, such as those that occur in Mail, Messages, and other apps.

When a user is browsing your website in Safari and they tap a universal link to a URL in the same domain as the current webpage, iOS respects the user’s most likely intent and opens the link in Safari. If the user taps a universal link to a URL in a different domain, iOS opens the link in your app.

For users who are running versions of iOS earlier than 9.0, tapping a universal link to your website opens the link in Safari.

首先,这是一种标准的HTTPS连接,为何要强调这一点呢?由于它解决了一个很核心的问题,即便你的设备上没有安装App,那么点击该连接也不会出现上面“Safari没法打开该网页,由于网址无效”的报错,它能够看成普通网页正常被访问,为用户体验层面的提高提供了更多的可能。

其次,经过 Universal Links 跳转到本身App从而进行通信的方式不须要两个App之间的兼并开发,别人的App里不须要为打开本身的App作任何配置,只须要本身开发配置好本身的App和网页便可,无论本身的网页是在哪个App里被打开,网页和App之间实现的 Universal Links 都一直有效。

最后,使用这种方式还有几个细节优点点,好比省去了URL Scheme跳转App前的系统确认提示框,相比之下更直接,另外,App未安装时点击以后直接访问网页,一方面解决了URL Scheme在浏览器层面不可知的成功或者失败,同时还可以呈现给用户网页内容,引导用户下载或是进行网页操做,无论从哪一层面来讲,这都是一种完胜URL Scheme的方式。

3、如何实现iOS上的深度连接

添加 Universal Links 的支持很简单。你只须要三步便可实现:

  • 建立一个 apple-app-site-association 文件,文件内容是关于你的App可以处理的URLs的JSON数据
  • 上传上面建立好的这个 apple-app-site-association 文件到你的支持HTTPS的Web服务器。你能够将这个文件放到你服务器的根目录下或者 .well-known 的子文件夹里
  • 在你的App里配置、处理 Universal Links

建立和上传 Association 文件

为了在你的网站和App之间建立一个安全的链接,你创建了它们之间的信任关系。这个信任关系的创建分两步:

  • 一个是你添加到你的网站的 apple-app-site-association 文件
  • 另外一个是你添加到你的App的 com.apple.developer.associated-domains 权限(这一部分在下面的 准备处理 Universal Links 的App 中介绍)

在您的apple-app-site-association文件中,您能够指定网站中应做为通用连接处理的路径以及不该做为通用连接处理的路径。保持路径列表至关短,并经过正则通配符的方式来匹配更多的路径集。以下是一个 apple-app-site-association 文件的示例,该文件标识了应做为通用连接处理的三个路径。

{
    "applinks": { "apps": [], "details": [ { "appID": "9JA89QQLNQ.com.mob.moblink", "paths": [ "/moblink/news/", "/videos/moblink/2019/*"] }, { "appID": "ABCD1234.com.mob.moblink", "paths": [ "*" ] } ] } } 复制代码

注意

不要 在 apple-app-site-association 文件名后面添加 .json 后缀 。

  • apps:这个key必须存在,而且对应value必须是一个空数组
  • details:这个key对应的value是一个包含一个或多个字典的数组,其中每个字典都对应一个网站支持的app,另外,数组中字典的顺序决定了系统查询匹配的顺序,因此你能够指定app只处理你网站的部分路径
  • appID:这个key对应的value是Team ID后面拼接上Bundle ID,这个很重要,千万不能错
  • paths:这个key对应的value是指定你的网站中哪些路径是须要(或者不须要)app处理的字符串数组。

不须要匹配的path则在对应路径前面加 NOT 便可,例如:"paths": [ "/moblink/news/", "NOT /videos/moblink/2010/*", "/videos/moblink/201?/*"]因为系统会顺序查找路径规则,一旦发现规则相匹配时则中止查找,因此你应该将优先级高的写在优先级低的后面。若是将前面的示例改成: "paths": [ "/moblink/news/", "/videos/moblink/201?/*", "NOT /videos/moblink/2010/*"]则数组中最后一条规则就没有用了,由于它必定会被前一条规则拦截掉。

在 apple-app-site-association 文件中有不少种方式来指定网站路径。你能够:

  • * 来指定你的整个网页都支持
  • 包含一个特殊的URL,例如 /moblink/news 来指定部分连接支持
  • 在特殊URL后面加 * ,例如 /videos/moblink/2017/* 来指定一组连接支持

注意
paths数组中的路径字符串是大小写敏感的,必定要注意区分大小写。

建立 apple-app-site-association 文件后,将其上传到HTTPS Web服务器的根目录或 .well-known 子目录。该文件须要经过HTTPS直接访问-无需重定向-位于 https://<domain>/apple-app-site-associationhttps://<domain>/.well-known/apple-app-site-association 。接下来,你须要在你的App中处理 Universal Links。

准备处理 Universal Links 的App

Universal Links使用了两项技术:第一个是在Web浏览器和App之间启用Handoff的相同机制,第二个是共享Web凭据。关于这两项技术能够参考官方 Web Browser–to–Native App HandoffShared Web Credentials Reference 。当用户点击一个 Universal Link 时,iOS系统启动你的App,而且带了一个你能够查询到你的App是经过什么方式被启动的 NSUserActivity 对象参数到你的App里。

要在你的App里支持 Universal Links,只须要作以下两步:

  • 添加一个指定的你的App支持的域名权限
  • 更新你的 AppDelegate 当接收到 NSUserActivity 对象时做出适当的响应

在你App的 com.apple.developer.associated-domains 权限里,包含了全部你的App想要看成universal link处理的域名列表。在Xcode的项目主页中,选择 Capabilities tab页,而后打开 Associated Domains ,以 applinks: 开头添加上你的App支持的域名,例如:applinks:z.t4m.cnapplinks:*.ulml.mob.com

注意:这个域名权限列表最多添加20到30个。

15625698347787

配置好Associated Domains以后,就要在 AppDelegate.m 中实现 HandOffUIApplicationDelegate 方法以便你的App可以接收到universal link并进行适当的处理。

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler { NSLog(@"title: %@", userActivity.title); // NSUserActivityTypeBrowsingWeb NSLog(@"activityType: %@", userActivity.activityType); // The webpage URL property always contains an HTTP or HTTPS URL, and you can use NSURLComponents APIs to manipulate the components of the URL. NSLog(@"webpageURL: %@", userActivity.webpageURL); // 根据webpageURL的路径、参数等做出适当的处理 // <your code here ...> return YES; } 复制代码

到此,iOS上深度连接的实现就完成了。总体来看,实现iOS上的深度连接涉及到先后端的操做和联调会特别多,尤为是HTTPS证书和错误处理访问到网站那一块,看似简单,但真正一步一步作起来的时候,大大小小的问题仍是很多的,若是对于先后端不是特别熟悉的话可能仍是须要一些时间的。这里我建议你们能够选择第三方深度连接服务,好比MobLink、魔窗、LinkedMe等等,相比之下,MobLink全球领先的移动端场景还原解决方案 以避免费、服务好和功能而出名,较为推荐。

4、WWDC2019: What's New in Universal Links

时隔多年,在刚结束没有多久的 WWDC 2019 中,又再一次提到了Universal Links,虽然 整个session不长,也就不到20分钟的时间,但足以体验苹果一直在作这件事儿。

首先,划一下重点:Universal Links 以前只支持在 iOS 和 tvOS 上,如今全面登录到 macOS 上了,不管你是用 UIKit 仍是 AppKit 开发的 Mac App 均可以使用Universal Links。

这一次 WWDC2019 Universal Links 主要的变化有两点:

  • apple-app-site-association 文件支持精细化地址匹配写法
  • 全面支持macOS系统

OverView 总览

Universal Link 的基本运做机制

  • 经过在 XCode 的 App 配置中配置了相关信息以及安全域名指定
  • 经过在 Https only 的安全域名上部署一个配置 apple-app-site-association 文件
  • apple-app-site-association 文件中配置上丰富的 website 与 app 的连接信息
  • 在 website 与 app 之间创建起了安全有效的握手机制
  • 实现 website 的 url 与 app 的直接联动
  • 相对于自定义的 schemes 来讲 Universal Link 能带给你更安全更流畅的体验

补充:schemes 上最使人诟病的就是 app 劫持,不少 app 会冒充注册知名大厂的 app scheme 从而拦截调常规的大厂 scheme 唤起,这一点在 Universal Link 就能很好的避免。

apple-app-site-association 文件精细化匹配

15625733635308

上图是 MobLink 这款提供深度连接功能的SDK的apple-app-site-association文件老的写法示例。

WechatIMG399

这是新的写法,支持了更多更强的配置能力。

  • apps 这个字段只有在 iOS 上有用,tvOS/macOS 这个字段能够忽略
  • details 字段结构大幅度变化
    • 之前是字典 appID 为 Key,如今是数组,而且支持 appIDs 这样的 key,能够一套配置适配多个 appID,大幅度减小工做量
    • 新增 components 字段,能够进一步约束 Universal Link 的生效条件
      • 能够经过 / 来配置支持的 path 格式条件
      • 能够经过 # 来配置支持的锚点条件
      • 能够经过 ? 来配置支持的字段条件
      • exclude 是排除字段,符合这个条件的 Universal Link 不生效

Universal Links 网络服务的配置建议

在部署网络服务,配置 apple-app-site-association 文件的时候,苹果建议还要遵循一下几点 Tips

  • 必须支持 https:

必须是正规证书,不能使用自定义证书。

  • URL 使用 ASCII 编码

由于在 URL 中会使用不少符号诸如 # ?% ,所以要使用 ASCII 编码。

  • 减小 apple-app-site-association 文件的大小

减小大小有助于在拥堵的网络条件下,更顺畅的生效 Universal Link。若是你的应用面向不通的国家,针对不一样的国家有不一样的配置文件,能够经过国家标记符来分别配置,从而让用户只下载最精简的 JSON 文件。

  • apple-app-site-association 文件的下载和更新策略:

当 App 安装到设备的时候,会从配置域名上下载这个JSON文件到本地,从而根据配置生效相关的功能。而且设备上下载的这个JSON文件会不按期的更新(亲测过,App 发布版本更新的时候也会准确触发JSON文件的更新)。

  • 使用 Smart Banner

网页中的 Smart Banner 与 Universal Links 一块儿配合使用,能够有效的引导未安装 app 的用户前往下载,已安装 app 的用户就能够顺畅的进行跳转

Universal Links 支持 macOS

在 XCode 中配置 Universal Links

WechatIMG398

开发 Universal Links的代码,支持macOS:

// Configuring Your App
func application(_ application: Application, 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 ?? [] { … return true } 复制代码

在支持 macOS 的状况下,appDelegate 的 Universal Link 的处理也是这个 delegate,区别只是 UIApplication 变为 NSApplication。

因为这个 delegate 会由不少其余的快捷方式触发,不只仅由 Universal Link 触发,因此经过 NSUserActivityTypeBrowsingWeb 来判断来源,剩下的就是标准的 url 处理了。

macOS 下的 Universal Links 工做机制与 iOS 下存在必定的差别

  • 默认打开网页,会提示用户是否须要打开app
  • 远程登陆下没法生效
  • Appstore 签名 macApp 能够在下载 App 后马上生效
  • 开发者签名的 macApp 必须在用户运行过一次后生效

在 mac app 中打开一个 Universal Link

// UIApplication
UIApplication.shared.open(url, options: [ .universalLinksOnly: true ]) { … } // NSWorkspace let configuration = NSWorkspace.OpenConfiguration() configuration.requiresUniversalLinks = true NSWorkspace.shared.open(url, configuration: configuration) { … }复制代码
相关文章
相关标签/搜索