本文详解在微信、QQ、微博及Safari中通过JS唤起App的完整流程。针对微信屏蔽Universal Links的现状,提供跳转应用宝的替代方案;解析iOS与Android在不同客户端下的兼容性差异,包括Scheme与Universal Links的使用限制及白名单机制,并提供本地调试所需的User-Agent配置。
背景与目标
背景
近期致力于在微信、QQ及微博环境中实现JS唤起App的功能。此前虽有过类似实践,但方案较为简陋且考量不足,加之技术迭代迅速,旧有方案已逐渐淘汰。如今,存在体验更佳、功能更完善的唤起技术。本文旨在分享一套全面且最新的唤起方案,以期对开发者有所帮助。
目标
当用户点击“打开App”或下载按钮(该按钮可能位于下载入口页、分享页面的吸顶或吸底Banner中)时,系统需进行判断:若用户已安装App,则根据业务逻辑跳转至对应的Native页面;若未安装,则引导用户前往AppStore或应用市场下载我们的App。
完整唤起流程
一个完整的流程

首先,所有的下载或唤起入口均应为直接跳转链接,形式如下:
<a href="https://applink-party.mtime.cn/mtlf">下载</a>
或者采用以下形式:
window.location.href = 'https://applink-party.mtime.cn/mtlf'
所有的业务逻辑判断均在mtlf页面内部执行,这样做具备两点优势:
一是实现多业务代码复用。在团队环境中,每个业务线都可能拥有独立的Banner下载入口,通过location跳转至指定URL是最简单的调用方式。二是可以利用universal link,简要说明universal link。
在iOS9之前,iOS与Android的唤起方式一致,均使用scheme进行唤起。这种方式存在一个小问题:每次唤起时,系统会弹出提示询问“是否打开xx应用”,这增加了用户的操作步骤,影响体验。而universal link则能实现直接跳转,无需在页面停留。其前提条件是在项目根目录下增加一个apple-app-site-association.json文件,内容大致如下:

随后,在iOS App后台进行相应配置,即可实现直接唤起。
各平台唤起方案详解
微信、微博、QQ、Safari在各平台的唤起方案
经过长期实验,总结了这张展示各种情况下唤起成功或失败解决方案的图表,接下来我们将逐一解析。
微信环境处理
微信
微信是极其重要的分享渠道,但我们的操作空间有限。此前,iOS下的微信支持universal link这种唤起方式,但从2018年1月8日起,微信屏蔽了该功能!无论微信出于何种原因屏蔽iOS下这种最便捷的唤起方式,我们只能适应。因此,现在无论是iOS还是Android,处理方式一致:直接跳转至应用宝。iOS的应用宝会引导用户打开AppStore,而Android的应用宝则直接打开App(前提是已下载)。
注:微信也屏蔽了itunes链接,因此无法直接跳转AppStore,只能借助应用宝作为桥梁。
微博环境处理
微博
微博目前仍支持universal link唤起,我们只需考虑未下载的情况。
在iOS下,微博不支持打开应用宝链接,因此我们需要引导用户使用Safari打开,形式如下:

在Andriod平台下,使用scheme这种方式无法唤起App,但存在特例。同样是scheme,大众点评和网易云音乐可以成功唤起,大家可以自行尝试。由此可推断,Android平台下的微博也存在类似微信的白名单机制,在白名单内的应用可以使用scheme唤起,就像微信中的京东通过scheme方式唤起一样。
因此,无论是iOS还是Andriod,我们的方案是:直接引导用户使用本地浏览器打开。
QQ与Safari环境处理
QQ iOS平台下,QQ目前仍支持universal link唤起。若未安装,QQ也支持直接打开itunes链接,相比其他应用,QQ的支持最为完善。在Andriod平台下,QQ也支持scheme方式唤起,但在部分老机型上,QQ有一定概率唤起失败。具体现象为:第一次打开页面唤起失败,再次打开则成功。根据现象推测,QQ的webview会对scheme的唤起方式施加加载时间限制,经测试约为500ms,超过此时间值即出现唤起失败。第二次打开成功率较高,是因为首次加载时已缓存文件,第二次直接加载,时间在限制范围内。
Safari这种情况较为简单,支持universal link,也支持直接打开itunes,因此按图示处理即可。
兼容性与踩坑指南
踩坑 在iOS9中,Safari不支持直接跳转itunes,因此需要做兼容处理。在判断唤起是否成功前,需自行计算时间,因为若唤起成功,setInterval的时间会变慢。经测试,该方法已不再必要,只需使用document.hidden || document.webkitHidden即可,兼容性良好。判断是否为Safari浏览器时,通常检查UA中是否包含该字符串,但测试发现Android的UA中也包含Safari字符串(如下UA展示),因此需增加操作系统的判断。关于Scheme唤起,此前有多种方案,如使用iframe、<a>标签点击、window.location等。经测试,使用a标签点击兼容性最佳,代码大致如下:

本地调试与测试
关于测试
两个平台,如此多情况,是否需逐一测试?当然需要逐一验证,但在开发期间,每改一行代码就在手机上测试一次效率太低,尤其是像选择安卓4.4手机时,绝对考验耐心。为提高效率,分享常用的UA,以便在Chrome模拟器中配置本地调试,常用UA如下:
iOS-微信
Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_2 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Mobile/15C202 MicroMessenger/6.6.1 NetType/WIFI Language/zh_CN
iOS-QQ
Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_2 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Mobile/15C202 QQ/7.3.5.473 V1_IPH_SQ_7.3.5_1_APP_A Pixel/1125 Core/UIWebView Device/Apple(iPhone X) NetType/WIFI QBWebViewType/1
iOS-微博
Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_2 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Mobile/15C202 Weibo (iPhone10,3__weibo__8.1.0__iphone__os11.2.2)
iOS-safari
Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_2 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0 Mobile/15C202 Safari/604.1
Andriod-微信
Mozilla/5.0 (Linux; Android 4.4.2; PE-TL20 Build/HuaweiPE-TL20; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/043807 Mobile Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/WIFI Language/zh_CN
Andriod-QQ
Mozilla/5.0 (Linux; Android 4.4.2; PE-TL20 Build/HuaweiPE-TL20; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/043807 Mobile Safari/537.36 V1_AND_SQ_7.3.2_762_YYB_D QQ/7.3.2.3350 NetType/WIFI WebP/0.3.0 Pixel/1080
Andriod-微博
Mozilla/5.0 (Linux; Android 4.4.2; PE-TL20 Build/HuaweiPE-TL20) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36 Weibo (HUAWEI-PE-TL20__weibo__8.0.2__android__android4.4.2)
配置完成后,即可像我一样,在电脑上切换环境进行调试:
