最近我们有一个 DeepLink 的需求 用的是 Branch, 在这个过程中自然会涉及到 Universal Links 和 Custom URL Schem,在此进行笔记下,也把在用 Branch 中遇到的问题分享下。
// Respond to URI scheme links
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
// 我们需要的判断跳转
return YES;
}
// Respond to Universal Links
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
// 我们需要的判断跳转
return YES;
}
然后从下面四个点来了解下这块:
- Universal Links 和 URL Schem 基本概念的了解
- Universal Links 和 URL Schem 的用法
- Universal Links 和 URL Schem 需要的注意点
- Branch 使用中遇到的问题
一、基本了解
- URL Scheme
URL Scheme 是为方便app之间互相调用而设计的,注册自己独一的URL Scheme,然后进行交互。我们可以通过系统的OpenURL来打开该app,也可以直接通过 Safari 直接打开该 app,并可以传递参数内容。
- Universal Links
iOS 9 之后,苹果推出的通用链接:一种能够方便的通过传统 HTTP 链接来启动 APP, 使用相同的网址打开网站和 APP。
推出它,肯定有其优点: - 唯一性: 不像自定义的scheme,因为它使用标准的http/https链接到你的web站点,所以它不会被其它的app所声明.另外,Custom URL scheme 因为是自定义的协议,所以在没有安装 app 的情况下是无法直接打开的,而 universal links 本身是一个 HTTP/HTTPS 链接,所以有更好的兼容性
- 安全:当用户的手机上安装了你的app,那么iOS将去你的网站上去下载你上传上去的说明文件(这个说明文件声明了你的app可以打开哪些类型的http链接).因为只有你自己才能上传文件到你网站的根目录,所以你的网站和你的app之间的关联是安全的.
- 可变:当用户手机上没有安装你的app的时候,Universal Links也能够工作.如果你愿意,在没有安装你的app的时候,用户点击链接,会在safari中展示你网站的内容.
- 简单:一个URL链接,可以同时作用于网站和app
- 私有 其它app可以在不需要知道你的app是否安装了的情况下和你的app相互通信.
二、用法
两者代码里面其实没什么区别,主要是配置的去呗
2-1、URL Scheme
-
2-1-1、注册设置 URL Scheme
2-1-2、AppDelegate 设置
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL*)url {
// 接受传过来的参数
NSLog(@"url Scheme === %@\n url Host === %@",url.scheme,url.host);
// url Scheme === testyang url Host === testContent
return YES;
}
- 2-1-3、打开
-
Safari
App 之间
在另一个 App 中的 info Plist 中添加白名单 Url
-
<key>LSApplicationQueriesSchemes</key>
<array>
<!-- 设置我们设定的,如我们需要的URL Scheme 白名单-->
<string>testYang</string>
</array>
在另一个 APP 中 添加打开的 代码
NSString *url = @"testYang://testContent";
// NSString *url = @"testYang://com.testYang.www&testContent";
if ([[UIApplication sharedApplication]
canOpenURL:[NSURL URLWithString:url]]) {
// iOS 10 以上用这个方法,iOS 10 以下直接用 openURL 就 OK 了
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url] options:@{UIApplicationOpenURLOptionUniversalLinksOnly : @NO} completionHandler:^(BOOL success) {
NSLog(@"success");
}];
}
注意:APP URL格式为: URL Scheme://URL identifier,直接调用URL Scheme也可打开程序, URL identifier是可选的。
2-2、Universal Links
- 2-2-1、创建一个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 文件需要上传到网站根目录
* 每一个代表着应用的 字典,必须包含一个 appID 和 paths, appID 是teamID 和 bundleID,paths 是一个字符串的数组 **明确着应用支持的通用链接和应用程序不支持的通用连接内容**
Note: Don’t append .json to the apple-app-site-association
filename. (文件不要接 .json)
-
2-2-2、上传 apple-app-site-association 到服务器下
- 注意是上传到web server根目录下
- paths 路径是大小写敏感的
- paths 内容可明确哪些通用链接需要被处理,哪些不需要
- NOT 使用:为了明确指出不被处理的链接,可增加 “NOT”在链接前面
例 如 "paths":[ "/wwdc/news/"
,"NOT /videos/wwdc/2015/*"
,"/videos/wwdc/201?/*"]
- 可以使用 星号
*
明确所有的网页, 也可以使用一个明确的的 URL,例如/wwdc/news/6
, 也可以追加 星号到你的 URL ,例如/videos/wwdc/2015/*
也可以使用 星号
*
来匹配任何字符,使用?
来匹配一个字符,可以在路径 中使用这种混搭的形式, 例如/foo/*/bar/201?/mypage
-
2-2-3、App 内的处理
-
2-2-3-1、在targets->Capabilities->Associated Domains中打开Associated,然后系统会自动帮你写入.entitlements文件,所以不需要自己去手动加。需要注意的是,有人遇到过.entitlements文件没有被加入工程的,这也会产生问题,需要手动把.entitlements加入工程。
- 2-2-3-2、代码内的处理 AppDelegate 中
-
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
// 我们需要的判断跳转
return YES;
}
- 2-2-3-4、在 证书中心的处理
进入苹果Apple Developer --- Member Center - Certificates, Identifiers & Profiles – Identifiers - App IDs –Edit 然后开启打钩 Associated Domains 后保存,但此处我这边自动成了。
如有不清晰,可以再看这个翻译iOS Universal Links(通用链接)还是很仔细的。
三、注意点
- URL Scheme
- URL identifier 的唯一性
- iOS9 之后的白名单
- iOS 10 之后的 OpenURL 的被弃用
- Universal Links
- 域名可通过 SSL 访问 (需要有效的证书)
- 支持上传一个 JSON 文件到域名(
apple-app-site-association
) - iPhone 至少 iOS 9.2 以上
- 至少 Xcode 7 以上
- 需要真机测试, 模拟器不支持通用链接
- web server 需要支持 https,客户端需要通告 https 访问,并且不支持任何重定向
总的说来,URL Scheme慢慢会退出舞台,然后是Universal Links 登上台面的时候。PS: 苹果验证Universal Links URL 是否正确的网址。
四、Branch DeepLink 使用中遇到的问题
作为国外常用的 Branch,国内目前基本应该不太用的,整体说来其文档相对来说,还是很清晰的,只是之前一直有两点困扰我的:
- 如何自定义类型做判断跳转
一直跳转不成功,设置好URL ,始终从Web 页面跳转不到 APP, 只往AppStore 走
1、如何自定义类型做判断跳转,因为它不同于系统的,直接在
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;
}
但这是第一层,以前我们判断就是拿到这个 url 就是直接去判断,然后跳转到我们想走的跳转路线,但是此处呢?
[branch initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
if (!error && params) {
NSLog(@"params: %@", params.description);
if ([params[@"+clicked_branch_link"] boolValue]) { // 此处代表是 branch_link 点击进入的情况
[DeepLinkManager branchDeepLinkWithParams:params];
}
}
}];
- 2、一直跳转不成功,设置好URL ,始终从Web 页面跳转不到 APP, 只往 AppStore 走。
注意 Branch 文档中的 Link Domain 设置 Associated Domains 错误啦。
而且通过 branch 的测试 URL 是满足条件的 UNIVERSAL LINKS VALIDATOR。但是在苹果验证Universal Links URL 是否正确的网址上却是错误的:
**cannot fetch app site association **
这就尴尬了,branch 处是OK的,apple 提示Universal Links是错误的。但同时也说明 URL Scheme 设置是对的,否则会单单直接报出一个 “Error: cannot fetch app site association ” 的错误。
所以说,此时的问题又回归到 Universal Links 没设置对的原因,没能正确上传好app site association,但是此处使用的是 Branch, 这个设置 Universal Links 就是按 Branch 流程 上面走的,这样就略显尴尬啦,一下子原因找不到,卡了好久。
解决步骤1: 到 https://domian.com/apple-app-site-association
看是否正确,当然用 Branch 的话是https://domian.app.link/apple-app-site-association
, 结果发现这是存在的,但是内容有点不一样 path
"paths": [
"NOT /e/*",
"*",
"/"
]
然后我对比了下经典的例子收集 list-of-universal-link,继续寻找中...
解决步骤2: 直接向 branch 邮箱求助,那边的工作人员会给出很详细的解答步骤,第一次没有解决,现在等待第二次邮件回复...
解决步骤3: 硬是不行,再重新弄一个账号尝试,对比过程是否有遗漏的东东...
PS: 最终解决:
通过邮件得知,苹果那边的那个验证没有通过其实也是OK的, 所以那里可以忽略。
只是之前设置的时候,设置错误了..
注意 branch_key 直接设置,注意 test 和 live 的区别,但是其实可以直接 不用 dictionary, 而用 string, 因为我暂时设置成 Debug 状态下有时是无效的,所以直接用string ,到时替换就好了。
另外出现这个问题也可以看看 Stack Overflow 的回答:iOS9: Universal Links does not work。
话说起来这也是一个自己熟悉陌生英文文档的过程,可以多来几次,这一两天全是英文文档感觉英语都提高了,😆,只是希望下次效率可以更高一些。说白了,所有问题都是文档没弄清晰的原因。
PS : 再次补充:
有些情况下,在 FaceBook、 QQ、微博 用的是本身的浏览器,都有其限制的,此时我们直接用 DeepView , 方能解决,否则会一直跳转到 AppStore 去的。
五、总结
其实总的来说,想了解更详细的直接看苹果官方文档就OK 了。
往往出错是在看文档的时候忽略一些细节!明显是在就是翻译文档,😌,但还翻译错了,或者说理解错了......
备注:
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(通用链接)