支持IOS9+和Android5+,JS打开APP的解决方案

该话题,也是一个老话题了,就是在移动端开发中,经常能碰到的一个问题,如果在浏览器,仅使用链接或者再加上JS,就打开对应的APP呢?如果您正在找这方面的问题,那么接下来的内容,也许会给您一些帮助。

前提

首先,我们可以先看知乎上的一个讨论:iOS9中『经浏览器唤起APP』的最佳实现方案是怎样的?,看了这个问题,那么我们就对于接下来要做的事情,有了一些基本的概念了。

兼容性

在前两年,IOS9,Android5之前(具体版本不清楚),有一个还不错的解决方案是使用iframe配合时间差的方式来唤起APP,然后在本页内,做定时处理,也就是在前面文章中,第二条的描述。因为在大多数(不确定是不是所有移动设备都这样,不过我认为可以放弃不支持的那些)的移动设备中,如果浏览器进入后台运行,那么在浏览器内部的JS,也会停止执行,所有当你再回到浏览器时,会有时间差的概念,以这个时间差,可以来分辨是否已经成功打开了APP,然后再可以继续做接下来的逻辑。

那么之前为什么会使用iframe,而没有直接使用location.href呢?location.href虽然在IOS下的表现与使用iframe没有太大的区别,但是在Android的一些机型上,会直接跳转到一个错误页,所以,在这个时候,只能使用iframe的了。

第二,这是当时的另外一种解决方案,那就是两者都跳转,先尝试打开APPurl,然后当前页面也跟着跳转。这个方案我当时在好些个网站都看到了该方法,它有一个好处就是,不会出现页面假死的状态,也有一个坏处就是,会浪费用户的流量。

既然说到兼容性,那么就说明上面的方法,现在已经出现问题了,是的,前端开发者一般最怕的就是浏览器的兼容问题(现在好多了,至少不需要兼容IE6了),以前是浏览器的兼容,现在又加了客户端的兼容了,比如这里,IOS9Android5版本之后,浏览器想要打开APP,是需要用户去手动确认的,主要是一种安全机制,防止恶意代码,不受限制的去打开APP,对于用户来说,这是一个更安全的机制,但是对应开发来说呢?

这个提示图就是这样的:(直接引入的知乎中的一张图)

同样上面的需求,同样上面的两种解决方案,就会出现这样的问题:

1:iframe

的计时已经结束了,用户并未点击确认按钮,然后页面直接跳转了。

2:直接跳转的方式更是直接完蛋,这个提示打开APP的弹框刚出来,直接页面跳转,弹框没有了。

这就是现在存在的问题,只是在网上,一直没有找到好的解决方案,但是又不能放任该问题存在,所以这里给出一个折中的方案。

新的方案

在说新方案前,先来说一说,解决过程中,有哪些问题:

1:浏览器端无法检测是否安装有某个APP

2:客户端的安全机制,弹出的确认框,它是浏览器的底层行为,不会阻塞JS的运行,也无法通过JS调用浏览器的接口,来判断该弹出层的状态。

那么我们根据上面的内容,来提出一些新的解决方案,就像平时做兼容性处理一样,可以根据客户端的版本来做不同的处理。

IOS9之前和Android5之前的版本,依然使用之前的方法,这里说的之前的方法,就是使用iframe配合时间差来做判断,或者是页面跳转的同时,也打开APP

那么对应之后的版本呢,这里就要判断一下了,时间差判断的解决方案,基本是行不通的了,因为这牵扯到了用户的反应过程,那么这个时间差就不好设置了。太短了不行,如果有APP的话,可能用户还没有操作,这边就执行来页面的跳转;太长了也不行,如果没有APP的话,页面会在这里假死一段时间,用户体验也是不好。

那M站的URLAPPURL同时跳转,这个不可用的原因,前面也说过了。

那是否有一个稍微好一些的解决方案呢,这个我们可以按照前面解决方案中,进行一些小的改动,比如把两者合并,两个URL同时跳转,但是M站的URL直接使用iframe来显示,而这个iframe直接覆盖全屏,这样OK吗?

虽然还是比较消耗用户的流量,但却解决了一下用户体验方面的问题。至少页面不会出现假死,而且当用户安装有APP时,可以把一部分用户量,导入到APP中去。

到了这里,这个解决方案基本差不多了,但是这个时候,如果我想要返回,要怎么返回呢,因为是iframe显示的另外一个新页,那么就有一个问题,返回是无法再返回原来的页面了,这样又会带来另外的体验问题,所以呢,这里我们就可以使用另外一个新的(挺老的)浏览器熟悉,history.pushState属性,这样不管是在点击IOS的浏览器返回,还是Android的浏览器返回和客户端返回,都可以会触发window.onpopstate的回调函数,那么在这个回调函数中,我们把之前显示的iframe更新掉就OK了。

其实到这里,基本就把这个问题的一个取巧的解决方案说完了,下面就直接看个示例吧。

PC端看源码链接:http://zhangyunling.com/study/2016/20161112/index.html

Mobile端看效果,请扫二维码:

注:微信中的没有做处理,所以请在浏览器看哦;

注:代码中,使用时间差的那个方法,是借鉴自别人的方法,不过现在找不到来源了,不好意思啊~~

2016-12-28更新,之前的源码中,正则写错了,所以导致IOS10系统无法吊起APP,感谢suface评论指出,现在已经更新了

好久没有写东西了,感觉都不知道怎么写了,上面的内容,其中的一些观点是跨度比较大的总结,所以现在真实的情况已经有所出入,如果您有这方面的总结或者经验,请赐教,谢谢!

本文属于原创文章,转载请注明出处,谢谢!

本文地址:http://www.zhangyunling.com/?p=559

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

支持IOS9+和Android5+,JS打开APP的解决方案》有21个想法

  1. buling buling说道:

    如果没有下载页面,安卓的下载地址直接是apk 的地址的话有没有什么办法避免这个问题呢?

    1. 这个应该是OK的吧?我这里之所以是使用下载页来做跳转判断,是因为下载的时候,是需要判断平台的,比如你在Android是跳转到apk的下载,在IOS是跳转都App Store下载等。

      我这里假设,这个判断是在下载页做了,所以这里就是单纯的尝试打开APP的,没有耦合下载的功能,如果你需要的话,可以在已有代码的基础上,进行修改。

  2. raferxu说道:

    试了一下出现,打开app的时候也会出现下载提示,请问这是安卓或iSO要做什么设置吗?谢谢

    1. 在浏览器打开APP的时候,因为无法确认手机端是否已经安装了APP,所以会同时跳转到下载页,牺牲了一部分体验,以保证功能正常。

      你说是这个意思吗?

  3. 菜鸟杨说道:

    我想请问一下,为什么同一个按钮会出现三种状态 ,有时候可以调起APP,有时候只弹出打开按钮,但是点击后没响应,最后一种直接没响应。能帮忙分析下这种情况是怎么回事吗?跪求解惑

    1. 菜鸟杨说道:

      不是同一个按钮,是同一页面的多个按钮

      1. 菜鸟杨说道:

        发现是我自己的问题,感谢分享,内容写的很赞,感觉你和张鑫旭分享的干货很丰富,得仔细看看。

  4. 汤玉鹏说道:

    你这种写法在qq中无法拉起应用你

    1. QQ没有太用到过,所以没有测试,这个就跟微信一样,如果客户端端限制了,是无法打开的,或者可以认为,这种方案是属于浏览器中的解决方案,如果在客户端的话,那么特别受限于客户端是否支持。

  5. 张三说道:

    没什么用,iOS10会弹个框:safari打不开该网页,因为网址无效。相当于错误页了。

    1. 是这样的,我是使用的location.href直接尝试唤起的,如果未安装,就会有这样的提示,这个在iOS9之后,就会这样的。这个解决方案并不完善,只是一个折中的解决方案,如果想要更完善的,需要客户端,运维,后端多方的配合才行,这个就需要更多的研究了,对那个方案,我也没有自己去做实现,你们如果需要的话,可以尝试一下。

      1. 张三说道:

        你是说那个通用网址吧,直接用http的链接了。那个需要站点有https的证书。

  6. 望尘说道:

    var appUrl = “QDReader://”; 这个 QDReader:// 是什么来的??

    1. 这个是客户端的schema协议,用来呼起指定客户端的。

      1. 望尘说道:

        好像通过这个方式唤起app 都会弹出一个确认框,要用户确认了才可以打开,如果用户选择了取消还是打开不了, 有什么办法能监测到用户选择了 打开还是取消 吗?

        1. 那个确认的弹窗,是手机浏览器系统级别的弹窗,好像没有方法能监听到那个的回调,就算是有的话,那还要去确认是否各个浏览器,都能监听到,这个的兼容问题,就更大了,我觉得,可以不去考虑这个问题吧。

  7. 西部世界说道:

    我是用openinstall解决这个问题的

  8. yvette说道:

    ios10 用safari不能打开app store

    1. 你是从DEMO点击过去吗?DEMO中,没有跳转到appStroe的,所以是无法打开app store的。不知道我理解的是不是你想说的意思?

  9. suface说道:

    貌似 ios 10 打不开了. 只能下载页面了

    1. 请确认是否下载了起点读书的APP,如果您手机没有这个软件的话,那是会进下载页面的。

      还会直接有个提示框提示,链接无效什么的。

      这个我当前无法确认,因为手边没有IOS10的系统,我下周再确认一下IOS10的系统,会不会这样,感谢提出问题。