当所做的h6页面在微信端打开时,想要调起手机内的app,一般我们会用scheme协议监测本地的应用,要是没有则下载app,有的话就直接打开。
但是微信上是屏蔽了,所以我们要是在微信端,则得提示用户用浏览器打开页面再进行监测本地的应用。

tips:如何判断是否在微信浏览器端:

const u = navigator.userAgent;
const isWeixin = u.toLowerCase().indexOf("micromessenger") !== -1;

一、scheme协议

scheme 是一种页面之间跳转的协议,不仅可以用于app之间进行跳转,还可以用于 H5 页面跳转到app页面。

无论Android还是IOS,都可以通过在H5页面中打开 scheme 协议的地址,从而打开本地app。

[scheme]://[host][:port]/[path]?[query]
 
 // 例子:
 sinaweibo://userinfo?uid=3177804914

scheme: 协议名称(由开发人员自定义)(必要,其他都是可选)
host: 域名
port:端口
path: 页面路径
query: 请求参数

每个app的这些协议都不一样根据自己的情况去查找,有些App分IOS和Android的协议是相同的,有些又是不一致的。

那么scheme协议在原生的app内是怎么设置的呢:

<activity
    android:name=".ui.main.ui.activity.SchemeFirstActivity"
    android:screenOrientation="portrait">
    <!--Android 接收外部跳转过滤器-->
    <!--要想在别的App上能成功调起App,必须添加intent过滤器-->
    <intent-filter>
        <!-- 协议部分配置 ,注意需要跟web配置相同-->
        <!--协议部分, sinaweibo://from?type=yangchong  -->
        <data android:scheme="sinaweibo"
            android:host=""
            android:path="/userinfo"
            android:port=""/>


        <!--下面这几行也必须得设置-->
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <action android:name="android.intent.action.VIEW" />
    </intent-filter>
</activity>

二、在浏览器中打开 scheme

注意这步得是在除微信浏览器之外的浏览器中进行,因为在微信浏览器里scheme不起作用。

思路:
首先在本地打开scheme协议,等2秒之后(因为浏览器没有提供是否能打开scheme协议的回调函数,所以只能在这2秒内进行是否离开浏览器的监测判断),要是浏览器能弹出选择跳转app的弹窗,用户选择打开之后离开浏览器之后,那么我们就不弹出要下载app的apk,否则就打开这个apk进行下载。

本次用一个app做例子:

const u = navigator.userAgent;
const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //android终端
const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端

function click(){
	if(isAndroid){
		// 安卓的scheme协议跳转
        window.location.href = "jegotrip://";
        checkOpen();
	}else if(isIOS){
	 // 做个例子,因为也不知道ios的是不是这个
	  window.location.href = "jegotrip://";
	  checkOpen();
	}
}

/**
 * 获取页面隐藏属性的前缀
 * 如果页面支持 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`;
}
/**
 * 检测是否唤端成功
 */
function checkOpen() {
    const visibilityChangeProperty = getVisibilityChangeProperty();
    const timer = setTimeout(() => {
        const hidden = isPageHidden();
        if (!hidden) {
            // 端口唤起失败,下载apk
            if(isAndroid) {
            	window.location = 'https://at.umtrack.com/ry0bya';
            }else {
           		window.location = 'https://at.umtrack.com/SH1vyi';
            }
        }
    }, 2000);
    if (visibilityChangeProperty) {
        document.addEventListener(visibilityChangeProperty, res => {
            clearTimeout(timer);
        });
        return;
    }
    window.addEventListener("pagehide", () => {
        clearTimeout(timer);
    });
}

效果图:

h5 调用android h5 调用 scheme_jquery


注意,有时会有需求说,希望能主动触发click事件,让一进入页面就监测,但是由于浏览器会有拦截自动打开app,所以要特别说明

// 有时在进入页面的时候,直接调用click方法不会触发,可以试试下面的方法
// 模拟在移动端的点击
let theEvent = document.createEvent("Events");
theEvent.initEvent("click", true, true);
document.getElementsByClassName("toAppLink")[0].dispatchEvent(theEvent);