H5唤起APP某页面
做的H5页面,在APP中放了入口,在APP中访问别的页面
场景
我们做的H5页面,希望从浏览器跳转至APP的某个特定页面,如在H5中设置购买按钮,希望点击跳转至APP内部的购买页面。
2、过程
(1)是否安装APP判断
首先浏览器是不能自动判断设备是否安装APP,所以抛出如下弹窗让用户自己选:
- 点击下载APP跳转至对应的下载页面 /download 或根据环境下载ios或Android 的APP
- 点击已安装,APP会通过scheme协议唤起,如:xx,通过a标签添加链接地址,实现跳转。
(2)唤起APP判断
- 唤起APP成功,跳转至APP对应的页面
- 唤起失败,页面没反应,所以此时需要给用户一个toast提示,告诉用户唤起失败
- 我们调起APP成功后快速返回浏览器,仍能看到toast提示,所以需要清除定时器
首先,H5或APP无法判断设备是否调起APP成功,所以在什么时机给用户toast提示,是个问题。
通过时差方案:
1、setTimeout时隔几秒后,给出提示
理想过程是这样:浏览器尝试打开URL scheme,开始计时,n秒后,在当前页面给出“调起失败”的toast提示,如果成功调起APP,清除定时器,当用户在跳转APP后n秒内又返回该页面,不给出“调起失败”的提示。
(1)click触发浏览器打开URL scheme,启动定时任务:
let timer = setTimeout(()=>{ // 给出唤起失败的toast提示信息 }, 6000);复制代码
(2)成功调起APP,判断用户离开了当前浏览器界面, 清除定时器:
判断用户离开页面方法有下面两种:
- onbeforeunload
onbeforeunload该方法兼容性不好,在ios Safari中无法准确判断:
window.onbeforeunload = function () { clearTimeout(timer); }复制代码
- visibilityChange
通过document.hidden或document.[webkit|moz|ms]Hidden来判断页面是否被置入后台(即应用被唤起),或visibilitychange事件,但对于Android 4.4版本以下则不支持。 // 各种浏览器兼容
var hidden, visibilityChange; if (typeof document.hidden !== "undefined") { hidden = "hidden"; visibilityChange = "visibilitychange"; } else if (typeof document.mozHidden !== "undefined") { hidden = "mozHidden"; visibilityChange = "mozvisibilitychange"; } else if (typeof document.msHidden !== "undefined") { hidden = "msHidden"; visibilityChange = "msvisibilitychange"; } else if (typeof document.webkitHidden !== "undefined") { hidden = "webkitHidden"; visibilityChange = "webkitvisibilitychange"; } document.addEventListener(visibilityChange, function() { if(document[hidden]){ console.log('用户没有浏览当前页面,清除定时器'); clearTimeout(timer); }else{ console.log('用户有浏览当前页面,正常发送报错信息'); }复制代码
该方法通过setTimeout判断时间,不同设备可能不同,不够精确稳定。
2、setInterval
但如果设置比较小的运行间隔(<30ms),在浏览器或者webview中,应用切换到后台,setInterval会被很明显的延迟执行。
比如设置一个运行间隔20ms,总计运行100次的定时器,如果页面一直处于前台,则100次跑完,总耗时与100x20=2000ms不会有太大差异,但页面在后台运行时,此时间会明显超过2000ms,利用这一点来实现是否成功打开APP检测及回调。(该方法能够兼容老版本机型,有兴趣的可以用这个方法)
没有完美的解决方案:最终决定采用visibilityChange,能够实现在Android>4.4和ios浏览器环境中,无二次弹窗确认的场景,正常提示。
附坑:
在尝试打开URLscheme 后,如果设备有一个默认的二次确认弹窗,询问是否用 xx应用来打开,往往用户还没来得及点击打开,定时器被触发了,导致toast无法精准提示。
由于微信会屏蔽scheme,所以在微信中无法唤起APP。
查看资料说,「在尝试打开URLscheme 后,再加一个页面跳转,这样对话框会被覆盖,再刷新页面,就能无需确认唤起APP」,亲测这个方案不好用。
- 首先这个情况是无toast提示,直接唤起下载页,与我们现有弹窗逻辑不符;
- 其次唤起下载页及reload的方法体验很不好,在有APP的时候快速跳转至APP,但浏览器界面还是会继续执行后两个location跳转,无APP的时候界面跳转或reload不定,体验不好;
- 最后,不仅二次确认弹窗不仅在部分ios中有,Android部分机型的自带浏览器也会有,无法准确的区分。
以上唤起APP方案是我在开发中遇到采用的,如果有别的逻辑、方案,欢迎评论补充分享。