c端业务会常用到需要唤起本地app功能,也就需要检测相关的app是否正常安装,我们通常使用a标签跳转或者window.location来达到跳转的目的,但是实际业务中,如果APP唤醒失败,或者APP未安装的话,很多时候都会跳到错误页,这很影响用户体验,而我们的要求可能是跳转到其他页面或者下载APP。
所以就有一种比较hack的方法来检测app是否正常安装
在 body 上添加 iframe,设置 src 属性为跳转的 URL scheme
/**
* 检测是否安装app,如果未安装则提示!已安装指定app则唤起app
* @param {String} url - 唤起app的url地址
* @returns {Promise} Promise对象
*/
export default function (url) {
return new Promise((resolve, reject) => {
let hasApp = true
const ifr = document.createElement('iframe')
const t1 = Date.now()
setTimeout(() => {
if (hasApp) {
resolve()
} else {
reject()
}
document.body.removeChild(ifr)
}, 2000)
ifr.setAttribute('src', url)
ifr.setAttribute('style', 'display:none')
document.body.appendChild(ifr)
setTimeout(() => {
const t2 = Date.now()
if (!t1 || t2 - t1 < 1000 + 100) {
hasApp = false
}
}, 1000)
})
}
这一种方法不会引起页面内容可见的变化,不会导致浏览器历史记录的变化。
原理: 浏览器尝试打开 URL scheme,在 1 秒计时后,检查当前时间,如果实际时间已过 1100 毫秒,说明唤起 app 成功(唤起 app 会让浏览器的定时器变慢);如果没超过 1200 毫秒,很可能是没有安装应用,就抛出错误。