Skip to content

H5唤起APP的小结[每天进步一点点系列] #32

Description

@stuxt

背景

最近在做DeepLink的需求,DeepLink不算是一个新话题了,但是却一直都没间断过讨论。开始接触之前了解并不是很多,但是接触下来发现也就那几种实现方式。

什么是DeepLink呢?其实就是H5页面提供一个按钮,例如:“打开APP”或者“下载APP”等。在H5页面中点击这个按钮,如果安装了目标APP直接通过链接唤起,否则跳转到下载页面去下载APP。这种通过H5唤起APP的链接的方式就是DeepLink。

看起来很简单的一个业务流程,但是实现起来还是有很多坑的,主要是因为设备、设备版本、浏览器等碎片差异严重,导致很多兼容需要处理。

最终实现的效果

用户点击H5页面的打开App或者下载按钮(这个按钮可能在一个下载入口页、各种分享页面的吸顶或吸底的banner),如果用户已经安装了App,则根据业务跳转到相应的Native页面;如果用户没有安装该应用,则跳到AppStore或者应用市场去下载App。

default
图1:各种实现方式

已安装APP时的实现方式

一、iOS中的实现

iOS中在IOS9.0前后是一个分界点,因为从iOS9.0之后苹果开放universal link的方式代替schema的方式来唤起APP。下面我们就分别从iOS9.0前后分别来说:

1、iOS9.0之前

iOS9.0之前苹果和安卓的实现方式都是通过schema的方式来实现的。但是跳转方式也有很多种(window.location.href方式、a链接方式、iframe方式等),经过测试和查阅资料发现,iOS9.0之后的跳转方式选择iframe的方式是最靠谱的方式。代码如下所示:

function openOrDownload() {
		var ifr = document.createElement('iframe');
    		ifr.src = 'test.1234://deeplink?token=1111111';
    		ifr.style.display = 'none';
    		document.body.appendChild(ifr);
}

2、iOS9.0+

iOS9.0+后的版本的苹果设备,开始支持universal link的实现方式,当然schema的方式也是被支持的,只不过在遇到未安装的时候会弹出一个丑陋的错误提示框,即使安装了也还是会弹窗询问用户是不是要打开APP,用户体验不好。

universal link的实现方式在网上有很多很详尽的说明和示例,此处不做详细说明。

当然,universal link的实现方式需要客户端和服务端的配合。

对于跳转方式iOS9.0+后选用a链接的方式最靠谱,iframe的方式已经无法使用了。a链接的示例代码如下所示:

        let t = document.createElement("a");
        iframeState = t;
        t.style.display = "none";
        t.href = url;
        document.body.appendChild(t);
        t.click();

二、Android中的实现

安卓中的实现方式比起苹果设备来看要更加复杂一点,因为有一些过长的浏览器总是奇葩的存在(如:UC)。
但是在安卓中目前schema是实现的主要方式,跳转方式通过测试,也是iframe的方式最靠谱。实现方式如上面iframe实现方式所示。

未安装的实现方式

因为在H5中是无法获取到设备中app的安装情况,无法判断是否安装,只能采用尝试打开的方式,如果已经安装则直接打开,如果未安装,通过时间差的方式来判断做出跳转到下载页面的操作。

其实,这个过程中还是存在一些坑的,比如跳转到app了,返回H5页面后还是会跳转到下载页面,因为浏览器差异兼容情况不一,始终没有完美的方案,只能通过如下方式尽量来兼容。

实现代码如下所示:

        var o = setTimeout(function() {
		    	document.body.removeChild(ifr);
		        document.hasFocus() && (window.location = 'http://www.baidu.com')
		    }, 1000);

	var hidden,
            visibilityChange;
	        if (typeof document.hidden !== "undefined") {
	            hidden = document.hidden;
	            visibilityChange = "visibilitychange";
	        } else if (typeof document.mozHidden !== "undefined") {
	            hidden = document.mozHidden;
	            visibilityChange = "mozvisibilitychange";
	        } else if (typeof document.msHidden !== "undefined") {
	            hidden = document.msHidden;
	            visibilityChange = "msvisibilitychange";
	        } else if (typeof document.webkitHidden !== "undefined") {
	            hidden = document.webkitHidden;
	            visibilityChange = "webkitvisibilitychange";
	        } else {
	            hidden = false;
	        }

	        document.addEventListener(visibilityChange,
	            function() {
	                 clearTimeout(o);
	            },
	        !1)

通过上面的实现方式可以兼容大部分,但是有些还是有问题,iOS下的safari就有问题,可以再加上如下代码,safari问题就可以解决了,代码如下:

        /**
         * 兼容safari 唤醒APP后仍跳转下载页面的问题
         */
        window.addEventListener("pageshow", function(evt){
            clearTimeout(o);
        }, false);

        window.addEventListener("pagehide", function(evt){
            clearTimeout(o);
        }, false);

微信、QQ等的实现方式

目前所有的直接再微信里面跳转APP的方式都已经行不通了,只有两种处理方式:1、提示在浏览器打开 2、通过应用宝来打开。

QQ、微博等,都是差不多的,具体没有一一测试,但是腾讯系的都可以通过应用宝的方式解决,其他的就提示浏览器打开吧。

基本H5唤起APP的大概的实现方式已经做了简单的介绍。

最后再吐槽一个莫名其妙的坑,就是ios中在safari中使用schema打开应用,应用没有安装的时候,会跳转App Store,如果第一次提示打开App Store时,选择“取消”,那么再点击的时候是无法跳转到App Store的,具体不知道苹果是怎么想的。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions