iOS/Android 浏览器(h5)及微信中唤起本地APP

在移动互联网,链接是比较重要的传播媒质,但很多时候我们又希望用户能够回到APP中,这就要求APP可以通过浏览器或在微信中被方便地唤起。

这是一个既直观又很好的用户体验,但在实现过程中会遇到各种问题:

如何解决未安装APP时的做好引导页 如何在微信中唤醒APP 在iOS9中如何处理universal link被用户误关的情况 如何解决 Android各种机型、各种第三方浏览器导致的兼容问题等 在APP未安装情况下,引导用户下载后打开APP后,如何进入之前唤起时指定的页面或内容,即如何实现场景还原 在微信中唤醒APP时,如何进入指定的页面或内容

下面是我一些个人的经验分享。

浏览器中打开

iOS/Android APP配置

这块内容其实比较简单,在网上都有很多资料可供查阅,就不再赘述。

原理说明

首先需要说明,不管iOS还是Android,浏览器都不可能预知本地是否安装了某个APP的。或者更严谨地说,我们不能通过浏览器来预知本地是否安装。因为就算浏览器可以读取本地应用的安装列表,但是目前也没任何一家浏览器提供查询的API,所以这条路是走不通的。

本质上浏览器是通过URL scheme打开APP,一个APP可以设置一个或多个打开自己的URL scheme。比如,Twitter就注册自己能被「twitter://」打开。

其实,如果是做APP间相互跳转是比较简单的。iOS就可以使用 UIApplication 的 canOpenUrl 方法来检测URL scheme 是否能打开对应的APP。比如,如果「twitter://」检测能被打开,也就说明本地安装了 Twitter 。再用 UIApplication 的 openURL 方法,就能打开Twitter了。Android 中的做法类似。

实现方案

因为iOS9和之前的iOS系统有区别,所以这里我们也要区别对待。

iOS7/iOS8

iOS中默认通过Safari打开URL scheme,方法一般如下两种:

直跳方式:点击链接、修改 window.location 等。 iframe 方式:在 body 上添加 iframe,设置src属性为跳转的URL scheme。

第一种情况:

?
1
window.location.href = http: //blog.youkuaiyun.com/dreamstarting/article/details/schemeUrl;

但在第一种情况,如果APP唤醒失败,或者APP未安装的话,很多时候都会跳到错误页,这很影响用户体验,而我们的要求可能是跳转到其他页面或者下载APP。

后一种方法不会引起页面可见的变化(例如页面内容变成一个新页面),不会导致浏览器历史记录的变化,

过程是这样:点击 a 标签时,首先会尝试打开URL scheme,如果成功,就唤起APP;如果失败,则跳转到 href 属性,即下载页。

Android

但这个方案在很多安卓机型上有问题,为保证可用,改用第一种方案:

?
1
2
3
4
5
6
7
8
9
10
$( 'a' ).click(function() {
     location.href = '自定义 URL scheme' ;
     t = Date.now();
     setTimeout(function(){
         if (Date.now() - t < 1200 ) {
             location.href = 'Android 下载地址' ;
         }
     }, 1000 );
     return false ;
}

理想过程是这样:浏览器尝试打开 URL scheme,在1秒计时后,检查当前时间,如果实际时间已过 1200 毫秒,说明唤起APP 成功(唤起 APP 会让浏览器的定时器变慢);如果没超过 1200 毫秒,很可能是没有安装应用,就跳到下载地址。

或者换种方式:

?
1
2
3
4
5
6
7
8
9
10
11
var 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);
     if ( (+ new Date()) - openTime > 2500 ){
         window.location = 'http://exam.com/xxxx.apk' ;
     }
}, 2000 )

但原理都是一样,利用setTimeout。但这其实不稳定,因为Android是基于Linux的分时多任务的,setTimeout的基准偏差可能会没那么大。

但如果设置比较小的运行间隔(<30ms),在浏览器或者webview中,应用切换到后台,setInterval会被很明显的延迟执行,比如设置一个运行间隔20ms,总计运行100次的定时器,如果页面一直处于前台,则100次跑完,总耗时与 100x20=2000ms不会有太大差异,但页面在后台运行时,此时间会明显超过2000ms。可以利用这一点来实现是否成功打开APP检测及回调。

?
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
<code>function openApp(openUrl, appUrl, action, callback) {
     //检查app是否打开
     function checkOpen(cb){
         var _clickTime = +( new Date());
         function check(elsTime) {
             if ( elsTime > 3000 || document.hidden || document.webkitHidden) {
                 cb( 1 );
             } else {
                 cb( 0 );
             }
         }
         //启动间隔20ms运行的定时器,并检测累计消耗时间是否超过3000ms,超过则结束
         var _count = 0 , intHandle;
         intHandle = setInterval(function(){
             _count++;       
             var elsTime = +( new Date()) - _clickTime;
             if (_count>= 100 || elsTime > 3000 ) {
                 clearInterval(intHandle);
                 check(elsTime);
             }
         }, 20 );
     }
 
     //在iframe 中打开APP
     var ifr = document.createElement( 'iframe' );
     ifr.src = openUrl;
     ifr.style.display = 'none' ;
     if (callback) {
         checkOpen(function(opened){
             callback && callback(opened);
         });
     }
 
     document.body.appendChild(ifr);     
     setTimeout(function() {
         document.body.removeChild(ifr);
     }, 2000 ); 
}</code>

另外,可以通过 document.hidden 或 document.[webkit|moz|ms]Hidden 来判断页面是否被置入后台(即应用被唤起),或visibilitychange事件,但对于Android 4.4版本一下则不支持。

iOS9

在 iOS 9 上,iframe 方案变得不可用。
按不能使用之前Android的代码,因为在打开自定义 URL scheme 时,会弹出对话框,询问是否用 xx 应用来打开。往往用户还没来得及点击打开,定时器又触发了,导致跳到 App Store。

可以在尝试打开URL scheme 后,再加一个页面跳转,这样对话框会被覆盖,再刷新页面,就能无需确认唤起APP:

?
1
2
3
4
5
<code><code><code><code>$( 'a' ).click(function() {
     location.href = '自定义 URL scheme' ;
     location.href = '下载页' ;
     location.reload();
}</code></code></code></code>

这里,下载页延时 2 秒跳转到 App Store。

APP已安装这是没问题的,但如果APP未安装,跳 App Store 的请求会失败。
这时可以使用两个定时器:

?
1
2
3
4
5
6
7
8
9
<code><code><code><code>$( 'a' ).click(function() {
     location.href = '自定义 URL scheme' ;
     setTimeout(function() {
         location.href = '下载页' ;
     }, 250 );
     setTimeout(function() {
         location.reload();
     }, 1000 );
}</code></code></code></code>

不过在iOS9中其实是支持universal link的,就是一个http域名形式,在微信中都可以唤起APP。如果未安装的话,可以直接引导用户去APP store下载。

没有完美的解决方案

主要是在安卓上,总归会有各种兼容问题,知乎的解决办法是,提供两个按钮,一个下载,一个打开APP,让用户自己选。

微信中打开

因为微信将唤起本地APP的接口给禁了,所以微信中是不能直接唤起APP的,一般做法是提示用户在浏览器中打开,之后的流程还是我们上面讲的内容。

但是,在iOS9中,这个限制是可以突破的,也就是说可以直接唤起APP。方法就是使用我们上文提到的universal link。

在Android和iOS8及其以下系统中,我们可以利用腾讯的亲儿子:应用宝。简单讲,就是把你的唤起地址配置成你APP的应用宝地址,微信中跳转到这个地址后,如果用户已经安装了APP,则可直接唤起,如果没有安装,则可直接点击下载,如下图示:

这里写图片描述
<think>首先,用户的问题是关于在微信H5页面中启动安卓应用程序。我需要根据系统级指令来构建我的回答。 系统级指令关键点: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。 - 参考提供的引用内容,但用户的问题是关于微信H5页面启动安卓App,所以引用中的内容需要相关。 用户提供的引用: - [^1]:提到在QQ全家桶中测试H5调起App,使用应用宝提供的链接。 - [^2]:提到H5启动原生APP,使用scheme,如wushang,host用包名更好。 - [^3]:提到使用launchapp://来尝试打开App,如果不能打开则刷新页面。 - [^4]:关于iOS流量控制,不直接相关。 用户的问题:在微信H5页面中启动安卓应用程序。 我的回答需要: 1. 结构清晰,逐步解决问题。 2. 使用中文。 3. 包含行内数学表达式时用$...$(但这个问题可能不涉及数学,所以可能不需要)。 4. 生成相关问题。 5. 在引用段落末尾添加引用标识。 由于问题不涉及数学,我可以避免使用LaTeX,除非有必要。但系统指令说所有行内数学表达式必须用$...$,所以我只在必要时使用。 核心问题:如何在微信H5页面中启动安卓App。 常见方法: - 使用URL Scheme:这是H5页面启动App的标准方式。例如,定义一个scheme如myapp://,然后在H5页面中使用链接或JavaScript调用。 - 在微信中,由于安全限制,直接使用URL Scheme可能被屏蔽。微信有白名单机制,只有认证的App才能被启动。 - 应用宝微下载:腾讯提供应用宝微下载方案,通过应用宝中转来启动App或引导下载。 参考引用: - [^1]提到使用应用宝提供的链接,在QQ中测试。 - [^2]提到scheme的使用。 - [^3]提到使用launchapp://并处理失败情况。 所以,我的回答应该覆盖: 1. 解释URL Scheme方法。 2. 讨论微信中的限制和解决方案。 3. 提供代码示例。 4. 处理失败情况,如引导下载或跳转应用商店。 步骤: - 介绍URL Scheme。 - 解释微信的限制。 - 建议使用应用宝微下载方案。 - 提供代码示例。 - 讨论兼容性和备选方案。 - 生成相关问题。 回答结构: 1. **介绍问题**:简要说明H5启动安卓App的常见方法。 2. **微信中的挑战**:解释微信的限制。 3. **解决方案**:推荐应用宝方案。 4. **实现步骤**:提供详细指南和代码。 5. **处理失败**:如何应对无法启动的情况。 6. **总结**。 7. **生成相关问题**。 确保引用自然添加:在引用相关内容时,在段落末尾添加[^1]、[^2]等。 例如,如果提到应用宝方案,引用[^1];提到scheme,引用[^2];提到刷新页面,引用[^3]。 最终,生成相关问题。</think>### 微信 H5 页面中启动安卓应用程序指南 在微信 H5 页面中启动安卓应用程序是一个常见需求,但微信浏览器(如内置的 X5 内核)存在安全限制,直接使用 URL Scheme 可能被屏蔽或无效。以下我将基于行业最佳实践和参考内容,逐步解释可靠的方法。整个过程分为原理介绍、微信限制分析、推荐方案、代码实现和备选处理,确保回答清晰可靠。 #### 1. **原理:H5 启动安卓 App 的基本机制** H5 页面启动原生 App 主要通过 URL Scheme 实现。URL Scheme 是 App 自定义的协议头(如 `myapp://`),当用户在 H5 页面点击链接或执行 JavaScript 时,系统会尝试调用已安装的 App。如果 App 未安装,则需引导用户下载。例如,Scheme 设计应包含唯一标识符(如 App 包名),以避免系统弹出选择框[^2]。 - **关键点**:Scheme 格式通常为 `scheme://host/path?params`,其中 `host` 建议使用 App 包名(如 `com.example.myapp`)以提高唯一性[^2]。 - **数学示例**:在分析性能时,调用延迟可建模为随机变量,例如平均响应时间 $E[T]$ 与网络条件相关,但本问题不涉及复杂数学,重点在实现。 #### 2. **微信浏览器的限制与挑战** 微信浏览器对 URL Scheme 有严格白名单机制: - 仅腾讯系应用(如 QQ、微信)或通过应用宝认证的 App 才能被直接唤醒[^1]。 - 非白名单 Scheme 在微信中会被屏蔽,导致调用失败(例如,点击链接无响应或跳转错误页)。 - 引用测试案例:在 QQ 全家桶中测试时,使用应用宝链接可正常调起 App,但其他浏览器(如 Chrome)可能无法识别,仅显示下载按钮[^1]。因此,微信环境需要特殊处理。 #### 3. **推荐方案:使用应用宝微下载(腾讯官方方案)** 针对微信限制,最可靠的方法是集成腾讯应用宝的“微下载”功能。应用宝作为中转层,能绕过微信白名单: - **工作原理**:H5 页面使用应用宝提供的专属链接(格式如 `https://a.app.qq.com/o/simple.jsp?pkgname=com.example.myapp`)。用户点击时,微信会先跳转到应用宝页面,自动尝试调起 App;如果 App 未安装,则引导下载。 - **优势**:兼容微信全家桶(QQ、微信等),且无需额外权限[^1]。 - **步骤**: 1. **注册应用宝**:在腾讯开放平台(https://open.tencent.com/)创建应用,配置安卓包名和 Scheme。 2. **获取微下载链接**:在应用宝后台生成 H5 跳转链接。 3. **集成到 H5**:在微信 H5 页面中,使用该链接作为按钮或自动触发点。 #### 4. **代码实现与示例** 以下是一个完整的 JavaScript 实现,结合应用宝方案和直接 Scheme 回退(用于非微信环境)。代码处理了成功调起、失败刷新和下载引导。 ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>启动安卓App示例</title> <script> // 定义App的Scheme和包名(根据实际修改) const SCHEME = 'myapp://'; // 自定义Scheme,如 myapp 对应唯一标识符[^2] const PACKAGE_NAME = 'com.example.myapp'; // App包名 const FALLBACK_URL = 'https://play.google.com/store/apps/details?id=' + PACKAGE_NAME; // 下载页(如Google Play) // 应用宝微下载链接(需在腾讯开放平台配置后获取) const TENCENT_LINK = 'https://a.app.qq.com/o/simple.jsp?pkgname=' + PACKAGE_NAME; function launchApp() { // 检查是否微信环境 const isWeixin = /MicroMessenger/i.test(navigator.userAgent); if (isWeixin) { // 微信中:使用应用宝链接 window.location.href = TENCENT_LINK; } else { // 非微信环境:尝试直接Scheme调用 window.location.href = SCHEME; // 设置超时检测:如果2秒未调起App,则刷新页面或引导下载 setTimeout(function() { if (document.hidden || document.webkitHidden) { // App已调起,页面进入后台 } else { // 调起失败,刷新页面(或跳转下载页)[^3] window.location.reload(); // 或 window.location.href = FALLBACK_URL; } }, 2000); } } </script> </head> <body> <button onclick="launchApp()">启动App</button> </body> </html> ``` **代码说明**: - **微信环境**:直接跳转应用宝链接,自动处理调起或下载。 - **非微信环境**:尝试直接 Scheme 调用(如 `myapp://`),并设置超时检测。如果调用失败(页面未隐藏),则刷新页面或跳转下载页[^3]。 - **优化建议**:在 `setTimeout` 中添加用户提示(如弹窗),避免频繁刷新影响体验。 #### 5. **处理失败情况与备选方案** - **Scheme 调用失败**:在非微信浏览器中,Scheme 可能不被支持(如某些国产手机浏览器)。此时,引导用户手动打开或跳转下载页(如 Google Play)[^3]。 - **微信中备用方案**:如果应用宝认证耗时,可临时使用“点击右上角浏览器打开”提示,让用户在外部浏览器中触发 Scheme。 - **通用兼容性**:测试多环境(如 QQ、Chrome),确保方案健壮。引用案例显示,QQ 中应用宝链接有效,但其他浏览器需独立处理[^1]。 #### 6. **总结** 在微信 H5 页面启动安卓 App,核心是优先使用应用宝微下载方案解决微信限制,辅以直接 Scheme 调用处理非微信环境。代码实现需包含超时检测和下载引导,确保用户体验。实际部署前,务必在腾讯开放平台完成 App 认证,并测试不同场景[^1][^2][^3]。对于流量优化(如后台刷新),可参考类似移动端设置[^4],但本问题不直接相关。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值