在h5中是无法直接判断是否安装app的,我们只能使用间接的方式。先尝试打开app,因为正常情况下打开了app,我们的h5会变成后台,app变成前台。所以我们判断一定时间内,如果h5变成了后台运行了,就说明app打开了,就不去跳转下载了。
那么,既然思路在这里,我们就需要解决以下几个问题
- 判断机型Android或ios
- 判断打开我们h5的浏览器类型
- 打开app方式
- 延时代码,用于app未打开,去下载app
- 不同机型不同浏览器下载app
ok、撸起袖子开干
判断机型navigator.userAgent
一般我们写h5都需要判断是Android还是ios、因为身边机型有限,网上找了很多各家的判读方法,大抵如下:
var browser={
versions:function(){
var u = navigator.userAgent;
var app = navigator.appVersion;
return {
trident: u.indexOf('Trident') > -1, //IE内核
presto: u.indexOf('Presto') > -1, //opera内核
webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,//火狐内核
mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1 || u.indexOf('Linux') > -1, //android终端
iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器
iPad: u.indexOf('iPad') > -1, //是否iPad
webApp: u.indexOf('Safari') == -1, //是否web应该程序,没有头部与底部
weixin: u.indexOf('MicroMessenger') > -1, //是否微信 (2015-01-22新增)
qq: u.match(/\sQQ/i) == " qq", //是否QQ
browser: navigator.userAgent.indexOf('MQQBrowser') >-1
};
}(),
language:(navigator.browserLanguage || navigator.language).toLowerCase()
}
注意:以上判断QQ的方式涵盖了QQ浏览器。也就是browser.versions.qq不能区分是QQ浏览器还是QQ内置浏览器打开。
这里,我们使用另外一种方式来兼容处理一下、排除QQ浏览器
browser.versions.qq && !browser.versions.browser
补充发现:oppo R17 Android 10 qq内置浏览器,既存在QQ也存在MQQBrowser 所以用以上方式实现不了,但是它里面有个QQTheme
我们就再处理一下这种情况
browser.versions.qq && navigator.userAgent.match(/QQTheme/i) == 'QQTheme'
哎!太烦了....
判断打开我们h5的浏览器类型
使用以上的设备判断方式,我们需要区分微信和QQ打开我们的h5,因为安卓里面微信和QQ是没有办法直接跳转到我们的app的。而ios的微信里面可以通过设置URL Scheme来实现直接跳转(ios9以上才有效)。我自己测试是ios的qq里面跳转不了,跳转会404,网上有小伙伴说跳转方式使用window.top.location.href可以,but 我测试是不行的。所以最终我们只实现在微信里面直接跳转app。
ok,我们来判断浏览器,实现不同的逻辑,无法跳转的我们让其在浏览器打开。
button.onclick = function() {
// 获取到当前连接 注意这里只有点击事件才能跳转,直接js模拟点击去跳转是实现不了的。
QQ或者安卓微信
if ((browser.versions.qq && !browser.versions.browser) || (browser.versions.android && browser.versions.weixin)){
// 提示浏览器打开
} else if (browser.versions.iPad) {
openApp(
`iPad链接`,
goConfirmAddr
)
} else if (browser.versions.android || window.screen.width > 500) {
//Android的pad没有找到判断的方式,感觉它就是一个大的手机
openApp(
`Android的Pad链接`,
goConfirmAddr
)
} else if (browser.versions.android) {
openApp(
`安卓打开app的链接`,
goConfirmAddr
)
} else if (browser.versions.ios) {
openApp(
`https://ios打开app的链接`,
goConfirmAddr
)
}
}
打开app方式
- iframe方式
- a标签方式
- location方式
iframe方式
var ifr = document.createElement('iframe')
ifr.setAttribute('src', url)
ifr.setAttribute('style', 'display:none')
document.body.appendChild(ifr)
a标签方式
var a = document.createElement('a')
a.setAttribute('href', url)
a.setAttribute('style', 'display:none')
document.body.appendChild(a)
a.click()
注意:a标签这种方式有可能触发不了,需要手动触发,所以我们推荐location的方式
location方式
window.location.href = url
location.href
在上面我们说过只有ios的微信可以直接唤起app,其实qq应该也可以的。但是需要使用top.location的方式去跳转。但是我测试还是不行,不知道是不是我的写法有问题,如果有发现可以实现的小伙伴一定要留言告诉我哟~
检测唤起app是否成功
其实实际上是检测不了的,但是我们可以曲线救国。设置延时或者查看我们的h5是否被后台运行了
var _clickTime = +new Date()
function check(elsTime) {
if (elsTime > 3000 || document.hidden || document.webkitHidden) {
} else {
callback && callback()
}
}
//启动间隔20ms运行的定时器,并检测累计消耗时间是否超过3000ms,超过则结束
var _count = 0,
intHandle
intHandle = setInterval(function() {
_count++
var elsTime = +new Date() - _clickTime
if (_count >= 100 || elsTime > 3000) {
clearInterval(intHandle)
check(elsTime)
}
}, 20)
以上方式也不完美解决它,比如安卓上面需要确认之后再唤起app,这时已经过去3s了,就会触发下载。哎! 求更好的解决办法。
不同机型不同浏览器下载app
这就没啥好讲的了,跟上面差不多。ok我们贴个完整代码吧
// 判断手机上是否安装了app,如果安装直接打开url,如果没安装,执行callback
function openApp(url, callback) {
window.location.href = url
var _clickTime = +new Date()
function check(elsTime) {
if (elsTime > 3000 || document.hidden || document.webkitHidden) {
} else {
callback && callback()
}
}
//启动间隔20ms运行的定时器,并检测累计消耗时间是否超过3000ms,超过则结束
var _count = 0,
intHandle
intHandle = setInterval(function() {
_count++
var elsTime = +new Date() - _clickTime
if (_count >= 100 || elsTime > 3000) {
clearInterval(intHandle)
check(elsTime)
}
}, 20)
}
// 去下载
function goConfirmAddr() {
// 是否是安卓QQ打开
if (isIosPad) {
window.location = 'iPad下载地址'
} else if (isAndroidPad) {
window.location = 'Pad下载地址'
} else if (isIos) {
window.location = 'ios下载地址'
} else {
window.location = 'Android下载地址'
}
}
window.onload = function() {
let button = document.getElementById('btn')
button.onclick = function() {
if (isAndroidQQ || isAndroidWechat || isIosQQ) {
// 提示浏览器打开
} else if (isIosPad) {
openApp(`XXXXXX`, goConfirmAddr)
} else if (isAndroidPad) {
openApp(`XXXXXX`, goConfirmAddr)
} else if (isAndroid) {
openApp(`XXXXXX`, goConfirmAddr)
} else if (isIos) {
openApp(`XXXXXX`, goConfirmAddr)
}
}
}
补充一下:如果没有app,ios打开那个链接会404。解决方法是把我们的ios打开链接的地址代理到我们的h5下载页,直接去下载。