您当前的位置:首页 > 计算机 > 编程开发 > Html+Div+Css(前端)

Web 网页调起本地 App 的方式解析

时间:12-14来源:作者:点击数:

很多人会遇到这个问题,大多数都是站在移动端的角度去解释这个问题,本篇文章将会从 web 端的角度分析问题,解决问题

背景

了解背景,有助于我们更加深入的理解需求,分析需求

用户和流量的量级决定了一款互联网产品的优秀度。对一款优雅的互联网产品而言,app 端和 web 端是必不可少的,我们借助它们形成闭环,保证用户体验和活跃度。除了端的覆盖,我们还要做到端到端的交互,由此我们提出了产品的需求: wap 页唤起 app,如果用户没装 app 则跳转到下载页(引导页都行)。如果用户已安装,根据 URL 跳到app 内指定的界面,这也正是本文正要解决的问题。

1. 先说一个最常规的方法,也是最常用的方法:scheme

wzry://videolists.show/mark/penta_kill?num=1

这种方式需要事先在 app 中注册相应的 scheme,通过网页访问已注册的 scheme,达到调起 App 客户端及相关界面

Android 的相关配置: AndroidManifest.xml

<activity android:name=".ui.SchameFilterActivity">
	<intent-filter>
	<action android:name="android.intent.action.VIEW" />
	<category android:name="android.intent.category.DEFAULT" />
	<category android:name="android.intent.category.BROWSABLE" />
	<data
	    android:host="videolists.show"
	    android:path="/mark/penta_kill"
	    android:scheme="wzry"/>
	</intent-filter>
</activity>

至于定义scheme以后的逻辑请自行 google,但是逻辑中一定要做防护

好了我们可以愉快的使用了

<a href="wzry://videolists.show//mark/penta_kill?vid=666">你过来啊!</a>

你也用直接访问地址的方式,这种方式有小坑:有些浏览器是会返回 404 状态码,或者变成搜索结果页,声明 sheme 后,回过头来看一下需求:用户安装了 app,调起 app。用户未安装我们需要引导用户下载 。那这里就有一个问题了:网页是不知道用户有没有安装 app 的。那我们换一个思路,可不可以知道页面被置于后台了?页面进入后台,可以认为是唤起成功了;页面没进入后台,说明唤起失败(没安装 or 其他原因)。

一个新的 API 完全满足上边提到的需求 : Page Visibility API( developer.mozilla 组织网/en-US/docs/Web/API/Page_Visibility_API),文档中详细的介绍了这个 API ----> 可以准确的知道页面当前的状态(前台,后台等状态),但是这个 API 太新了,需要较新的浏览器支持,覆盖率有点低。所以我们不能大面积使用。如之奈何?交给黑科技了: 定时器

我先说一下思路:

  • setTimeout 的实现过程:浏览器尝试打开 URL scheme 并记录时间点 t1,在2秒计时后,检查当前时间 t2,如果 t2-t1 > 2200ms,说明唤起 app 成功(唤起 app 会是浏览器的定时器延后执行),如果t2-t1 < 2200ms,可能没有安装 app,可以引导用户进入下载页
  • setInterval 实现过程:原理上跟 setTimeout 相似,方法上换成设置一个比较小的时间间隔(例如 20ms),运行多次(例如 100),比较运行完 100 次的总耗时与 20*100 的时间差。逻辑判断同 setTimeout

优缺点:

  • setTimeout 不稳定,因为 Android 是基于 Linux 分时多任务的,setTimeout 的基准偏差不会那么大,比较难调教
  • setInterval 要好一点,页面一直处于前台(调起 app 失败),则100次跑完,总耗时与 100x20=2000ms 不会有太大差异,但页面在后台运行时(调起 app 成功),此时间会明显超过 2000ms
注:不知道 setTimeout,setInterval 为什么会延迟执行的,请恶补一波它们的执行原理

setTimeout

var openTime = +new Date();
window.location.href = 'wzry://videolists.show/mark/penta_kill?num=1'
var timer = setTimeout(function () {
    if ((new Date()) - openTime < 2200) {//加了200ms基准误差
        window.location.href = 'you app download page';
    }
    if ((new Date()) - openTime > 2200) {
        clearTimeout(timer);
    }
}, 2000);

setInterval

var limit_num = 100;
var openTime = +new Date();
window.location.href = 'wzry://videolists.show/mark/penta_kill?num=1'
var timer = setInterval(function () {
   if(limit_num > 0){
        limit_num--;
   }else{
        if ((new Date()) - openTime < 2200) {//加了200ms基准误差
            window.location.href = 'you app download page';
        }
        clearTimeout(timer);
   }
}, 20);

当我们完成这些操作之后,在一般环境下是可以正常唤起 app 的了

2. 那我再说一下特殊情况:微博,微信

像这种爸爸级别的应用是有 scheme 白名单的,只有白名单内的 scheme 才不会被过滤掉,就问你怕不怕?嗯?

像这种我们怎么去解决那?

(I). 其实最简单的办法就是像爸爸低头,使用应用宝。

使用它颁发给你的应用地址,向这个地址跳转,然后一切就交给爸爸了,直接无视微信什么的,直接带你飞到 app 内

(II). 使用 Universal Links

它是 iOS9 推出的一项强大的功能。可以让你 通过 http 链接的方式唤起你的 app(不管你的在微信/微博还是其他 app 内,因为 Universal Links 是由系统直接处理的),下面我来简单说一下怎么使用 Universal Links 完成唤醒的 app,你也可以通过官方文档( developer.apple 商业网/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html)详细的了解它。

首先

  • 必须给域名配置 https 才能使用它
  • 在开发者中心做配置:找到对应的 App ID ——> Associated Domains,设置成 Enabled
  • 打开工程,在 capabilities 中设置Associated Domains,在其中的 Domains 中填入你想支持的域名,注意必须以 applinks: 为前缀
  • 编辑 apple-app-site-association 文件(文件名,json 格式不能改变,注意 apple-app-site-association 文件是没有格式后缀的)
{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "TeamID + BundleId TeamID",
                "paths": [ "/mark/penta_kill?num="]
            }
        ]
    }
}
  • 上传该文件到域名的根目录,确保可以被访问

做完这些,你就可以尝试唤起你的 iOS app 了

这里还要强调一下 拦截的地址 一定要与当前 webview 的 url 不在同一个域名下。这样 Universal Links 才会生效,不要问我怎么知道的,都是血泪啊

3. 还有最后一种 ---- 自己做引导,引导用户浏览器打开,绕过限制。不过这样,步骤较多,折损率可能会升高

综上,Android app 除了使用应用宝跳转唤起和引导页没发现其他更好的办法,iOS 方案多了个 Universal Links,这也是为什么我们经常看到有些 app 在微信/微博中 iOS端可以直接唤起 app,而 Android 端经常是需要走一道应用宝的原因

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐