理解Deep Link & URI Schemes & Universal Link & App Link
https://www.jianshu.com/p/909999e398e6
引言
最近在做客戶端開發的工作中,需要解決一些渠道流量監控的問題。發現在喚醒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。處理的方法就是:
- 註冊一個URL type,註冊的方法就是在app的info.plist檔案裡新增 CFBundleURLTypes 鍵,它包含了一個由多個字典組成的陣列,每一個字典定義了這個app支援的一個URL scheme
Key | Value |
---|---|
CFBundleURLName | 一個包含了URL Scheme的抽象名字的字串。為了保證它的唯一性,通常需要明確一個reverse-DNS的identifier,同時還應該保證它的可讀性。 |
CFBundleURLSchemes | 一個包含了多個URL Scheme names的字串陣列。 |
- 用到
application:willFinishLaunchingWithOptions:
和application:didFinishLaunchingWithOptions:
這兩個方法去取回關於URL的資訊同時決定是否要開啟它。 - 在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厲害的地方:
- 之前的Custom URL scheme是自定義的協議,因此在沒有安裝該app的情況下是無法直接開啟的。而Universal Links本身也就是一個能夠指向一個web頁面或者app中的內容頁的標準的web link(形如https://example.com) 因此能夠很好的相容其他情況。也就是說,當已經安裝了這個app的時候,不需要載入任何web頁面,app就會立即啟動;當這個app沒有安裝的時候,就會預設地從當前瀏覽器中重定向到App Store中引導使用者去下載安裝這個app。
- Universal links是從伺服器上查詢是哪個app需要被開啟,因此不存在Custom URL scheme那樣名字被搶佔、衝突的情況。
- Universal links支援從其他app中的UIWebView中跳轉到目標app
- 安全性,用universl link去開啟的時候,只有你(開發這個app的人)可以通過建立和上傳一個允許這個網頁去通過這個URL去開啟你的app的檔案。
- 隱私性,提供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 Handoff 和 Shared Web Credentials Reference。
當一個使用者點選了這個universal link,iOS就會啟動你的app,然後會傳入一個NSUserActivity的物件,讓你能夠查詢到你的app是如何被啟動的。要實現這些,你需要做以下步驟:
- 新增一個許可權(entitlement),用來具體說明你的app支援哪些域(domains)。
具體在xcode中,就是在Capabilities欄中找到Associated Domains,在裡面新增以applinks:為字首的域。如圖:
- 寫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的右側會出現一個通過網站開啟的按鈕選項。如圖:
因此,一旦使用者點選了這個選項,他就會通過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領域實際上仍然是處於一種碎片式混亂的局面,有很多問題都還有待解決,距離達到一個工業級別的標準還很遠。然而,利用現有的技術去不斷優化使用者的體驗是每一個客戶端開發工程師的使命,所以我們沒有任何理由去抗拒變革,在目前沒有統一的標準的情況下,我們能夠做到的就是,應用不同的標準去適應所有可能的情況。
作者:Edie小哪吒
連結:https://www.jianshu.com/p/909999e398e6
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。