iOS H5打开App(通用链接)
入秋了,路上会遇到用小贩用小货车拉着卖芒果,和去年一样,我会停下急匆匆的脚步,买几个。一则自己爱吃芒果不过敏,二则品尝下是否和去年一样熟悉的味道。
很多时候可能都希望在浏览器,微信里面点击一个H5链接或按钮,之后直接打开App跳到App里面指定的页面。
- safari,chrome,UC,搜狗,opera Mini等浏览器-----》唤醒App。
用户通过浏览器地址栏输入官网地址,或商品地址打开App里面指定页面。若手机内未安装App则引导用户跳入Apple Store下载页。(本来准备举美团的例子,结果美团变成了小程序,那就某东吧)。
在浏览器中输入商品地址:
手机安装了某东。
2.gif手机未安装某东。
4.gif
- 微信,QQ,微博-----》唤醒APP。
用户通过某APP分享了一条链接至微信,QQ或微博,用户点开该链接后,会引导用户B打开该APP或者下载该APP。
在微信里面点击的分享的商品:
手机安装了某东。
1.gif手机未安装某东。
3.gif
- 短信、备忘录,邮件-----> 唤醒APP。
用户收到一条推广短信,在短信里面点击链接跳入App里面或下载App页。
如何实现上面的场景呢?分为iOS9.0以前和iOS9.0以后。
1.iOS9.0以前只有一种实现方式,scheme方式。若安装App则跳入指定页面,则scheme后面加参数:”taobao://item.taobao.com/item.htm?id=“。若未安装跳到下载页引导用户下载安装。
let link = "taobao://item.taobao.com/item.htm?id=" + id,
fallback = "itms-apps://itunes.apple.com/cn/app/" + appId;
// 尝试呼起 App
location.href = link;
// 3s 后未能呼起则跳转 App Store
setTimeout(() => location.href = fallback, 3000);
浏览器如何知道手机是否安装了App呢,通过设置延时。
setTimeout的实现过程:
浏览器尝试打开URL scheme并记录时间点t1,在2秒计时后,检查当前时间t2,如果t2-t1 > 2200ms,说明唤起app成功(唤起app会是浏览器的定时器延后执行),如果t2-t1 < 2200ms,可能没有安装app,可以引导用户进入下载页。
5.gif
6.gif
var openTime = +new Date();
window.location.href = 'wzry://videolists.show/mark/penta_kill?num=1'
var timer = setTimeout(function () {
if ((new Date()) - openTime < 2200) {//加了200ms基准误差
window.location.href = 'you app download page';
}
if ((new Date()) - openTime > 2200) {
clearTimeout(timer);
}
}, 2000);
- setInterval实现过程:
原理上跟setTimeout相似,方法上换成设置一个比较小的时间间隔(例如20ms),运行多次(例如100),比较运行完100次的总耗时与20*100的时间差。逻辑判断同setTimeout。
var limit_num = 100;
var openTime = +new Date();
window.location.href = 'wzry://videolists.show/mark/penta_kill?num=1'
var timer = setInterval(function () {
if(limit_num > 0){
limit_num--;
}else{
if ((new Date()) - openTime < 2200) {//加了200ms基准误差
window.location.href = 'you app download page';
}
clearTimeout(timer);
}
}, 20);
iOS9.0以后有两种方式,scheme和universal link(后面单独说)。重要的事情说三遍,iOS9.0以后还是可以用scheme,只是在iOS9上,iframe方案变得不可用,在打开自定义URL scheme时,会弹出对话框,询问是否用 xx应用来打开。若未安装App则会显示“safari打不开该网页,因为网址无效”。(可以通过直接跳转:点击链接或者修改window.location。<a href="schemeUrl">唤醒你的APP</a>,window.location.href = schemeUrl)
针对微信,就不区分iOS9.0之前和之后了,因为微信有白名单,白名单里面只包含50个App的url scheme。怎么查看呢。通过Apple configuration 2能够查到,具体请看文章。
白名单如下:在这个 plist 文件中找到白名单很简单,因为微信已经达到了49个的上限,一个很扎眼的 “(49 items)” 的 “Array” 项 LSApplicationQueriesSchemes 就是我们要找的白名单了。我们可以看到诸如腾讯新闻 (qqnews), 腾讯视频 (tenvideo2) 都是在白名单内的。
8.gif
有两种解决办法:
1.使用腾讯应用宝。
使用它颁发给你的应用地址,向这个地址跳转,然后一切就交给微信了,直接无视微信什么的,直接带你飞到app内。具体可看腾讯应用宝Applink接入文档。举个例子,网易新闻。从网易新闻分享一天链接到微信,在微信里面点开链接。
7.gif
- 若安装了微信。直接打开到网易新闻App对应链接。
8.gif 11.gif 12.gif
- 若未安装微信。腾讯应用宝跳到Apple Store进行下载。有趣的是下载完成后,点击打开后还能跑到对应链接。这是为什么呢。因为在微信里面点击打开按钮时,粘贴板上粘贴了该条链接的信息,跳入网易新闻之后,和淘宝一样监听到粘贴板上面的内容后跳到指定页面。
2.Universal Links(通用链接)。
- 在2015年的WWDC大会上,Apple推出了iOS 9的一个功能:Universal Links通用链接。如果你的App支持Universal Links,那就可以访问HTTP/HTTPS链接直接唤起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,可以定义统一的web-native协议;
- 私有:其它APP可以在不需要知道是否安装了的情况下和你的APP相互通信;
缺点:
只支持iOS9及以上系统;当使用Universal Link打开APP之后,状态栏右上角会出现链接地址,点击它会取消Universal Link,需引导用户重新使用Safari再次打开该链接,弹出Safari内置APP广告条,再点击打开重新开启Universal Link。
首先,你必须有一个域名,且这个域名的网站需要支持https,然后拥有网站的上传到.well-known目录的权限(这个权限是为了上传一个Apple指定的文件apple-app-site-association),有了这个先决条件才能够继续下面的步骤:
1.创建一个json格式的命名为apple-app-site-association文件,注意这个文件必须没有后缀名,文件名必须为```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.yourapp's bundle identifier
paths = APP支持的路径列表,只有这些指定的路径的链接,才能被APP所处理,大小写敏感。举个例子,如果你的网站是www.domain.com,你的path写的是"/support/*",那么当用户点击www.domain.com/support/<path>?<params>=<value>,就可以唤醒APP了,相反www.domain.com/other就不会。此外Apple为了方便开发者,提供了一个网址来验证我们编写的这个apple-app-site-association是否合法有效。
2.激活Xcode工程中的Associated Domains能力,在其中的Domains中填入你想支持的域名(这里不是随便填的,是可以支持你需要的Universal Links的域名), 必须以applinks:为前缀,例如:applinks:www.domain.comApple将会在合适的时候,从这个域名请求apple-app-site-association文件。注意:当你打开Associated Domains后,Xcode会在你的工程中添加.entitlements文件,并且登录开发者中心,可以看到Associated Domains处于Enable状态。
20170508193612385.png3.在AppDelegate里实现如下代理方法:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {
// NSUserActivityTypeBrowsingWeb 由Universal Links唤醒的APP
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
NSURL *webpageURL = userActivity.webpageURL;
NSString *host = webpageURL.host;
if ([host isEqualToString:@"yohunl.com"]) {
//进行我们需要的处理
} else {
[[UIApplication sharedApplication]openURL:webpageURL];
}
}
return YES;
}
至此APP已经开启Universal Links,可以通过链接唤醒APP,并跳转至指定页面了。流程如下:
WechatIMG433.jpeg
4.从微信跳转到app的时候,屏幕右上角还有个 "xxx.xx" 的小箭头:点击该箭头,会在Safari中打开该页面。此时再回到微信浏览器中点击 "打开App"按钮,神奇的事情出现了:无法跳转到app!!!
解决方案:在Safari中打开该页面,将网页拉倒最顶部,会出现一个悬浮框,点击悬浮框中的打开按钮,又跳回到app中打开指定页面,此时再回到微信浏览器中点击 "打开App"按钮,又能正常跳转到app了。
Universal Links 功能的接入其实相当于给某些 URL 添加了一种新的打开方式,但是旧的通过浏览器打开 URL 的方式仍然可用,当点击右上角跳转箭头时,相当于又设置这些特定 URL 的默认打开方式为浏览器而非 web,因此一键跳转功能此时会失效。反之通过点击顶部 "打开" 按钮,相当于又将这些特定 URL 的默认打开方式修改为 app ,一键跳转功能恢复正常。
在Safari中打开页面刚进入时,横条是隐藏的,一定要将页面拉到最顶部时才能显示。
5.跨域。举例假设当前微信浏览器中话题详情页面的 URL 为 "www.domain.com/XXX",底部“打开App”按钮对应的链接URL为 "www.domain.com/YYY",虽然通过上述配置了 "www.domain.com" 路径,但由于两者都在www.domain.com的域名下,因此实际不能完成跳转。必须在一个与applinks中添加的域名不同的页面test.domain.com(要跨域),写了一个点击操作,跳转到applinks中所写的域名www.domain.com/YYY,在微信中就直接跳转到了我们的app中了!
注:用于跳转打开app的域名需要支持https,如果是一级域名页面有个按钮,点击按钮跳转二级域名来打开app,那么二级域名需要支持https。这里DEMO的二级域名不支持https,所以采用的方案是二级域名跳转到一级域名来打开APP。