一是如何唤起本地app,二是如何判断浏览器是否安装了对应app。
我们从前端角度思考看这个问题,需要知道的一点是,ios与Android都支持一种叫做schema协议的链接。
这个协议不需要我们前端去实现,我们只需要将协议放在a标签的href属性里,或者使用location.href与iframe来实现激活这个链接。而location.href与iframe是解决这个需求的关键。
在ios中,还支持通过smart app banner来唤起app,即通过一个meta标签,在标签里带上app的信息,和打开后的行为,代码形如
<meta name="apple-itunes-app" content="app-id=1023600494, app-argument=tigerbrokersusstock://com.tigerbrokers.usstock/post?postId=7125" />
我们还需要知道的一点是,微信里屏蔽了schema协议。除非你是微信的合作伙伴之类的,他们专门给你配置进白名单。否则我们就没办法通过这个协议在微信中直接唤起app。
因此我们会判断页面场景是否在微信中,如果在微信中,则会提示用户在浏览器中打开。
一、如何判断本地是否安装了app
很无奈的是,在浏览器中无法明确的判断本地是否安装了app。因此我们必须采取一些取巧的思路来解决这个问题。
我们能够很容易想到,采用设置一个延迟定时器setTimeout的方式,第一时间尝试唤起app,如果200ms没有唤起成功,则默认本地没有安装app,200ms以后,将会触发下载行为。
使用location.href的同学可能会面临一个担忧,在有的浏览器中,当我们尝试激活schema link的时候,若本地没有安装app,则会跳转到一个浏览器默认的错误页面去了。因此大多数人采用的解决方案都是使用iframe
后来观察了网易新闻,今日头条,YY等的实现方案,发现大家都采用的是iframe来实现。好吧,面对这种情况,只能屈服。
整理一下目前的思路,得到下面的解决方案
var url = {
open: 'app://xxxxx',
down: 'xxxxxxxx'
};
var iframe = document.createElement('iframe');
var body = document.body;
iframe.style.cssText='display:none;width=0;height=0';
var timer = null;
// 立即打开的按钮
var openapp = document.getElementById('openapp');
openapp.addEventListener('click', function() {
if(/MicroMessenger/gi.test(navigator.userAgent) {
// 引导用户在浏览器中打开
}) else{
body.appendChild(iframe);
iframe.src = url.open;
timer = setTimeout(function() {
wondow.location.href = url.down;
}, 500);
}
}, false)
一测试,就发现简单的这样实现有许多的问题。
第一个问题在于,当页面成功唤起app之后,我们再切换回来浏览器,发现跳转到了下载页面。
为了解决这个问题,发现各个公司都进行了不同方式的尝试。
也是历经的很多折磨,发现了几个比较有用的事件。
pageshow: 页面显示时触发,在load事件之后触发。需要将该事件绑定到window上才会触发
pagehide: 页面隐藏时触发
visibilitychange: 页面隐藏没有在当前显示时触发,比如切换tab,也会触发该事件
document.hidden 当页面隐藏时,该值为true,显示时为false
由于各个浏览器的支持情况不同,我们需要将这些事件都给绑定上,即使这样,也不一定能够保证所有的浏览器都能够解决掉这个小问题,实在没办法的事情就不管了。
因此需要扩充一下上面的方案,当本地app被唤起,则页面会隐藏掉,就会触发pagehide与visibilitychange事件
$(document).on('visibilitychange webkitvisibilitychange', function() {
var tag = document.hidden || document.webkitHidden;
if (tag) {
clearTimeout(timer);
}
})
$(window).on('pagehide', function() {
clearTimeout(timer);
})
还是没有实现。。。。。
参考网易云的逻辑,h5页面点击打开会跳转到一个下载页面,这个下载页面一加载完成就尝试打开app,如果打开了就直接跑到app里面去了,如果没有就在页面上有一个立即下载的按钮,按钮行只有下载处理。
$(function(){
//不同端下载链接
if ((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) {
$("#openApp").attr('href', 'https://itunes.apple.com/us/app/yi-wang-quan-cheng/id875785098?l=zh&ls=1&mt=8');
$("#dowbtn").attr('href', 'https://itunes.apple.com/us/app/yi-wang-quan-cheng/id875785098?l=zh&ls=1&mt=8');
} else if (navigator.userAgent.match(/android/i)) {
$("#openApp").attr('href', 'http://m.yiwang.com/android/yiwang.apk');
$("#dowbtn").attr('href', 'http://m.yiwang.com/android/yiwang.apk');
}
var ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger'){
if ((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i)))
{
$("#openApp").attr('href', 'http://a.app.qq.com/o/simple.jsp?pkgname=com.yiwang.mobile');
$("#dowbtn").attr('href', 'http://a.app.qq.com/o/simple.jsp?pkgname=com.yiwang.mobile');
} else {
$("#openApp").attr('href', 'http://a.app.qq.com/o/simple.jsp?pkgname=com.yiwang.mobile');
$("#dowbtn").attr('href', 'http://a.app.qq.com/o/simple.jsp?pkgname=com.yiwang.mobile');
}
}
})