H5 页面唤起APP或跳转到下载APP的某个链接地址。总结如下:
在 IOS 中, 系统版本在 8 以下时,可以监听页面的 pagehide / visibilitychange 事件。 系统版本大于 8 以后,可以使用 universal Link 或 URL scheme 进行跳转。
// IOS 的唤起 function vForIOS(urlScheme, storeURL, fallback, universalLink) { var tid = deferFallback(TIMEOUT_IOS, storeURL, fallback); if (parseInt(os.version, 10) < 8) { bindPagehideEvent(tid); } else { bindVisibilityChangeEvent(tid); } if (parseInt(os.version, 10) > 8 && os.name == 'iOS' ) { // 通过universalLink if (universalLink === undefined) { universalLink = urlScheme; } else { clearTimeout(tid); } vLocation(universalLink); } else { vIframe(urlScheme); } } |
在安卓中, 安卓版本 4.4.4 以上机型的安卓自带浏览器、chrome 浏览器,需要通过 intent 跳转 【详情请见 https://developer.chrome.com/multidevice/android/intents】,其他浏览器大多数可通过 url scheme 唤起。但由于唤起APP后浏览器并无回调事件,我们很难判断是否已成功拉起APP,比较通用的解决办法是判断计时器是否变慢,若APP启动浏览器最小化入后台将会导致计时器变慢,即为实际事件间隔大于理想时间间隔。若未变慢则判断为未成功拉起APP,则跳转至下载地址。此判断代码如下:
function deferFallback(timeout, storeURL, fallback) { var clickedAt = new Date().getTime(); return setTimeout( function () { var now = new Date().getTime(); if (isPageVisible() && now - clickedAt < timeout + INTERVAL) { fallback(storeURL); } }, timeout); } |
安卓系统中,不同浏览器对唤起APP有严重的兼容性问题,主要处理方案有以下几种:
- 通过改变 window.location.href
- 通过创建 iframe 并为其 src 赋值
- 通过 intent
- 通过制造不可见 a 链接,并触发点击时间
// 打开页面的方式可能 // 1. 通过改变location function vLocation(urlScheme) { window.location.href = urlScheme; } // 2. 通过ifreame function vIframe(urlScheme) { setTimeout( function () { var iframe = createHiddenIframe( 'appLauncher' ); iframe.src = urlScheme; }, 100); } // 3. 通过intent function vIntent(launchURI) { if (browser.name == 'Chrome' ) { move(); } else { setTimeout(move, 100); } function move() { // window.top.location.href = launchURI; window.location.href = launchURI } } // 3. 通过添加出发alink function vAlink(launchURI) { var aLink = document.createElement( "a" ); aLink.setAttribute( "href" , launchURI); aLink.style.display = "none" ; document.body.appendChild(aLink); var event = document.createEvent( "HTMLEvents" ); event.initEvent( "click" , !1, !1); aLink.dispatchEvent(event) } // IOS 中的 可见性事件 function bindPagehideEvent(tid) { window.addEventListener( 'pagehide' , function clear() { if (isPageVisible()) { clearTimeout(tid); window.removeEventListener( 'pagehide' , clear); } }); } function bindVisibilityChangeEvent(tid) { document.addEventListener( 'visibilitychange' , function clear() { if (isPageVisible()) { clearTimeout(tid); document.removeEventListener( 'visibilitychange' , clear); } }); } function isPageVisible() { var attrNames = [ 'hidden' , 'webkitHidden' ]; for ( var i = 0, len = attrNames.length; i < len; i++) { if ( typeof document[attrNames[i]] !== 'undefined' ) { return !document[attrNames[i]]; } } return true ; } |
已知的浏览器兼容问题:
- 上述 chrome 和 Android Browser 可以使用 intent 的方式拉起 app
- QQ 浏览器 无法正确判断计时器是否变慢
- 微信浏览器 和 百度浏览器 无法唤起 app 除非加入其白名单
- 安卓4.4.4以前的 UC浏览器无法正确识别为 【安卓系统】需要单独设置判断条件
另: 研究京东唤起APP的代码时,其对百度浏览器做了如下操作,但我们对此的尝试并为成功,如下为其代码, 希望对后续研究此项的同学有帮助 :
function ai(aA) { var aD = ay(aA, true ); var aB = aA.universalLinksUrl + "/ul/ul.action?" + aD; if (navigator.userAgent.indexOf( "baidubrowser" ) >= 0) { window.location.href = aB } else { var az = document.createElement( "a" ); az.setAttribute( "href" , aB); az.style.display = "none" ; document.body.appendChild(az); var aC = document.createEvent( "HTMLEvents" ); aC.initEvent( "click" , !1, !1); az.dispatchEvent(aC) } } |