APP

H5唤端

参考资料


H5唤起APP指南(附开源唤端库)
NPM包 callapp-lib
H5唤起APP小结(附开源唤端库)
H5唤起APP
HTML打开APP & android chrome禁止自动跳转


唤端成功判断逻辑

第一种方案


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/**
* 获取页面隐藏属性的前缀
* 如果页面支持 hidden 属性,返回 '' 就行
* 如果不支持,各个浏览器对 hidden 属性,有自己的实现,不同浏览器不同前缀,遍历看支持哪个
*/
function getPagePropertyPrefix() {
const prefixes = ['webkit', 'moz', 'ms', 'o'];
let correctPrefix;

if ('hidden' in document) return '';

prefixes.forEach((prefix) => {
if (`${prefix}Hidden` in document) {
correctPrefix = prefix;
}
});

return correctPrefix || false;
}

/**
* 判断页面是否隐藏(进入后台)
*/
function isPageHidden() {
const prefix = getPagePropertyPrefix();
if (prefix === false) return false;

const hiddenProperty = prefix ? `${prefix}Hidden` : 'hidden';
return document[hiddenProperty];
}

/**
* 获取判断页面 显示|隐藏 状态改变的属性
*/
function getVisibilityChangeProperty() {
const prefix = getPagePropertyPrefix();
if (prefix === false) return false;

return `${prefix}visibilitychange`;
}

/**
* 检测是否唤端成功
* @param {function} cb - 唤端失败回调函数
*/
export function checkOpen(cb, timeout=2000) {
const visibilityChangeProperty = getVisibilityChangeProperty();
const timer = setTimeout(() => {
const hidden = isPageHidden();
if (!hidden) {
cb();
}
}, timeout);

if (visibilityChangeProperty) {
document.addEventListener(visibilityChangeProperty, () => {
clearTimeout(timer);
});

return;
}

window.addEventListener('pagehide', () => {
clearTimeout(timer);
});
}

获取判断页面 显示|隐藏 状态改变的属性,可能结果:

visibilitychange

webkitvisibilitychange

mozvisibilitychange

msvisibilitychange

ovisibilitychange

false

获取页面隐藏属性,可能结果:

hidden

webkitHidden

mozHidden

msHidden

oHidden

false

timeout间隔后,通过isPageHidden返回值 判断唤起是成功 false代表失败 失败则执行回调

document.hidden

document.webkitHidden

document.mozHidden

document.msHidden

document.oHidden

false

如果显示|隐藏 状态改变的属性存在

1
2
3
4

document.addEventListener(visibilityChangeProperty, () => {
clearTimeout(timer);
});

如果显示|隐藏 状态改变的属性不存在

1
2
3
window.addEventListener('pagehide', () => {
clearTimeout(timer);
});


第二种方案 setTimeout / setInterval 设置延时


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
setTimeout
浏览器尝试打开URL scheme并记录时间点t1,在2秒计时后,检查当前时间t2
如果t2-t1 > 2200ms,说明唤起app成功(唤起app会是浏览器的定时器延后执行)
如果t2-t1 < 2200ms,可能没有安装app,可以引导用户进入下载页。
let openTime = +new Date();
window.location.href =
let timer = setTimeout(function () {
if ((new Date()) - openTime < 2200) {//加了200ms基准误差
window.location.href = 'https://d.douyin.com/2QvJ/';
}
if ((new Date()) - openTime > 2200) {
clearTimeout(timer);
}
}, 2000);

方案二 setInterval
跟setTimeout相似,方法上换成设置一个比较小的时间间隔(例如20ms)运行多次(例如100),比较运行完100次的总耗时与20*100的时间差。
逻辑判断同setTimeout。
let limit_num = 100;
let openTime = +new Date();
let timer = setInterval(function () {
if (limit_num > 0) {
limit_num--;
} else {
if ((new Date()) - openTime < 2200) {//加了200ms基准误差
window.location.href = 'https://d.douyin.com/2QvJ/';
}
clearTimeout(timer);
}
}, 20);

分享到