前言
公司要做在H5页面内唤醒我们公司的App功能,在此记录一下解决方法与参考文章。
原理
js没有办法获取到客户端是否安装了某个APP,所以我们可以用定时器在后台运行时会变慢的功能去模拟实现
URL scheme方式
首选需要判断当前机型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// 判断浏览机型
var browser={
versions:function(){
var u = navigator.userAgent;
return {
u: u,
trident: u.indexOf('Trident') > -1, //IE内核
presto: u.indexOf('Presto') > -1, //opera内核
webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,//火狐内核
mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, //android终端
iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器
iPad: u.indexOf('iPad') > -1, //是否iPad
Mac: u.indexOf('Macintosh') > -1, // 是否是Mac
webApp: u.indexOf('Safari') == -1, //是否为Safari浏览器
weixin: u.indexOf('MicroMessenger') > -1, //是否微信
qq: !!u.match(/\sQQ|\sTIM/i) //是否QQ或TIM
}
}()
};需要区分是否是微信端(微信不允许在其中打开第三方APP,不过好像是有白名单之类的功能,具体情况没了解到),微信端解决方案有两个:
- 使用引导页,点击下载按钮时引导用户在浏览器中打开页面进行唤醒或下载
- 直接跳转下载页,用户在app Store中打开
URL scheme由客户端生成,打开此App的专属链接。(比如:
weixin://
这种形式)核心代码:
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/**
* 打开app事件,未下载则跳转下载链接
* downUrl: 下载链接
* openUrl: 打开APPSchema
* callback: 回调函数
*/
function openApp(downUrl,openUrl,callback) {
// 检查APP是否打开
function checkApp(cb) {
var _clickTime = +(new Date());
var flag = false;
function check(elsTime) {
if(elsTime > 3000 || document.hidden || document.webkitHidden) {
flag = true;
cb(flag);
console.log(elsTime,"s,elsTime超过3000了不会自动跳转下载了");
}else {
cb(flag);
console.log("elsTime未大于3000,跳转下载链接")
}
}
var _count = 0;
var timer = setInterval(function() {
_count ++;
var elsTime = +(new Date()) - _clickTime;
if(_count >= 100 || elsTime > 3000) {
clearInterval(timer);
check(elsTime);
}
},20);
}
// 创建a标签并触发点击跳转下载,两秒后删除
var ifr = document.createElement('a');
ifr.href = openUrl;
$(ifr).css({display: 'none'});
var event = document.createEvent('MouseEvents');
event.initEvent('click',false,false);
ifr.dispatchEvent(event);
if(callback) {
checkApp(function(opend) {
callback && callback(opend)
})
}
$('body').append(ifr);
setTimeout(function() {
$('body')[0].removeChild(ifr);
},2000);
}进入方法后首先创建了a标签,href为打开app的openUrl,然后用createEvent事件触发了a标签。进入checkApp方法生成一个定时器,如果没有安装app的话则_count会先大于等于100,此时的elsTime是没有大于3000的,所以可以在回调函数内进行下载链接跳转。但是如果安装了app(弹窗提示是否打开此app时页面是假死状态)打开后,定时器加载会变慢,那么elsTime就会大于3000,所以不进行跳转下载链接。
使用方法:
1
2
3
4
5
6
7
8
9
10
11if(browser.versions.iPhone || browser.versions.iPad){ // 机型判断
if(!browser.versions.weixin){
openApp(downloadUrl,openUrl,function(flag){
if(!flag) {// 跳转下载页
window.location.href = downloadUrl;
}
})
}else {// 微信直接跳转下载,不必等2s
window.location.href = downloadUrl;
}
}优化
因为没有安装app的话需要等待两秒才跳转下载链接,所以这两秒的时间内给用户一个提示避免用户以为手机死掉了,优化后代码:
1
2
3
4
5
6
7
8
9
10
11
12
13if(browser.versions.iPhone || browser.versions.iPad){ // 机型判断
// popupHint('正在打开APP...'); // 弹窗提示
if(!browser.versions.weixin){
openApp(downloadUrl,openUrl,function(flag){
// popupHint('','none'); // 有回调后关闭弹窗
if(!flag) { // 跳转下载页
window.location.href = downloadUrl;
}
})
}else { // 微信直接跳转下载,不必等2s
window.location.href = downloadUrl;
}
}
Universal Link
Schema 的弊端能通过Universal Link解决。
在没装App的时候,Universal Link是一个合法的url链接,浏览器可以正常跳转,因此不会出现在iOS上讨人厌的框。
Universal Link目前还没有基于iOS的UI/WKWebView的应用进行拦截,所以目前看还是能突破微信/手百的封锁。
配置apple-app-association文件
究竟哪些的url会被识别为Universal Link,全看这个apple-app-association文件
- 你的域名必须支持Https
- 域名根目录下放这个文件apple-app-association,不带任何后缀
- 文件为json保存为文本即可
- json按着官网要求填写即可
因为此方法需要域名支持https,所以我没有进行测试,是用URL scheme方法解决的,so没有代码例子
参考
ios:
从微信/H5中调起iOS应用(这是一个总结了几个方法的文章)
Android下解决方法:
支持IOS9+和Android5+,JS打开APP的解决方案
结语
URL scheme的解决方法可以应付大部分场景了,微信端访问时引导用户通过safari打开进行下载。
有些Android低版本的系统,浏览器在访问URL scheme时会像打开url链接一样打开,导致404,如果需要向下兼容时就需要再研究一下了!