侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

html5唤醒APP小记

前端  /  管理员 发布于 6年前   228

最近遇到一个需求,需要在从APP分享出去的H5页面中,带有一个立即打开的按钮,如果本地安装了app,那么就直接唤起本地的app,如果没有安装,则跳转到下载。这是一个很正常的推广和导流量的策略。前端小白从来没有做过这个需求,只能开始哼唧哼唧地开启自己的度娘和谷歌之旅。

经过一段时间的探索之旅发现里面的学问很多,要做一个兼容性很好的方案,就需要考虑各种情况,在不同的情况适配不同的方案,比方说用户是在手机浏览器打开还是微信中打开,或者是在pc中打开,universal腾讯应用宝直接打开 APP link是否被关闭等,这就使代码实现变得复杂,且容易出错,且还有安卓平台机型众多、浏览器众多等导致的兼容问题。由于时间有限,这次主要先介绍一个比较普遍的使用URL Scheme进行App跳转的方法。

URL Scheme —— 唤端媒介

来源

一般来说,我们使用的智能设备上有许多我们的个人信息。比如:联系方式、银行卡/信用卡信息、支付宝/Paypal/各大商城的账户密码、照片甚至行程与位置信息等。

如果说,你设备上的每一个应用,不管是官方的还是你从任何商城安装的应用都可以随意地获取这些信息,那么你轻则收到骚扰信息和邮件、重则后果不堪设想。如何让这些信息不被其它应用随意使用,或者说,如何让这些信息仅在设备所有者本人知情并允许的情况下被使用,是所有智能设备与操作系统所要在乎的核心安全问题。针对这个问题,苹果使用了名为「沙盒」的机制:应用只能访问它声明可能访问的资源。一切提交到 App Store 的应用都必须遵守这个机制。

在安全方面沙盒是个很好的解决办法,但是有些矫枉过正。敏感的个人信息我们不愿意透露,却不代表所有的信息我们都不想与其它应用共享。因此,我们急需要一个辅助工具来帮助我们实现应用通信, URL Schemes 就是这个工具。

URL Schemes是什么

[scheme]://[host]/[path]?[query]

我们拿 https://www.baidu.com 来举例,scheme 自然就是 https 了,后面拼接的是传递的参数。URL Schemes 没有特别严格的规范,所以后面参数的具体定义是app开发者去自定义。

就像给服务器资源分配一个 URL,以便我们去访问它一样,我们同样也可以给手机APP分配一个特殊格式的 URL,用来访问这个APP或者这个APP中的某个功能(来实现通信)。APP得有一个标识,好让我们可以定位到它,它就是 URL 的 Scheme 部分。

但是,两者还有几个重要的区别:

  • 所有网页都一定有网址,不管是首页还是子页。但未必所有的应用都有自己的 URL Schemes,更不是每个应用的每个功能都有相应的 URL Schemes。几乎没有所有功能都有对应 URL 的应用。一个 App 是否支持 URL Schemes 要看那个 App 的作者是否在自己的作品里添加了 URL Schemes 相关的代码。
  • 一个网址只对应一个网页,但并非每个 URL Schemes 都只对应一款应用。这点是因为苹果没有对 URL Schemes 有不允许重复的硬性要求,所以曾经出现过有 App 使用支付宝的 URL Schemes 拦截支付帐号和密码的事件。
  •  一般网页的 URL 比较好预测,而URL Scheme 因为没有统一标准,所以非常难猜,通过猜来获取 应用的 URL Schemes 是不现实的。

前面普及了一下URL Schemes的相关知识,作为个前端开发者,就不去深究其中的原理,都交给app开发者吧。接下来开始我们的正题。首先当然是要客户端提供App的Url Schemes。

用浏览器去打开scheme

在浏览器中打开 scheme 就像打开一个不同的http地址一样。可以在一个 a 标签中打开。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>打开App</title></head><body><a href="luwei://" id="open">打开应用</a></body></html>

点击上面的H5页面中的链接将会尝试唤醒对应app,在一些浏览器中,可能会弹出一个提示框,询问用户是否允许打开应用。

如果打开的 scheme 在本地没有对应的 app,则点击不会反应。

当然还可以使用 JavaScript 代码打开,只需要添加相应的事件触发和处理即可。

在JavaScript代码中打开连接有以下几种方式:

  • 新建一个隐藏的 iframe ,地址指向需要打开的url
  • 使用 window.location 或者 window.location.href 刷新当前页面
  • 新建一个隐藏的 a 标签,地址指向打开的url,并触发打开链接事件
  • 动态创建一个script脚本,在这个脚本中新建一个a标签并打开
// 打开url的方式var urlOpen = {  // 在ios支持不好    'iframe' : function(url) {        var iframe = document.createElement('iframe');        iframe.style.display = 'none';        iframe.src = url;        document.body.appendChild(iframe);    },    'location' : function(url) {        window.location.href = url;    },    'href' : function(url) {        var a = document.createElement('a');        a.style.display = 'none';        a.href = url;        document.body.appendChild(a);        a.click();    },    'script' : function(url) {        var script = document.createElement('script');        script.setAttribute('type', 'test/javascript');        script.innerHTML = '(function(){' +'var a = document.createElement("a");' +'a.style.display = "none";' +'a.href = "' + url.replace(/"/g, '\\"') + '";' +'document.body.appendChild(a);' +'a.click();' +'})()';        document.body.appendChild(script);    },    'open' : function(url) {        window.open(url);    }};

以上方法是只是解决了在已安装App设备唤醒App的功能,并不能判断是否已安装App,没有安装即跳转至下载链接。

浏览器判断是否安装应用

在浏览器实际上是没有能力判断手机里是否安装了某个App的,所以只能够采取一种投机取巧的方式。

在JavaScript中判断页面是否进入后台来判断打开成功。Html5提供了下列事件和属性可以利用:

  • pagehide : 页面隐藏时触发
  • visibilitychange : 页面隐藏没有在当前显示时触发(切换tab也会触发该事件)
  • document.hidden : 当页面隐藏时,该值为true,显示时为false

上面这些事件或者属性并不是所有浏览器都支持。下面是一个给出为id为openBtn 的按钮添加打开scheme或者下载事件的例子,但对于Android 4.4版本以下则不支持

    var downloader,     scheme = 'luwei://',  // 需要打开的app scheme 地址    iosDownload='http://xxx.com';  // 如果打开scheme失效的app下载地址    andDownload = 'http://xxx.com';    var u = navigator.userAgent;    var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //g    var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端// 给 id 为 openBtn 的按钮添加点击事件处理函数    document.getElementById('openBtn').onclick = function () {        window.location.href = scheme;  // 尝试打开 scheme          // 设置3秒的定时下载任务,3秒之后下载app        downloader = setTimeout(function(){if(isAndroid) {    window.location.href = andDownload;}if(isIOS) {    window.location.href = iosDownload;}      }, 3000);    };     document.addEventListener('visibilitychange webkitvisibilitychange', function () {        // 如果页面隐藏,推测打开scheme成功,清除下载任务        if (document.hidden || document.webkitHidden) {clearTimeout(downloader);        }    });    window.addEventListener('pagehide', function() {        clearTimeout(downloader);    });

没有完美的方案

微信中无法唤醒App,需要“用浏览器打开”是因为微信对所有的分享链接接做了scheme屏蔽,也就是说分享连接中所有对于scheme的调用都被微信封掉了。有些app是能在微信打开是因为微信有一个白名单(有关系就是不错),对于在白名单中的分享链接是不会屏蔽掉scheme调用的。
本文只是小小地抛个砖,介绍了一种比较常用简单的方法去唤醒app,该方案兼容性不是特别好吧。要做出一个比较完美的方案还需要细细去钻研,还需要不停地去搬砖~不说了,搬砖去了~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


  • 上一条:
    Lua中string.len()使用指南
    下一条:
    ruby元编程之method_missing的一个使用细节
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客