小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
以下所有操作步骤已经过实际操作验证
Universal Link通用链接
Universal Link是Apple在WWDC上提出的iOS9的新特性之一;能够方便的通过打开一个HTTPS链接来直接启动您的客户端应用,当然前提条件是您必须在手机上安装了此App;
在Universal Link之前,我们通常使用URL Scheme的方法实现web-App的方式进行跳转;相比于URL Scheme方式,Universal Link提供了极佳的用户体验;
关于更多的介绍,可以查阅Universal Link官方介绍
应用场景
使用Universal Link可以让用户在Safari浏览器或者其他App的WebView中拉起相应的App,也可以在App中使用相应的功能,从而把用户引流到App中;比如我们购物时,在Safari浏览器中进入淘宝网页点击打开手机淘宝则会直接使用Universal Link来拉起淘宝App;
Universal Link优点
- 唯一性:与自定义的
URL Scheme相比,Universal Link使用的是标准的HTTPS协议链接到您的站点,所以一般不会被其他的App所声明;自定义的URL Scheme在没有安装应用的情况下是无法直接打开的,在Safari中还会出现一个不可打开的弹窗;而使用了标准HTTPS协议的Universal Link链接则具备更好的兼容性; - 安全:如果用户的手机上安装了您的应用,那么系统回去您配置的网站上下载您上传的文件
apple-app-site-association,在这个文件中标明了当前的Universal Link的链接能够打开哪些App;因为只有开发着自己才有权限在网站的根目录上传此文件,所以网站与App之间的关联是安全的; - 可变:如果用户的手机上没有安装您的应用,那么不必担心,
Universal Link依然能够工作;如果你愿意,在没有安装你的App的时候,用户点击链接,将会在Safari浏览器中展示你网站的内容; - 简单:作为
Universal Link使用的HTTPS链接,可以同时作用于网站和App; - 私有:其他
App可以在不需要知道你的App是否安装了的情况下与你的App相互通信;
支持条件
- 比如有一个支持
HTTPS的域名,并且拥有该域名下上传文件到根目录(或者是.well-known目录)的权限;需在在根目录(或者是.well-known目录)下上传Apple指定的文件; - 在
App开发者网站找到你的App对应的App ID配置Associated Domains,将其勾选上;
- 在工程中配置:点击
+Capability,然后搜索Associated Domains
确定之后,Xcode将会生成如下配置项:
在Domains中配置applinks:xxxxxxxxx;applinks:为固定字符串,后边xxxxxxxxx的就是存放文件的网址域名;比如你的网址是https://www.test.com,那么此处只需要配置applinks:www.test.com即可;
需要注意的是Debug和Release两种模式都要配置,Xcode版本不同,可能配置项位置有差异
- 上传指定文件:创建一个文件,名为
apple-app-site-association,注意,文件名必须固定为apple-app-site-association,没有后缀,没有后缀,没有后缀;其内容为json格式,如下:
{
"applinks":{
"apps":[],
"details":[
{
"appID":"M9N2NBY3KD.com.test.dev",
"paths":["/qq_conn1/*", "/wechat1/*"]
},
{
"appID":"ZB2D2P7QLR.com.test.dis",
"paths":["/qq_conn1/*", "/wechat1/*"]
},
{
"appID":"4X3EKPR8EQ.com.apple.dev",
"paths":["/qq_conn2/*", "/wechat2/*"]
},
{
"appID":"ZB2D2P7QLR.com.apple.dis",
"paths":["/qq_conn2/*", "/wechat2/*"]
},
{
"appID":"4X3EKPR8EQ.com.thk.dev",
"paths":["/qq_conn3/*", "/wechat3/*"]
},
{
"appID":"ZB2D2P7QLR.com.thk.dis",
"paths":["/qq_conn3/*", "/wechat3/*"]
}
]
}
}
此处我配置了三个
App,每一个App的测试和发布都分开配置,所以出现了六组配置信息;
appID的组成方式为:teamId.your app's bundle identifier;4X3EKPR8EQ、ZB2D2P7QLR、M9N2NBY3KD这些为Team ID,可以在开发者网站找到;
paths为支持的路径列表:/qq_conn3/*为QQ分享,"/wechat3/*为微信分享使用;
验证
Apple官方提供了验证apple-app-site-association是否配置成的网站前往验证网站
在网站中输入域名(不带协议头),如果出现如下信息,则说明配置成功:
配置失败:
踩坑指南
- 确认配置
apple-app-site-association的网站,美国ip可访问;(十分重要,多次测试,需要美国ip可访问) - 确认
开发者平台,SDK集成,Xcode配置项Domains三处Universal Link能够对应; - 如果在
根目录和.well-known目录下同时放了apple-app-site-association要确保两个文件一致(尽量不要这么操作);我最后只在根目录放了文件; - 域名需要
HTTPS协议; apple-app-site-association文件json数据配置问题:
错误案例1:(/wechat1/后边不是通配符*)
{
"applinks":{
"apps":[],
"details":[
{
"appID":"M9N2NBY3KD.com.test.dev",
"paths":["/qq_conn1/*", "/wechat1/app1"]
},
{
"appID":"ZB2D2P7QLR.com.test.dis",
"paths":["/qq_conn1/*", "/wechat1/app1"]
},
{
"appID":"4X3EKPR8EQ.com.apple.dev",
"paths":["/qq_conn2/*", "/wechat2/app2"]
},
{
"appID":"ZB2D2P7QLR.com.apple.dis",
"paths":["/qq_conn2/*", "/wechat2/app2"]
},
{
"appID":"4X3EKPR8EQ.com.thk.dev",
"paths":["/qq_conn3/*", "/wechat3/app3"]
},
{
"appID":"ZB2D2P7QLR.com.thk.dis",
"paths":["/qq_conn3/*", "/wechat3/app3"]
}
]
}
}
错误案例2:(单独配置了通配符*)
{
"applinks":{
"apps":[],
"details":[
{
"appID":"M9N2NBY3KD.com.test.dev",
"paths":["*", "/qq_conn1/*", "/wechat1/app1"]
},
{
"appID":"ZB2D2P7QLR.com.test.dis",
"paths":["*", "/qq_conn1/*", "/wechat1/app1"]
},
{
"appID":"4X3EKPR8EQ.com.apple.dev",
"paths":["*", "/qq_conn2/*", "/wechat2/app2"]
},
{
"appID":"ZB2D2P7QLR.com.apple.dis",
"paths":["*", "/qq_conn2/*", "/wechat2/app2"]
},
{
"appID":"4X3EKPR8EQ.com.thk.dev",
"paths":["*", "/qq_conn3/*", "/wechat3/app3"]
},
{
"appID":"ZB2D2P7QLR.com.thk.dis",
"paths":["*", "/qq_conn3/*", "/wechat3/app3"]
}
]
}
}
错误案例3:(单独配置了通配符*,并且三个App的q_conn重复)
{
"applinks":{
"apps":[],
"details":[
{
"appID":"M9N2NBY3KD.com.test.dev",
"paths":["*", "/qq_conn/*", "/wechat1/*"]
},
{
"appID":"ZB2D2P7QLR.com.test.dis",
"paths":["*", "/qq_conn/*", "/wechat1/*"]
},
{
"appID":"4X3EKPR8EQ.com.apple.dev",
"paths":["*", "/qq_conn/*", "/wechat2/*"]
},
{
"appID":"ZB2D2P7QLR.com.apple.dis",
"paths":["*", "/qq_conn/*", "/wechat2/*"]
},
{
"appID":"4X3EKPR8EQ.com.thk.dev",
"paths":["*", "/qq_conn/*", "/wechat3/*"]
},
{
"appID":"ZB2D2P7QLR.com.thk.dis",
"paths":["*", "/qq_conn/*", "/wechat3/*"]
}
]
}
}
以上三个json都会导致微信SDK的自检函数WXApi.checkUniversalLinkReady无法通过校验;并且,如果三个App配置在同一个域名下,并且在手机上安装了多个App,那么将会发现分享之后,返回App时返回错误的App;返回的App会根据details中的顺序一次查找,返回找到的第一个App;
正确的json数据格式为:
{
"applinks":{
"apps":[],
"details":[
{
"appID":"M9N2NBY3KD.com.test.dev",
"paths":["/qq_conn1/*", "/wechat1/*"]
},
{
"appID":"ZB2D2P7QLR.com.test.dis",
"paths":["/qq_conn1/*", "/wechat1/*"]
},
{
"appID":"4X3EKPR8EQ.com.apple.dev",
"paths":["/qq_conn2/*", "/wechat2/*"]
},
{
"appID":"ZB2D2P7QLR.com.apple.dis",
"paths":["/qq_conn2/*", "/wechat2/*"]
},
{
"appID":"4X3EKPR8EQ.com.thk.dev",
"paths":["/qq_conn3/*", "/wechat3/*"]
},
{
"appID":"ZB2D2P7QLR.com.thk.dis",
"paths":["/qq_conn3/*", "/wechat3/*"]
}
]
}
}
Universal Link可以为:
QQ:
https://www.xxxxxxxx.com/qq_conn/123https://www.xxxxxxxx.com/qq_conn/456https://www.xxxxxxxx.com/qq_conn/789
微信:
https://www.xxxxxxxx.com/wechat1/app1/https://www.xxxxxxxx.com/wechat2/app2/https://www.xxxxxxxx.com/wechat3/app3/
按照此处配置,目前微信自检函数完全通过自检;多个
App没有出现返回错乱的情况;
Universal Link最终是否配置正确,不能通过分享等功能是否能够成功来判断;因为在Universal Link无法通过校验的情况下分享也有可能会成功,因为此时将会降级使用URL Scheme的方式进行通信;
同理,在Safari浏览器中输入Universal Link,即使出现了App的打开入口,也无法确定Universal Link完全配置正确,因为会出现配置多个App,并且都在手机上安装之后,返回错误的情况;
所以请在测试阶段,以自检函数的检查结果为准;