理解Deep Link & URI Schemes & Universal Link & App Link

引言

最近在做客户端开发的工作中,需要解决一些渠道流量监控的问题。发现在唤醒app的时候涉及到很多这样那样的link,于是就先对这几个link做了一些了解。
事实上,这几个名词并不是完全区分的关系,同时这些技术都仍处在不断发展的阶段,因此面对这样碎片化的概念,很难去直接解释清楚它们之间的关系与不同,所以只能先从每个名字的概念上和实践运用中去把握了。
而且,这几个概念实际上是有一些从属和时间上的关系的,其实也不复杂,只是我们不光是要了解它们的意思,还得了解它们出现的情况,怎么使用。下面我就为大家简单介绍:

1. Deep Link

Deep Link就是一个链接的概念,事实上我们每天都会使用到它去打开一个网站页面,只不过它是比普通的链接更加复杂一些。在web开发领域,深度链接就是说这个链接不是仅仅打开一个网站http://example.com/, 而是直接地打开这个网站中的某个具体内容页面http://example.com/my-awesome-content-page 。 通常来讲,有很多链接就是深度链接,只不过大家都习惯于称之为链接。
在移动开发领域,深度链接的概念就是指app在处理特定的url时能够直接跳转到对应的内容页面或者触发特定的逻辑。这样的好处有:

  • 在web页面和app的切换过程中保留了上下文
  • App间的切换保留了上下文,实现app间参数的传递
  • Web页可以被搜索引擎索引,可以增加SEO的访问量从而提高app下载量和开启率。

Android、iOS都推出了相应的概念去实现深链接。于是就有了Universal Link、App Link、URL schemes.

2. URI Schemes

URI、URL、URN

有兴趣了解更多的话可以直接看这篇文章: The Difference Between URLs and URIs
这里我就直接捋一捋URI、URL、URN的关系。
首先,先看一下它们三个分别的英文全称:

  • URI : universal resource identifier
  • URL : universal resource locator
  • URN : universal resource name
    这里可以看出,URI就是一个资源的统一标志符,它既可以是定位符也可以是一个名称,因此URL、URN都属于URI。

如何区分URL和URN?

URL包含了找到资源的方法(路径)和资源名称,也就是当一个URI包含了一个访问机制或者网络位置的时候(e.g. http// or ftp://),它就是一个URL了。
URN就是一个独一无二的资源名称,它是由urn开头的一串URI。
e.g. urn:oasis:names:specification:docbook:dtd:xml:4.1.2
所以说,它们之间重要的区别就在于它的开头,也就是Scheme.

URI Schemes

大家应该都对http:// 非常熟悉,而它就是一个scheme,也就是一个url的开头部分。
有兴趣也可以去看我在之前写过一篇关于URL scheme的介绍:iOS-URL Schemes 。而有了以上概念之后,我们可以了解到,实际上scheme不仅仅可以指URL的开头,URI的开头也一样的是scheme。

那么回到正题,来讲它和deep link的关系。URI Schemes其实就是实现deep linking的第一代解决方案。利用它就可以在移动开发中实现从web页面或者别的app中唤起自己的app的功能,然而开发者们很快就发现,这样也还有很多限制:

  • 当要被唤起的app没有安装时,这个链接就会出错。
  • 当注册有多个scheme相同的时候,目前没有办法区分。

因此为了解决以上问题,苹果和安卓都有了自己的第二套解决方案,分别是iOS的Universal Link,和安卓的App Link。

Custom URL Scheme

iOS在之前的很长一段时间内用来实现deep linking以及app间通信的方法就是上面提到的,被叫做custom URL scheme。处理的方法就是:

  1. 注册一个URL type,注册的方法就是在app的info.plist文件里添加 CFBundleURLTypes 键,它包含了一个由多个字典组成的数组,每一个字典定义了这个app支持的一个URL scheme
Key Value
CFBundleURLName 一个包含了URL Scheme的抽象名字的字符串。为了保证它的唯一性,通常需要明确一个reverse-DNS的identifier,同时还应该保证它的可读性。
CFBundleURLSchemes 一个包含了多个URL Scheme names的字符串数组。
  1. 用到application:willFinishLaunchingWithOptions:application:didFinishLaunchingWithOptions:这两个方法去取回关于URL的信息同时决定是否要打开它。
  2. 在app delegate中实现入口方法:application:openURL:sourceApplication:annotation:或者application:openURL:options: 。前一个方法从iOS9后开始被淘汰,后一个方法是在iOS 9 之后引入的,若果没有实现这个方法,在iOS 9 上也还是会向前兼容调用第一个老的方法,因此现在一般还是实现老方法)。

在iOS中,所有传到app中的URL都是一个NSURL的对象,你可以定义URL的组成,但NSURL都遵守RFC 1808的一些规则,所以它支持大多数的传统URL组成规则。NSURL类中还有能够返回URL中的不同部分的方法,包括URL中的user、password、query、fragment、parameter strings等常见部分。
对于业务逻辑较少的app来说,可以直接通过url的字符串比较来区分业务逻辑。不过对于业务逻辑相对复杂,比如像现在开发团队共同维护这块逻辑的时候,就需要引入路由router来分发请求。在做上一个需求的时候有涉及,这里就不展开说了。

3. Universal Link

什么是Universal Link?

而iOS 9之后苹果推出的一个替代之前的custom URL Scheme的新概念就是Universal Link。在苹果开发者中可以看到对它的介绍是:

Seamlessly link to content inside your app, or on your website in iOS 9 or later. With universal links, you can always give users the most integrated mobile experience, even when your app isn’t installed on their device.

通俗讲,就是用了这个Universal Link,就可以让网站或者web view中的内容在用户点击跳转或安装了app之后仍然能够直接在这个app中被找到。比如,用户在官网上点击了“在app中浏览该商品”的链接,这个时候就可以通过Universal Link去唤起这个app,同时直接定位到该商品页面。

它的实现机制与之前的Deep Link相似,只不过它不是只定义一个custom URL scheme,而是匹配了多个web页面到app中相应的位置,当用户打开某个匹配的页面时,iOS会自动地将其重定向到app内。

Universal Link的好处

接下来说Universal Link厉害的地方:

  1. 之前的Custom URL scheme是自定义的协议,因此在没有安装该app的情况下是无法直接打开的。而Universal Links本身也就是一个能够指向一个web页面或者app中的内容页的标准的web link(形如https://example.com) 因此能够很好的兼容其他情况。也就是说,当已经安装了这个app的时候,不需要加载任何web页面,app就会立即启动;当这个app没有安装的时候,就会默认地从当前浏览器中重定向到App Store中引导用户去下载安装这个app。
  2. Universal links是从服务器上查询是哪个app需要被打开,因此不存在Custom URL scheme那样名字被抢占、冲突的情况。
  3. Universal links支持从其他app中的UIWebView中跳转到目标app
  4. 安全性,用universl link去打开的时候,只有你(开发这个app的人)可以通过创建和上传一个允许这个网页去通过这个URL去打开你的app的文件。
  5. 隐私性,提供Universal link给别的app进行app间的交流,然而对方并不能够用这个方法去检测你的app是否被安装。(之前的custom scheme URL的canOpenURL方法可以,具体可以看这里iOS Review-DetectScheme。)

使用Universal Link

首先,你需要创建一个 apple-app-site-association文件,它是一些JSON格式的数据,提供了你的app能够处理的URLs。然后你需要将这个文件上传到你的HTTPS web 服务器上。之后就是一些准备工作来处理这个Universal Link,有两种技术,Web Browser–to–Native App HandoffShared Web Credentials Reference

当一个用户点击了这个universal link,iOS就会启动你的app,然后会传入一个NSUserActivity的对象,让你能够查询到你的app是如何被启动的。要实现这些,你需要做以下步骤:

  • 添加一个权限(entitlement),用来具体说明你的app支持哪些域(domains)。
    具体在xcode中,就是在Capabilities栏中找到Associated Domains,在里面添加以applinks:为前缀的域。如图:
Associated Domains
  • 写app delegate的方法,使之在收到NSUserActivity对象的时候能够做出适当的响应。尤其是application:continueUserActivity:restorationHandler:

当你的app在用户点击universal link后被启动的时候,就会收到一个NSUserActivity对象,里面包括了值为NSUserActivityTypeBrowsingWeb的activityType。利用这个对象的webpageURL属性中的URL,就可以知道用户正在访问的URL地址。另外,因为这个webpageURL属性通常都会包括HTTP或者HTTPS URL,所以你还可以用NSURLComponents APIs去操纵这个URL的内容。

Universal Link的缺陷

在讲它的缺陷之前,我先介绍一下iOS的Universal link的一个机制:
在用户点击了Universal link之后,iOS会去检测用户最近一次是选择了直接打开app还是打开网站。这个选择的步骤,实际上是在用户进入了app之后,顶部bar的右侧会出现一个通过网站打开的按钮选项。如图:

bar

因此,一旦用户点击了这个选项,他就会通过safiri打开你的网站。并且在之后的操作中,默认一直延续这个选择,除非用户从你的webpage上通过点击Smart App Banner上的OPEN按钮来打开。也就是说,用户非常容易在一次选择之后,使得Universal link唤醒app的功能失效了。

4. Deferred Deep Link

然而,无论是URI Scheme还是Universal Link都没有解决一个问题,就是如果设备上没有安装这个app的时候,保留住此时用户停留的上下文。例如,利用Universal Link,在没有安装app的情况下,iOS能够重定位到app store去引导用户去下载安装这个app,但是在安装之后,app只能打开首页,也就是说丢失了用户在点击跳转进入app之前的那个页面。
因此,有了一个非常重要的另一个概念:Deferred Deep Link。顾名思义,这里的deferred是延迟的意思,可以理解为延迟一下,在安装过程中keep住跳转前的特定页面内容,在app安装之后,再利用这个link在app里进行跳转。举个例子,用户在某个电商网站上看到一个商品,于是他点击了一个按钮“在app中查看该商品”,但他并没有下载这个app,于是iOS就引导他到了App Store安装这个app,当他安装完成之后,打开这个app,就会自动地在app中跳到他刚才想看的那个商品的页面。这对于商家来说,也就大大提高了用户的转化率。

其他 Deep Link标准

这里介绍的主要都是针对于iOS开发中使用到的deep link标准,那么对应安卓开发,同样也有类似的标准,大家可以自主了解:

  • Facebook App Links
  • Android App Links
  • Chrome Intents

后话

目前,移动开发Deep Link领域实际上仍然是处于一种碎片式混乱的局面,有很多问题都还有待解决,距离达到一个工业级别的标准还很远。然而,利用现有的技术去不断优化用户的体验是每一个客户端开发工程师的使命,所以我们没有任何理由去抗拒变革,在目前没有统一的标准的情况下,我们能够做到的就是,应用不同的标准去适应所有可能的情况。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 移动互联时代,很多互联网服务都会同时具备网站以及移动客户端,很多人认为APP的能帮助建立更稳固的用户关系,于是经常...
    zyl04401阅读 43,898评论 17 72
  • 最近我们有一个 DeepLink 的需求 用的是 Branch, 在这个过程中自然会涉及到 Universal L...
    天空中的球阅读 14,938评论 10 35
  • 背景说明 通知相关的页面跳转POCT项目处于后台状态,服务器发推信息到客户端,客户端在通知栏点击消息,进入App并...
    sycasl阅读 1,274评论 0 1
  • 并不能说我已经习惯用电脑打字的手感 而忘记了笔尖与纸张摩擦碰撞所迸发出来的灵感。 只是很多时候,在各种不适的情况下...
    白鹿与小宁阅读 357评论 0 0
  • 01.平凡的忙碌 今天早上到学校门口的早餐店吃饭,进去的时候一个人都没有,我还纳闷这正饭点的怎么一个顾客都没有,后...
    宋一二阅读 3,485评论 9 18