-
Notifications
You must be signed in to change notification settings - Fork 2
Description
背景
最近在做DeepLink的需求,DeepLink不算是一个新话题了,但是却一直都没间断过讨论。开始接触之前了解并不是很多,但是接触下来发现也就那几种实现方式。
什么是DeepLink呢?其实就是H5页面提供一个按钮,例如:“打开APP”或者“下载APP”等。在H5页面中点击这个按钮,如果安装了目标APP直接通过链接唤起,否则跳转到下载页面去下载APP。这种通过H5唤起APP的链接的方式就是DeepLink。
看起来很简单的一个业务流程,但是实现起来还是有很多坑的,主要是因为设备、设备版本、浏览器等碎片差异严重,导致很多兼容需要处理。
最终实现的效果
用户点击H5页面的打开App或者下载按钮(这个按钮可能在一个下载入口页、各种分享页面的吸顶或吸底的banner),如果用户已经安装了App,则根据业务跳转到相应的Native页面;如果用户没有安装该应用,则跳到AppStore或者应用市场去下载App。
已安装APP时的实现方式
一、iOS中的实现
iOS中在IOS9.0前后是一个分界点,因为从iOS9.0之后苹果开放universal link的方式代替schema的方式来唤起APP。下面我们就分别从iOS9.0前后分别来说:
1、iOS9.0之前
iOS9.0之前苹果和安卓的实现方式都是通过schema的方式来实现的。但是跳转方式也有很多种(window.location.href方式、a链接方式、iframe方式等),经过测试和查阅资料发现,iOS9.0之后的跳转方式选择iframe的方式是最靠谱的方式。代码如下所示:
function openOrDownload() {
var ifr = document.createElement('iframe');
ifr.src = 'test.1234://deeplink?token=1111111';
ifr.style.display = 'none';
document.body.appendChild(ifr);
}
2、iOS9.0+
iOS9.0+后的版本的苹果设备,开始支持universal link的实现方式,当然schema的方式也是被支持的,只不过在遇到未安装的时候会弹出一个丑陋的错误提示框,即使安装了也还是会弹窗询问用户是不是要打开APP,用户体验不好。
universal link的实现方式在网上有很多很详尽的说明和示例,此处不做详细说明。
当然,universal link的实现方式需要客户端和服务端的配合。
对于跳转方式iOS9.0+后选用a链接的方式最靠谱,iframe的方式已经无法使用了。a链接的示例代码如下所示:
let t = document.createElement("a");
iframeState = t;
t.style.display = "none";
t.href = url;
document.body.appendChild(t);
t.click();
二、Android中的实现
安卓中的实现方式比起苹果设备来看要更加复杂一点,因为有一些过长的浏览器总是奇葩的存在(如:UC)。
但是在安卓中目前schema是实现的主要方式,跳转方式通过测试,也是iframe的方式最靠谱。实现方式如上面iframe实现方式所示。
未安装的实现方式
因为在H5中是无法获取到设备中app的安装情况,无法判断是否安装,只能采用尝试打开的方式,如果已经安装则直接打开,如果未安装,通过时间差的方式来判断做出跳转到下载页面的操作。
其实,这个过程中还是存在一些坑的,比如跳转到app了,返回H5页面后还是会跳转到下载页面,因为浏览器差异兼容情况不一,始终没有完美的方案,只能通过如下方式尽量来兼容。
实现代码如下所示:
var o = setTimeout(function() {
document.body.removeChild(ifr);
document.hasFocus() && (window.location = 'http://www.baidu.com')
}, 1000);
var hidden,
visibilityChange;
if (typeof document.hidden !== "undefined") {
hidden = document.hidden;
visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
hidden = document.mozHidden;
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = document.msHidden;
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = document.webkitHidden;
visibilityChange = "webkitvisibilitychange";
} else {
hidden = false;
}
document.addEventListener(visibilityChange,
function() {
clearTimeout(o);
},
!1)
通过上面的实现方式可以兼容大部分,但是有些还是有问题,iOS下的safari就有问题,可以再加上如下代码,safari问题就可以解决了,代码如下:
/**
* 兼容safari 唤醒APP后仍跳转下载页面的问题
*/
window.addEventListener("pageshow", function(evt){
clearTimeout(o);
}, false);
window.addEventListener("pagehide", function(evt){
clearTimeout(o);
}, false);
微信、QQ等的实现方式
目前所有的直接再微信里面跳转APP的方式都已经行不通了,只有两种处理方式:1、提示在浏览器打开 2、通过应用宝来打开。
QQ、微博等,都是差不多的,具体没有一一测试,但是腾讯系的都可以通过应用宝的方式解决,其他的就提示浏览器打开吧。
基本H5唤起APP的大概的实现方式已经做了简单的介绍。
最后再吐槽一个莫名其妙的坑,就是ios中在safari中使用schema打开应用,应用没有安装的时候,会跳转App Store,如果第一次提示打开App Store时,选择“取消”,那么再点击的时候是无法跳转到App Store的,具体不知道苹果是怎么想的。