移动互联时代,很多互联网服务都会同时具备网站以及移动客户端,很多人认为APP的能帮助建立更稳固的用户关系,于是经常会接到各种从浏览器、webview中唤醒APP的需求,显然,这对于前端开发人员来说,是一件很纠结的事。
##唤醒APP
目前常见的主动唤醒APP方式有几种:
###Url scheme
Url scheme是iOS,Android平台都支持,只需要原生APP开发时注册scheme, 那么用户点击到此类链接时,会自动跳到APP。比如
如果配置scheme的路径,并在app中识别,则可以直接打开APP特定页面,如下:
上述的链接,需要考虑手机是否支持此Scheme:
支持:弹出相应程序;
不支持:错误处理情况因平台而异,部分app会直接跳错误页(比如Android Chrome/41,iOS中老版的Lofter); 也有的停留在原页面,但弹出提示“无法打开网页”(比如iOS7);iOS8以及最新的Android Chrome/43 目前都是直接停留在当前页,不会跳出错误提示。
总体来看, iOS的支持程度比Android好,iOS在实际使用中,除非明确禁止的(比如微信),很少碰到不支持的情况;Android平台则各个app厂商差异很大,比如Chrome从25及以后就不再支持通过js触发(非用户点击),设置iframe src地址等来触发scheme跳转。
###Android intent
这是Android平台独有的,使用方式如下
这里的HOST/URI-path, 与普通http URL 的host/path书写方式相同, package是Android app的包名,其它参数如action、category、component不是很理解, 具体见文档 , 比如打开考拉 app的商品详情,代码如下
如果手机能匹配到相应的APP,则会直接打开;如没有安装,则会跳到手机默认的应用商店,比如Google原生系统Nexus 5,将会直接跳到Google Play, 对于国内各厂商定制过的系统,则跳转到各自的默认应用商店,或者弹出商店供选择。
intent 比scheme相对完善的一点是,提供一个打开失败去向URL的选项,可以通过指定参数
比如如下的打开APP动作,如果打开失败,则跳转到app下载页,这对于国内的特殊网络环境,还是挺有用的。
###HTTP URL订阅
Android Chrome平台独有,app中订阅自有内容相关的URL,在Chrome中浏览相关网页时,会自动弹出提示,让用户选择用浏览器还是APP打开,通用性有限。
###iOS内置APP广告条
在页面Head中增加meta, 添加智能 App 广告条 (iOS 6+ Safari), 如下
可以自动判断是否已安装应用, 可惜只能用于iOS+Safari, 在第三方应用中就不行了。
效果如下:

###Android Chrome内置app安装提示
这个是Mobile Chrome 43 beta新加入的特性,在用户浏览某一个网站多次后,如果Chrome发现该站点有原生APP,则会提示用户下载原生APP,此项特性开发者无法干预,完全是Google的推荐行为,在项目中用不上,具体见新闻报道
##实际应用中存在的问题
移动平台提供这么多唤醒APP的方法,但是功能还不够完善,以下情况JS无法检测并做处理:
那Android 浏览器有没有方法检测应用是否进入了后台呢? 页面可见性API(Page Visibility API), 可以通过检测
暮然回首,那人却在灯火阑珊处,
代码如下:
iframe方式打开APP的问题:
微信无法打开或者下载,打开APP这个基本无解,下载则只能让应用进驻应用宝市场,然后检测到在微信中运行时,跳转到应用宝页面下载。
###2015-11-01 补充
随着iOS9, Android M的推出, 原先的Scheme URL唤醒app的方式成功率以及很低,并且苹果还加入了确认机制,使得通过javascript来自动唤醒APP的方式基本不可用。
这两大平台都推出了自己的WEB与APP连接的方式: Universal Links, App Link, 这部分需要App的开发人员来做了。
##唤醒APP
目前常见的主动唤醒APP方式有几种:
###Url scheme
Url scheme是iOS,Android平台都支持,只需要原生APP开发时注册scheme, 那么用户点击到此类链接时,会自动跳到APP。比如
|
|
如果配置scheme的路径,并在app中识别,则可以直接打开APP特定页面,如下:
|
|
上述的链接,需要考虑手机是否支持此Scheme:
支持:弹出相应程序;
不支持:错误处理情况因平台而异,部分app会直接跳错误页(比如Android Chrome/41,iOS中老版的Lofter); 也有的停留在原页面,但弹出提示“无法打开网页”(比如iOS7);iOS8以及最新的Android Chrome/43 目前都是直接停留在当前页,不会跳出错误提示。
总体来看, iOS的支持程度比Android好,iOS在实际使用中,除非明确禁止的(比如微信),很少碰到不支持的情况;Android平台则各个app厂商差异很大,比如Chrome从25及以后就不再支持通过js触发(非用户点击),设置iframe src地址等来触发scheme跳转。
###Android intent
这是Android平台独有的,使用方式如下
|
|
这里的HOST/URI-path, 与普通http URL 的host/path书写方式相同, package是Android app的包名,其它参数如action、category、component不是很理解, 具体见文档 , 比如打开考拉 app的商品详情,代码如下
|
|
如果手机能匹配到相应的APP,则会直接打开;如没有安装,则会跳到手机默认的应用商店,比如Google原生系统Nexus 5,将会直接跳到Google Play, 对于国内各厂商定制过的系统,则跳转到各自的默认应用商店,或者弹出商店供选择。
intent 比scheme相对完善的一点是,提供一个打开失败去向URL的选项,可以通过指定参数
S.browser_fallback_url 来指定去向URL。比如如下的打开APP动作,如果打开失败,则跳转到app下载页,这对于国内的特殊网络环境,还是挺有用的。
|
|
###HTTP URL订阅
Android Chrome平台独有,app中订阅自有内容相关的URL,在Chrome中浏览相关网页时,会自动弹出提示,让用户选择用浏览器还是APP打开,通用性有限。
###iOS内置APP广告条
在页面Head中增加meta, 添加智能 App 广告条 (iOS 6+ Safari), 如下
|
|
可以自动判断是否已安装应用, 可惜只能用于iOS+Safari, 在第三方应用中就不行了。
效果如下:

###Android Chrome内置app安装提示
这个是Mobile Chrome 43 beta新加入的特性,在用户浏览某一个网站多次后,如果Chrome发现该站点有原生APP,则会提示用户下载原生APP,此项特性开发者无法干预,完全是Google的推荐行为,在项目中用不上,具体见新闻报道
##实际应用中存在的问题
移动平台提供这么多唤醒APP的方法,但是功能还不够完善,以下情况JS无法检测并做处理:
- APP如果唤醒失败,很多时候都会跳到错误页,影响用户体验,而我们的需求很可能是需要跳到下载或者其它页。
- APP成功唤醒,页面无法直接得知,系统没有提供此类回调。
- 要在打开APP失败时,不能使当前页面跳到错误页,且打开失败时,有失败函数回调。
- 如果成功打开APP,有成功函数回调。
针对第一点,可以将打开动作放到iframe中,就算跳转失败仍能停留在当前页面;那剩下的问题就是如何检测APP是否成功打开;
网上常见解决方案如下:1234567891011121314//创建一个隐藏的iframevar ifr = document.createElement('iframe');ifr.src = 'com.baidu.tieba://';ifr.style.display = 'none';document.body.appendChild(ifr);//记录唤醒时间var openTime = +new Date();window.setTimeout(function(){document.body.removeChild(ifr);//如果setTimeout 回调超过2500ms,则弹出下载if( (+new Date()) - openTime > 2500 ){window.location = 'http://exam.com/xxxx.apk';}},2000)
那Android 浏览器有没有方法检测应用是否进入了后台呢? 页面可见性API(Page Visibility API), 可以通过检测
document.hidden 或 document.[webkit|moz|ms]Hidden 来检查页面是否可见,或者订阅页面的visibilitychange事件; 如果仅仅应用在新版Android及Chrome上,这个是很美好的,对于老版本(<4.4)及Android Webview, 则不可用。暮然回首,那人却在灯火阑珊处,
setInterval,对,就setInterval, 如果设置比较小的运行间隔(<30ms),在浏览器或者webview中,应用切换到后台,setInterval会被很明显的延迟执行,比如设置一个运行间隔20ms,总计运行100次的定时器,如果页面一直处于前台,则100次跑完,总耗时与 100x20=2000ms不会有太大差异,但页面在后台运行时,此时间会明显超过2000ms。可以利用这一点来实现是否成功打开APP检测及回调。代码如下:
|
|
iframe方式打开APP的问题:
- Android Chrome/25+ 无法打开APP,所以最好是APP配合监听http URL 来实现。
- iOS、Android平台,近期发现在没有安装对应app时尝试唤醒,有少数APP会连当前页面(iframe的父页面)也变成错误页的情况。
微信无法打开或者下载,打开APP这个基本无解,下载则只能让应用进驻应用宝市场,然后检测到在微信中运行时,跳转到应用宝页面下载。
###2015-11-01 补充
随着iOS9, Android M的推出, 原先的Scheme URL唤醒app的方式成功率以及很低,并且苹果还加入了确认机制,使得通过javascript来自动唤醒APP的方式基本不可用。
这两大平台都推出了自己的WEB与APP连接的方式: Universal Links, App Link, 这部分需要App的开发人员来做了。