背景
我们在开发中经常会遇到从微信、从网页、从自家App中打开另外一个App的需求,并且要求跳转到指定页面,并继续完成后续业务。唤起App三种方案对比:
1、URL Scheme
a、配置
b、调用
优点:
十分简单,在plist文件中配置一个scheme,点击短信中的scheme或者将scheme输入到浏览器中就可以直接跳到App中。
缺点:
当手机上没有安装App时,短信中点击scheme会没有反应,浏览器中会访问失败;而且这种方式不太安全;对于唤起后跳转到App指定页面的这种方式拓展性不强。(而且在微信和QQ中这种方式是被禁用的)
2、写一个网页
H5唤起APP指南
在短信中点击链接,直接跳转到网页(引导下载页),在网页中判断是iOS端还是安卓端,然后自动跳转对应的scheme,如果手机上安装了App,则直接跳到App,如果没有安装App,则停留在当前网页,在网页上有一个去下载的按钮,点击按钮可以去苹果商店下载App。
在h5页面中判断是否成功唤起:
如果从h5页面唤起了App的话,页面就会进入后台运行,会触发h5页面的 visibilitychange 事件。如果触发了,则表明页面被成功唤起。
3、Universal Link (通用链接) - 最低支持iOS9
现在App都是最低支持iOS9了,可以直接用Universal Link替换URL Scheme了。
优点:
· 唯一性: 它使用标准的 https 链接到你的web站点,所以它不会被其它的App所声明。
· 安全: 只有你自己才能上传文件到你网站的根目录,所以你的网站和你的App之间的关联是安全的。iOS会去你的网站上去下载你上传上去的说明文件(这个说明文件声明了你的App可以打开哪些类型的https链接)。
· 可变: Universal Links本身是一个 https 链接,当用户手机上没有安装你的App的时候也能够工作。此时点击链接会跳转到safari中展示你网页。
· 简单: 一个URL链接,可以同时作用于网站和App。
· 私有: 其它App可以在不需要知道你的App是否安装了的情况下和你的App相互通信.
一、Universal Link的基本运作流程
App第一次启动、更新版本后第一次启动,都会自动下载 apple-app-site-association 配置文件
· 下载 - App向工程里配置的域名发起Get请求拉取配置好存放在https服务器上的配置文件
· 注册 - App将配置文件注册给手机系统
· 命中 - 由任意h5、或其他App发起的跳转url,如果命中了配置文件注册过的通用链接,就打开App
· 没命中 - 直接跳转url链接对应的h5页面
二、Universal Link配置 - 开发步骤
1、开发者账号配置:
打开证书页面,找到Identifiers下App IDs下自己的证书;勾选 Associated Domains
2、Xcode配置:
在Capabilities选项下打开Associated Domains;在Domains中填入你想支持的域名(存放打开App的文件的https服务器地址,必须 applinks: 开头) 该列表限制为不超过20到30个。
配置完后,Xcode中会自动生成一个 .entitlements 文件,专门存放Associated Domains的配置信息。 如果你的项目中有多个环境每个环境的域名不同,你可以拷贝多个.entitlements文件,每个环境对应一个.entitlements。
3、apple-app-site-association文件配置:
配置并上传配置文件到服务器中该域名的根目录下,可以用GET请求可以获取到这个配置文件。需注意的是文件不需要加后缀,部分服务器无法访问无后缀的文件, (文件的未压缩大小不得大于128 KB,数组中字典的顺序决定了系统在寻找匹配项时所遵循的顺序)
apple-app-site-association文件名固定,不能修改,不能加后缀; 必须支持https且不能重定向
{
"applinks":{
"apps":[],
"details":[
{
"appID":”9JXXXXXXNQ.com.XXXX.test",
"paths":["/dgtest/*"] //只要链接中包含/dgtest/就可以唤起app
}
]
}
}
a、配置
appID:组成方式是 teamId + bundle identifier。如上面的 9JXXXXXXNQ就是teamId。登陆开发者中心,在Account -> Membership里面可以找到Team ID。
paths:设定你的App支持的路径列表,只有这些指定的路径的链接,才能被App所处理。paths是按照顺序匹配路径的,所以高优先级路径要放在前面。
指定网站路径的规则:
· 使用 "*" 指定整个网站
· 包含特定的网址(例如"/wwdc/news/")以指定特定的链接
· 附加*到特定的网址(例如"/videos/wwdc/2015/*")以指定网站的一部分
· 除了用于*匹配任何子字符串之外,您还可以?用于匹配任何单个字符。您可以将两个通配符合并在一个路径中,例如"/foo/*/bar/201?/mypage"。
· 如果要指定不应作为通用链接处理的区域,请在路径字符串的开头添加“ NOT ”(注意有一个空格 "NOT /wwdc/2010/*")
b、上传
上传文件到HTTPS Web服务器的根目录或 .well-known 子目录。 这是为了苹果能获取到你上传的文件。上传完后,自己先访问一下,看看是否能够获取到文件,当你在浏览器中输入这个文件链接后,应该是直接下载apple-app-site-association配置文件。
4、实现接收方法:
Appdelegate中实现 continueUserActivity: 代理方法,并做打开的相应处理(不实现也不影响唤起功能)
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler{
NSString *url = [userActivity.webpageURL absoluteString];
url = [url stringByRemovingPercentEncoding];
//进行自定义处理
return YES;
}
5、调用
["*"] 调起https://mbankshare.XXXX.cn就可以启动App
["/dgtest/*"] 调起https://mbankshare.XXXX.cn/dgtest/*就可以启动App复制代码
在任何地方打开你的网址,系统命中后会直接跳转到你的app,没有命中会跳转到对应的网页;
如果在Safari中打开网址,在出现的网页上方下滑,可以看到有在”XX”应用中打开,点击“打开”按钮直接跳转App。
三、拓展
最新官方文档 偶然间看到苹果新的文档,关联文件格式有比较大的改动,这里简单做个记录:
构建关联文件后,将其放置在站点的 /.well-known/ 目录下。(文档没有提到放在根目录下,不知道是否还支持)
从macOS 11和iOS 14开始,应用程序不再将apple-app-site-association文件请求直接发送到Web服务器。而是将这些请求发送到专用于关联域的Apple管理的内容交付网络(CDN)。
{
"applinks": {
"details": [
{
"appIDs": [ "ABCDE12345.com.example.app", "ABCDE12345.com.example.app2" ],
"components": [
{
"/": "/buy/*",
"comment": "匹配路径以 /buy/ 开头的任何URL"
},
{
"/": "/help/*",
"?": { "articleNumber": "????" },
"comment": "匹配路径以/help/开头的任何URL,该URL有一个为'articleNumber'的查询项,值为4个字符"
},
{
"/": "/help/website/*",
"exclude": true,
"comment": "匹配路径以 /help/website/ 开头的任何URL,并指示系统不要将其作为通用链接打开"
},
{
"#": "no_universal_links",
"exclude": true,
"comment": "匹配任何片段等于 no_universal_links 的URL,并指示系统不要将其作为通用链接打开"
}
]
}
]
},
"webcredentials": {
"apps": [ "ABCDE12345.com.example.app" ]
},
"appclips": {
"apps": ["ABCED12345.com.example.MyApp.Clip"]
}
}
第一层级多了这两个:
Web Credentials 是手机上的密码(证书)填充功能
App Clips 是轻应用功能
details词典仅适用于applinks服务类型;其他服务类型不使用它。的components关键是字典的阵列,其提供模式匹配的URL的组件。
注意:
· 如果要对没有path的域名进行支持(如:www.163.com ), 在json文件的paths中用通配符’*’是不行的,需要在paths数组中加入’/’进行匹配。
· 服务器的域名地址必须是HTTPS的,并且SSL证书必须通过苹果信任。苹果支持的HTTPS证书列表。
· 即使页面打开是404,只要网址格式符合规则,也是可以命中的
· App处于运行或者后台时点击分享出去的链接然后跳转到应用里买呢以及对应的界面,但是App杀死在点击分享出去的链接只是单独的唤醒App并没有执行 continueUserActivity 这个方法(可能是在启动的时候做了其他操作,从而影响了在continueUserActivity方法中的处理)
无法唤起解决方案:
1、当我所有配置都配完,发现无法唤起,检查发现把英文的引号"打成了中文的引号“。
2、改好后再了几遍确认配置无误后,依然还是无法唤起App。
于是尝试了如下方法:
· 关闭代理;
· 清空safari缓存;
· safari不要开启隐私模式;
· 重启手机;
· 重新安装App;
结果:依然无法唤起
3、在苹果验证网站验证,一直提示:“XXX" isn't a valid webpage URL. Please check your URL and try again.(即使正常的地址也会提示这个,不知道什么情况)
4、继续用HTTP状态查询工具(查重定向等)排查问题,发现http状态码是202。
最后找后台同事沟通了老半天,最终发现原来是我们服务器加了安全设备检测工具,对网络进行了拦截导致的,苹果发起请求的时候被判定为非安全,所以导致被拦截了。所以apple-app-site-association文件下载一直是失败的,唤起App也就不会成功了 T.T
参考:
iOS微信授权登录+Universal Link(通用链接)
iOS 唤起App之Universal Link(通用链接)
Universal Link苹果官方文档
如发现遗漏或者错误,请在下方评论区留言。