0x00 引言
為了推廣產(chǎn)品,產(chǎn)品通常會設(shè)計一個二維碼,掃描這個二維碼進入一個H5頁面,H5頁面中提供一個鏈接按鈕,點擊這個按鈕或者直接調(diào)起應(yīng)用或者跳轉(zhuǎn)至AppStore引導下載。
在國內(nèi),微信基本上已經(jīng)變成了事實上的掃碼工具(不得不說,微信的掃碼模塊算法優(yōu)化的非常強悍,速度和識別率絕對是首屈一指),所有我們設(shè)計的H5頁面絕大多數(shù)情況下是在微信中展示。因此我們研究的重點也會側(cè)重于從微信中調(diào)起應(yīng)用的方法。
下面會介紹幾種從H5中調(diào)起iOS應(yīng)用的幾種方法。
0x01 URL Scheme
由于蘋果的app都是在沙盒中,相互是不能訪問數(shù)據(jù)的。但是蘋果還是給出了一個可以在app之間跳轉(zhuǎn)的方法:URL Scheme。簡單的說,URL Scheme就是一個可以讓app相互之間可以跳轉(zhuǎn)的協(xié)議。
我們所使用的每一個app就相當于一個功能,app的跳轉(zhuǎn)可以使得每個app就像一個功能組件一樣,幫助我們完成需要做的事情,比如三方支付,搜索,導航,分享等等。
官方的參考文檔:About Apple URL Scheme
在iOS系統(tǒng)中,通過URL Scheme的方式啟動應(yīng)用和參數(shù)的傳遞的步驟如下。
1 創(chuàng)建URL Scheme
首先在Info.plist中添加一行,選擇URL types;
在展開的Item 0中填寫URL identifier,這個用來唯一標識用戶自定義的URL Scheme,推薦使用域名的反轉(zhuǎn)形式,如:com.tsingwill.mylink;
在Item 0中添加新的一行,選擇URL Schemes, 展開URL Schemes,在Item 0中輸入自定義的Scheme的名稱。在這里只需要輸入自定義的Scheme的名稱即可,不需要加上://,例如這里輸入的是mylink,那么對應(yīng)的自定義的URL就是mylink://,這里可以輸入多個。
完整的示例圖如下:

2 使用URL Scheme
(1)在Safari中直接在瀏覽器的地址欄中輸入mylink://,即可啟動剛才的應(yīng)用;
(2)在其他的應(yīng)用程序中使用,在需要調(diào)用的地方使用下面的代碼即可實現(xiàn)調(diào)用。
NSString *customURL = @"mylink://";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:customURL]];
如果需要傳遞參數(shù),可以通過?傳遞,例如:
- (void)openOtherApp
{
NSString *customURL = @"mylink://?token=123abct®istered=1";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:customURL]];
}
(3)在AppDelegate中可以實現(xiàn)下面的代理方法
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
if ([sourceApplication isEqualToString:@"com.devzeng.demo.urlscheme"]) {
NSLog(@"調(diào)用的應(yīng)用程序的Bundle ID是: %@", sourceApplication);
NSLog(@"URL scheme:%@", [url scheme]);
NSLog(@"URL query: %@", [url query]);
return YES;
} else {
return NO;
}
}
3 URL Scheme的限制
設(shè)計好H5頁面并且配置了URL Scheme后,迫不及待地拿出微信掃下試試,結(jié)果發(fā)現(xiàn)并沒有效果。原來微信對第三方應(yīng)用的URL Scheme進行了屏蔽,只有加入白名單(交錢)后的URL Scheme才會被放行(可能微信的初衷是防止有人借助于微信平臺惡意推廣營銷)。
如果不想合(交)作(錢),我們只能在H5頁面中放上一個條件蒙版:如果是在微信中打開的H5,就展示蒙版,提示用戶點擊右上角“通過Safari打開”。
0x02 Universal Link
1 What is Universal Links?
通用鏈接:一種能夠方便的通過傳統(tǒng)HTTP鏈接來啟動APP, 使用相同的網(wǎng)址打開網(wǎng)站和APP,旨在打造無縫鏈接APP的體驗。首次出現(xiàn)在2015 WWDC上, 是Apple為iOS 9宣布的一個所謂通用鏈接的深層鏈接特性。
2 配置支持Universal Link
(1)Universal Link最低支持iOS9。
(2)添加域名到 Capabilities。
Associated Domains設(shè)置為Enable
設(shè)置Capabilities -> Associated Domains ,例如:
applinks:domain.tsingwill.com

(3)創(chuàng)建apple-app-site-association文件
apple-app-site-association是一個純文本json文件(注意不包含josn后綴名), 放置于服務(wù)器的/.well-known目錄(開發(fā)者需要自己想辦法搞一個https服務(wù)器)。例如:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "F7*******.com.tsingwill.mylink",
"paths":[ "/mylink/*" ]
}
]
}
}
(4)前端調(diào)起方式
前端(H5)可以通過標準的HTTPS的方式進行調(diào)起,例如:
https://domian.tsingwill.com/mylink/scan
如果想要傳遞參數(shù),同樣可以通過?的方式進行傳遞。
(5)APPDelegate中響應(yīng)回調(diào)
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
if (![userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
return YES;
}
NSURL *webUrl = userActivity.webpageURL;
// do what else about NSURL
}
(6)Universal Link的問題梳理
Universal Link是從iOS9開始支持的。但在iOS9.2中,蘋果調(diào)整了一些規(guī)則(估計也是防止惡意推廣鏈接),從iOS 9.2開始,在相同的domain內(nèi)Universal Links是不work的,必須要跨域才生效,我們實測值需要跨子域名即可,比如 m.domain.com 跳轉(zhuǎn) o.domain.com 是可以觸發(fā)跳轉(zhuǎn)App。從iOS 9.2開始,直接把 Universal Link 拷貝到 Safari 的地址欄是無效的,在相同的 domain 內(nèi) Universal Links 是無效的,通過 js 調(diào)用也是無效的,真的是醉了。
(7)Universal Link的完整流程

0x03 URL Scheme + Universal Link
現(xiàn)階段還是要提供對iOS8的支持,開發(fā)時可以對URL Scheme和Universal Link都提供支持,前端調(diào)用時判斷系統(tǒng)的版本,如為iOS9以下則采用URL Scheme的方式調(diào)用,若為iOS9+則采用Universal Link的方式調(diào)用。
0x04 關(guān)于WXAppExtendObject
微信提供了SDK,成為付費開發(fā)者后,可以通過WXAppExtendObject中提供的API讓自己的應(yīng)用成為白名單應(yīng)用。
0x05 使用第三方提供的方案
魔窗,企業(yè)級深度鏈接(Deeplink)解決方案,讓App能像Web一樣通過URL進行任意內(nèi)容的分發(fā)、管理和一鏈直達 ,一鍵喚醒App內(nèi)指定頁。實質(zhì)上也是對Universal Link等方式的包裝,并提供WEB服務(wù)器,開發(fā)者無需再自己搭服務(wù)器。具體使用可參考魔窗