blog icon indicating copy to clipboard operation
blog copied to clipboard

h5页面点击判断是否安装app并打开,否则跳转下载页面

Open chenyinkai opened this issue 7 years ago • 7 comments

需求描述:在移动端页面中,有一个”购买‘’按钮,若本地安装了 app,则直接打开本地 app,若没有安装,则跳转到 AppStore 或者应用市场。

如何打开本地 app?

首先, iosAndroid 都支持一种叫做 schema 协议的链接,例如 金华银行的协议为 jhbhttp://xxxxx

激活这个协议有 3 种方式:

1.直接写在 a 标签中 2.location.href 3.iframe 跳转

而 location.href 与 iframe 是解决这个需求的关键。

如何判断本地安装了 app

目前,我们是无法直接判断本地是否安装了 app,所以我们需要采取其他方式解决这个需求。

采用设置一个延迟定时器 setTimeout 的方式,第一时间尝试唤起 app,如果 1000ms 没有唤起成功,则默认本地没有安装 app,1000ms 以后,将会触发下载行为。

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() {
    body.appendChild(iframe)
    iframe.src = url.open
    timer = setTimeout(function() {
      wondow.location.href = url.down
    }, 500)
  },
  false
)

存在问题:

1.ios9 以上不支持 iframe 跳转 2.跳转到 app,页面也出现下载页面待完善。。。。

使用 location.href 方法,ios9 以上也可以跳转,延时器中使用两次跳转是因为有些机型是出现提示框“是否打开 app”,两次跳转可以将提示框刷新掉

window.location.href = URL scheme;
setTimeout(function(){
    window.location.href = downloadUrl;
    window.location.href = downloadUrl;
},2000);

监听页面隐藏事件,清除延时器(存在兼容问题,很多浏览器不支持该事件)

$(document).on('visibilitychange webkitvisibilitychange', function() {
  var tag = document.hidden || document.webkitHidden
  if (tag) {
    clearTimeout(timer)
  }
})

$(window).on('pagehide', function() {
  clearTimeout(timer)
})

目前最完善的解决方案:

ios 下

window.location.href = link
setTimeout(function() {
  window.location.href = url
  window.location.href = url
}, 2000)

andriod 下,由于安卓是多任务,应用会进入后台,所以若使用 ios 的方法,则既会跳转 app,也会跳转下载页面。原理: 设置一个运行间隔 20ms,总计运行 100 次的定时器,如果页面一直处于前台,则 100 次跑完,总耗时与 100x20=2000ms 不会有太大差异,但页面在后台运行时,此时间会明显超过 2000ms。可以利用这一点来实现是否成功打开 APP 检测及回调。

window.location.href = link
var _clickTime = +new Date()
function check(elsTime) {
  if (elsTime > 3000 || document.hidden || document.webkitHidden) {
  } else {
    window.location.href = url
  }
}
//启动间隔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)

chenyinkai avatar Sep 11 '17 08:09 chenyinkai

check函数window。location.href的位置是不是放错了?

niubiqigai avatar Nov 30 '18 08:11 niubiqigai

@niubiqigai elsTime > 3000 || document.hidden || document.webkitHidden 这个条件说明当前页面已经切换到后台,所以不进行跳转。。应该是这样的,有点久了。不够这个方案也还有问题。安卓的情况下如果没有安装会有个404的页面,所以当时这个问题是让安卓的开发拦截一下。

chenyinkai avatar Nov 30 '18 09:11 chenyinkai

@niubiqigai elsTime > 3000 || document.hidden || document.webkitHidden 这个条件说明当前页面已经切换到后台,所以不进行跳转。。应该是这样的,有点久了。不够这个方案也还有问题。安卓的情况下如果没有安装会有个404的页面,所以当时这个问题是让安卓的开发拦截一下。

感谢你的回复!请教一下,link跟url分别是代表什么?能有一个实例写法可以给我看看吗?

niubiqigai avatar Nov 30 '18 09:11 niubiqigai

@niubiqigai link是app的schema链接,url是下载地址。没有例子,这是很久之前上家公司的需求。。。

chenyinkai avatar Nov 30 '18 09:11 chenyinkai

现在还有更完善的解决方案吗

GeNa-jj avatar Apr 11 '19 07:04 GeNa-jj

@GeNa-jj 抱歉呐,后面就没有继续去研究了,如果跳转的app也是你们开发的话,那么可以和客户端的同事讨论下,基本可以实现这个场景。如果不是的话,那么好像没有完美的方案,总有一些问题。。

chenyinkai avatar Apr 11 '19 09:04 chenyinkai

@chenyinkai 不管怎么样,还是感谢你的答复。😁

GeNa-jj avatar Apr 22 '19 05:04 GeNa-jj