背景
去年12月4日,Apple CEO Tim Cook 和王興共同出現在上海的一家老字號生煎店“大壺春”,現場用大眾點評App體驗了iOS 11新功能,包括用地圖找店訂座、用相機掃碼點餐及Apple Pay付款等一條龍便利服務。
在今年的WWDC上,大眾點評App更進一步:Apple技術人員在“Create Great Customer Experience Using Wallet and Apple Pay”演講中專門重點演示瞭如何用iPhone相機直接掃碼點餐下單,並使用Apple Pay支付閉環的全流程。這背後的技術是怎麼實現的呢?
實現方案
相機掃碼
從iOS 7開始,系統就通過AVFoundation賦予了App“相機掃碼”的能力。不過當時只能通過程式碼的形式,構建AVCaptureDevice,並設定輸出型別為AVMetadataObjectTypeQRCode,來實現在App內部的二維碼識別。 然而,整個iOS系統在此後的幾年一直沒有系統級的掃碼入口,直到iOS 11釋出,Apple終於在系統“相機”App內提供了二維碼掃描識別並跳轉到對應URL的能力。
Universal-Link
Universal-Link是iOS 9之後推出的,可以實現URL和App之間的無縫連線,在此之前是自定義的URL Scheme。和自定義URL Scheme對比,Universal-Link有如下優勢:
- 唯一性:Universal-Link使用標準的HTTP協議URL,擁有唯一性。
- 安全性:App可以控制處理哪些URL。
- 簡單靈活:URL對於H5和App是通用的,如果沒有安裝App,就會跳轉到Safari開啟對應H5。
- 私密性:在跳轉之前並不需要知道使用者是否安裝目標App。
結合“相機掃碼”和Universal-Link,我們就可以做到從系統“相機掃碼”直接喚起App了。
具體方案:將一個Universal-Link連結對應的二維碼作為物料投放,使用者直接使用系統“相機”掃描此二維碼,如果裝有大眾點評App,會出現“是否用大眾點評開啟”的提示框,點選即進入App。如下所示:
面臨挑戰
上述方案是我們基於iOS系統現有能力做出的最佳實踐,然而現實世界總有很多“意外驚喜”等待著我們:
- 物料已經大規模投放出去了,沒辦法修改怎麼辦?
- 整個流程發起是通過“相機掃碼”進行,業務如何知道入口在哪?
- Universal-Link在微信裡不能跳怎麼辦?
我們知道Universal-Link的生效主要依賴兩部分:
- AppTarget的Capabilities中配置的Associated Domains,用以控制Universal-Link下的Domain。
- 部署在WebServer上的Apple-App-Site-Association,用以控制對應Domain下的Path。
也就是說,在大型工程化專案中使用Universal-Link,URL必須遵循一定的規則,才能做到所有業務共同使用互不干擾,點評App在引入Universal-Link時也制定了使用規範。
然而由於對應的物料已經大量投放,物料中二維碼的URL在投放時並沒有考慮Universal-Link的適配,無法遵循上面的“最佳實踐”,而重新更換物料的成本又非常高,時間上也不允許。
所以我們只好“另闢蹊徑”實現這個功能了。由於Universal-Link本身對URL沒有任何限制,理論上我們可以通過部署配置把任意一條URL變成Universal-Link。
這樣一來,投放出去的物料二維碼就無法遵循我們已經定義好的Universal-Link使用規範,但這也是我們必須接受的“妥協”,在區域性犧牲一些規範性換來重要功能的實現。
事情到此還沒有完全結束,這種實現方式會帶來另一個問題:這條物料二維碼對應URL在WebView內開啟的行為會發生改變。
按照Apple官方的解釋:Universal-Link由使用者“主動”觸發,例如在郵件,記事本或是其它App中通過openURL喚起App開啟這個URL;而如果使用者處在Safari瀏覽器內直接輸入或是點選連結開啟這個URL,系統會在同源(Domain)頁面下直接開啟,非同源頁面則會直接喚起App。
換句話說,如果在App內的WebView開啟非同源某個頁面,然後又在這個頁面上點選了Universal-Link連結,這會變成一次對系統openURL方法的直接呼叫,如果不做處理有可能會跳出App,即使處理過大部分App也會在此時開啟一個新的頁面。
這顯然不是我們希望得到的結果,但我們又必須將這些URL配置成Universal-Link。最終在非常困難的情況下,我們和業務同學達成共識:對於這批特殊的投放物料二維碼,業務系統保證URL使用場景的唯一性,不會在除二維碼之外的其它場景使用這批特徵URL,繞過App內WebView開啟異常的Case。
這樣我們完成了“對於既有投放二維碼的iOS相機掃碼喚起App”實現。
在這個特殊的場景中,整個流程的發起始自於App外,業務非常需要了解當前處於“相機掃碼喚起App”的場景。
遺憾的是iOS系統除了userActivity的相關回撥之外,並沒有一個明確的App啟動路徑標識,我們只能知道App是通過Universal-Link的方式被喚醒了。
由於啟動節點在App控制權範圍以外,任何Native埋點的方式都不能在此時生效,我們唯一可以拿到的是那條被喚醒的URL,缺乏足夠的上下文可能是所有啟動相關業務最難以處理的部分。
由於問題1的解決,我們知道這條URL在App Scope內是有場景唯一性的,所以我們可以據此來比較Tricky的判斷當前的場景。 拿到當前啟動場景標識之後,就要考慮如何告知業務。
最簡單的方式就是通過修改URL,告知業務具體特徵,但作為一個通用平臺型App直接修改業務方的原始URL顯然不是合適的行為,而且可能造成不必要的麻煩,Header,Cookie,JSBridge等都可以考慮作為與H5的通訊方式。
到此為止,我們完成了“從系統相機掃碼喚起App進入相應頁面”。然而,在國內微信才是各種二維碼最大的掃描入口,在今年的1月份,微信徹底關閉了Universal-Link的跳轉行為,任何Universal-Link在微信裡都不能往外跳了。
“撿了芝麻,丟了西瓜”,這個ROI對我們來說過於沉重不能接受。考慮在Universal-Link誕生以前,我們都是通過openSchema的方式喚起App,“綜合連結”是當時H5在微信喚起App的主要方式,我們可以在Universal-Link頁面內再套一層綜合連結,並在此區分使用者場景,完成從微信喚起App的“初心”。
結語
大眾點評App參與了過去多屆WWDC的現場演示,從iOS 6的PassKit開始,經歷Flat Design,MessageKit,MapKit,SiriKit,ApplePay到WWDC2018的ApplePay閃付。我們積累了豐富的與Apple溝通合作經驗,既有駐場Apple Campus的封閉式開發,也有在IAPM的Face2Face,更多時候是在安化路492號的遠端合作。
通常BD同學都會基於點評App現有功能和Apple提供的新能力,找到需求點。這種基於外部系統升級適配的二次開發,總會遇到各種問題。有些問題會比較容易可以直接解決,有些問題會挑戰我們設定的邊界需要我們做出妥協,還有些問題無法正面突破只能規避。
二進位制世界總是由輸入,計算,輸出來定義。合理規劃整體架構,明確劃分輸入輸出邊界,儘量減少外部依賴,可以讓我們在缺少上下文,不能端到端掌控整體流程的情況下依舊遊刃有餘。
團隊介紹
點評平臺移動研發中心總體負責大眾點評APP。依託平臺能力,我們不斷輸出高質量服務:Shark,Picasso,Logan,MCI,移動之家,Appkit等,在這裡和“最好的合作伙伴“以“最嚴格的標準”做“最複雜的業務”,經受考驗,砥礪前行,共同打造業界領先的移動開發團隊。
如果對我們團隊感興趣,可以關注我們的專欄。