最近我們有一個(gè) DeepLink 的需求 用的是 Branch, 在這個(gè)過程中自然會涉及到 Universal Links 和 Custom URL Schem,在此進(jìn)行筆記下,也把在用 Branch 中遇到的問題分享下。
// Respond to URI scheme links
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
// 我們需要的判斷跳轉(zhuǎn)
return YES;
}
// Respond to Universal Links
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
// 我們需要的判斷跳轉(zhuǎn)
return YES;
}
然后從下面四個(gè)點(diǎn)來了解下這塊:
- Universal Links 和 URL Schem 基本概念的了解
- Universal Links 和 URL Schem 的用法
- Universal Links 和 URL Schem 需要的注意點(diǎn)
- Branch 使用中遇到的問題
一、基本了解
- URL Scheme
URL Scheme 是為方便app之間互相調(diào)用而設(shè)計(jì)的,注冊自己獨(dú)一的URL Scheme,然后進(jìn)行交互。我們可以通過系統(tǒng)的OpenURL來打開該app,也可以直接通過 Safari 直接打開該 app,并可以傳遞參數(shù)內(nèi)容。
- Universal Links
iOS 9 之后,蘋果推出的通用鏈接:一種能夠方便的通過傳統(tǒng) HTTP 鏈接來啟動 APP, 使用相同的網(wǎng)址打開網(wǎng)站和 APP。
推出它,肯定有其優(yōu)點(diǎn): - 唯一性: 不像自定義的scheme,因?yàn)樗褂脴?biāo)準(zhǔn)的http/https鏈接到你的web站點(diǎn),所以它不會被其它的app所聲明.另外,Custom URL scheme 因?yàn)槭亲远x的協(xié)議,所以在沒有安裝 app 的情況下是無法直接打開的,而 universal links 本身是一個(gè) HTTP/HTTPS 鏈接,所以有更好的兼容性
- 安全:當(dāng)用戶的手機(jī)上安裝了你的app,那么iOS將去你的網(wǎng)站上去下載你上傳上去的說明文件(這個(gè)說明文件聲明了你的app可以打開哪些類型的http鏈接).因?yàn)橹挥心阕约翰拍苌蟼魑募侥憔W(wǎng)站的根目錄,所以你的網(wǎng)站和你的app之間的關(guān)聯(lián)是安全的.
- 可變:當(dāng)用戶手機(jī)上沒有安裝你的app的時(shí)候,Universal Links也能夠工作.如果你愿意,在沒有安裝你的app的時(shí)候,用戶點(diǎn)擊鏈接,會在safari中展示你網(wǎng)站的內(nèi)容.
- 簡單:一個(gè)URL鏈接,可以同時(shí)作用于網(wǎng)站和app
- 私有 其它app可以在不需要知道你的app是否安裝了的情況下和你的app相互通信.
二、用法
兩者代碼里面其實(shí)沒什么區(qū)別,主要是配置的去唄
2-1、URL Scheme
-
2-1-1、注冊設(shè)置 URL Scheme
注冊設(shè)置 URL Scheme 2-1-2、AppDelegate 設(shè)置
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL*)url {
// 接受傳過來的參數(shù)
NSLog(@"url Scheme === %@\n url Host === %@",url.scheme,url.host);
// url Scheme === testyang url Host === testContent
return YES;
}
- 2-1-3、打開
-
Safari
Safari 輸入
彈出提示框,TestUrlScheme 是 app 名字 App 之間
在另一個(gè) App 中的 info Plist 中添加白名單 Url
-
<key>LSApplicationQueriesSchemes</key>
<array>
<!-- 設(shè)置我們設(shè)定的,如我們需要的URL Scheme 白名單-->
<string>testYang</string>
</array>
在另一個(gè) APP 中 添加打開的 代碼
NSString *url = @"testYang://testContent";
// NSString *url = @"testYang://com.testYang.www&testContent";
if ([[UIApplication sharedApplication]
canOpenURL:[NSURL URLWithString:url]]) {
// iOS 10 以上用這個(gè)方法,iOS 10 以下直接用 openURL 就 OK 了
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url] options:@{UIApplicationOpenURLOptionUniversalLinksOnly : @NO} completionHandler:^(BOOL success) {
NSLog(@"success");
}];
}
注意:APP URL格式為: URL Scheme://URL identifier,直接調(diào)用URL Scheme也可打開程序, URL identifier是可選的。
2-2、Universal Links
- 2-2-1、創(chuàng)建一個(gè)json 格式的apple-app-site-association
{
"applinks": {
"apps": [],
"details": [
{
"appID": "9JA89QQLNQ.com.apple.wwdc",
"paths": [ "/wwdc/news/", "/videos/wwdc/2015/*"]
},
{
"appID": "ABCD1234.com.apple.wwdc",
"paths": [ "*" ]
}
]
}
}
* “appID”組成部分:TeamID + BundleId TeamID
* BundleId 一定要和 APP 的 BundleId 一致。
* apple-app-site-association 文件不能帶后綴
* apple-app-site-association 文件需要上傳到網(wǎng)站根目錄
* 每一個(gè)代表著應(yīng)用的 字典,必須包含一個(gè) appID 和 paths, appID 是teamID 和 bundleID,paths 是一個(gè)字符串的數(shù)組 **明確著應(yīng)用支持的通用鏈接和應(yīng)用程序不支持的通用連接內(nèi)容**
Note: Don’t append .json to the apple-app-site-association
filename. (文件不要接 .json)
-
2-2-2、上傳 apple-app-site-association 到服務(wù)器下
- 注意是上傳到web server根目錄下
- paths 路徑是大小寫敏感的
- paths 內(nèi)容可明確哪些通用鏈接需要被處理,哪些不需要
- NOT 使用:為了明確指出不被處理的鏈接,可增加 “NOT”在鏈接前面
例 如 "paths":[ "/wwdc/news/"
,"NOT /videos/wwdc/2015/*"
,"/videos/wwdc/201?/*"]
- 可以使用 星號
*
明確所有的網(wǎng)頁, 也可以使用一個(gè)明確的的 URL,例如/wwdc/news/6
, 也可以追加 星號到你的 URL ,例如/videos/wwdc/2015/*
也可以使用 星號
*
來匹配任何字符,使用?
來匹配一個(gè)字符,可以在路徑 中使用這種混搭的形式, 例如/foo/*/bar/201?/mypage
-
2-2-3、App 內(nèi)的處理
-
2-2-3-1、在targets->Capabilities->Associated Domains中打開Associated,然后系統(tǒng)會自動幫你寫入.entitlements文件,所以不需要自己去手動加。需要注意的是,有人遇到過.entitlements文件沒有被加入工程的,這也會產(chǎn)生問題,需要手動把.entitlements加入工程。
打開Associated - 2-2-3-2、代碼內(nèi)的處理 AppDelegate 中
-
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
// 我們需要的判斷跳轉(zhuǎn)
return YES;
}
- 2-2-3-4、在 證書中心的處理
進(jìn)入蘋果Apple Developer --- Member Center - Certificates, Identifiers & Profiles – Identifiers - App IDs –Edit 然后開啟打鉤 Associated Domains 后保存,但此處我這邊自動成了。
Associated Domains
如有不清晰,可以再看這個(gè)翻譯iOS Universal Links(通用鏈接)還是很仔細(xì)的。
三、注意點(diǎn)
- URL Scheme
- URL identifier 的唯一性
- iOS9 之后的白名單
- iOS 10 之后的 OpenURL 的被棄用
- Universal Links
- 域名可通過 SSL 訪問 (需要有效的證書)
- 支持上傳一個(gè) JSON 文件到域名(
apple-app-site-association
) - iPhone 至少 iOS 9.2 以上
- 至少 Xcode 7 以上
- 需要真機(jī)測試, 模擬器不支持通用鏈接
- web server 需要支持 https,客戶端需要通告 https 訪問,并且不支持任何重定向
總的說來,URL Scheme慢慢會退出舞臺,然后是Universal Links 登上臺面的時(shí)候。PS: 蘋果驗(yàn)證Universal Links URL 是否正確的網(wǎng)址。
四、Branch DeepLink 使用中遇到的問題
作為國外常用的 Branch,國內(nèi)目前基本應(yīng)該不太用的,整體說來其文檔相對來說,還是很清晰的,只是之前一直有兩點(diǎn)困擾我的:
- 如何自定義類型做判斷跳轉(zhuǎn)
一直跳轉(zhuǎn)不成功,設(shè)置好URL ,始終從Web 頁面跳轉(zhuǎn)不到 APP, 只往AppStore 走
1、如何自定義類型做判斷跳轉(zhuǎn),因?yàn)樗煌谙到y(tǒng)的,直接在
openURL
中做判斷,而是先要用其SDK 提供的方法。
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
[[Branch getInstance] handleDeepLink:url];
return YES;
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
BOOL handledByBranch = [[Branch getInstance] continueUserActivity:userActivity];
return handledByBranch;
}
但這是第一層,以前我們判斷就是拿到這個(gè) url 就是直接去判斷,然后跳轉(zhuǎn)到我們想走的跳轉(zhuǎn)路線,但是此處呢?
[branch initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
if (!error && params) {
NSLog(@"params: %@", params.description);
if ([params[@"+clicked_branch_link"] boolValue]) { // 此處代表是 branch_link 點(diǎn)擊進(jìn)入的情況
[DeepLinkManager branchDeepLinkWithParams:params];
}
}
}];
- 2、一直跳轉(zhuǎn)不成功,設(shè)置好URL ,始終從Web 頁面跳轉(zhuǎn)不到 APP, 只往 AppStore 走。
注意 Branch 文檔中的 Link Domain 設(shè)置 Associated Domains 錯(cuò)誤啦。
而且通過 branch 的測試 URL 是滿足條件的 UNIVERSAL LINKS VALIDATOR。但是在蘋果驗(yàn)證Universal Links URL 是否正確的網(wǎng)址上卻是錯(cuò)誤的:
**cannot fetch app site association **
cannot fetch app site association
這就尷尬了,branch 處是OK的,apple 提示Universal Links是錯(cuò)誤的。但同時(shí)也說明 URL Scheme 設(shè)置是對的,否則會單單直接報(bào)出一個(gè) “Error: cannot fetch app site association ” 的錯(cuò)誤。
所以說,此時(shí)的問題又回歸到 Universal Links 沒設(shè)置對的原因,沒能正確上傳好app site association,但是此處使用的是 Branch, 這個(gè)設(shè)置 Universal Links 就是按 Branch 流程 上面走的,這樣就略顯尷尬啦,一下子原因找不到,卡了好久。
解決步驟1: 到 https://domian.com/apple-app-site-association
看是否正確,當(dāng)然用 Branch 的話是https://domian.app.link/apple-app-site-association
, 結(jié)果發(fā)現(xiàn)這是存在的,但是內(nèi)容有點(diǎn)不一樣 path
"paths": [
"NOT /e/*",
"*",
"/"
]
然后我對比了下經(jīng)典的例子收集 list-of-universal-link,繼續(xù)尋找中...
解決步驟2: 直接向 branch 郵箱求助,那邊的工作人員會給出很詳細(xì)的解答步驟,第一次沒有解決,現(xiàn)在等待第二次郵件回復(fù)...
解決步驟3: 硬是不行,再重新弄一個(gè)賬號嘗試,對比過程是否有遺漏的東東...
PS: 最終解決:
通過郵件得知,蘋果那邊的那個(gè)驗(yàn)證沒有通過其實(shí)也是OK的, 所以那里可以忽略。
只是之前設(shè)置的時(shí)候,設(shè)置錯(cuò)誤了..
注意 branch_key 直接設(shè)置,注意 test 和 live 的區(qū)別,但是其實(shí)可以直接 不用 dictionary, 而用 string, 因?yàn)槲視簳r(shí)設(shè)置成 Debug 狀態(tài)下有時(shí)是無效的,所以直接用string ,到時(shí)替換就好了。
另外出現(xiàn)這個(gè)問題也可以看看 Stack Overflow 的回答:iOS9: Universal Links does not work。
話說起來這也是一個(gè)自己熟悉陌生英文文檔的過程,可以多來幾次,這一兩天全是英文文檔感覺英語都提高了,??,只是希望下次效率可以更高一些。說白了,所有問題都是文檔沒弄清晰的原因。
PS : 再次補(bǔ)充:
有些情況下,在 FaceBook、 QQ、微博 用的是本身的瀏覽器,都有其限制的,此時(shí)我們直接用 DeepView , 方能解決,否則會一直跳轉(zhuǎn)到 AppStore 去的。
五、總結(jié)
其實(shí)總的來說,想了解更詳細(xì)的直接看蘋果官方文檔就OK 了。
往往出錯(cuò)是在看文檔的時(shí)候忽略一些細(xì)節(jié)!明顯是在就是翻譯文檔,??,但還翻譯錯(cuò)了,或者說理解錯(cuò)了......
備注:
URL Scheme步驟詳解
Using URL Schemes to Communicate with Apps
Support Universal Links
ios-branch-deep-linking
iOS 9 by Tutorials 筆記(三)
Deferred Deep Linking in iOS
iOS Universal Links(通用鏈接)