js判断是否安装某个android app,没有安装下载该应用(websocket通信,监听窗口失去焦点事件)
现在经常有写场景需要提示用户下载app, 但是如果用户已经安装,我们希望是直接打开app。
实际上,js是没有判断app是否已经安装的方法的,我们只能曲线救国。
首先,我们需要有call起app的schema, 以及一个下载地址,比如:
var schema = 'myApp://main'; var downUrl = 'https://yourmain.com/downloadUrlTag';
一、使用websocket通信实现页端和app的通信
1. android app需要实现websocket的连接功能,开放一个特定的端口如8899;
2. 页端js建立websocket连接
1 var download = function (schema, downUrl) { 2 var ws = "ws://localhost:8899/websocket"; 3 4 function onMessage(event) { 5 if (event.data != 'SUCCESS') { 6 console.log(event.data + "!= 'SUCCESS'"); 7 window.location.href = downUrl; 8 } 9 socket.close(); 10 } 11 12 function onError(event) { 13 console.log("websocket error"); 14 window.location.href = downUrl; 15 } 16 17 function onOpen() { 18 } 19 20 function onClose() { 21 } 22 // 判断浏览器 23 if (navigator.userAgent.match(/android/i) && (navigator.userAgent.match(/Chrome/) || navigator.userAgent.match(/Opera/))) { 24 if (window.WebSocket) { 25 try { 26 socket = new WebSocket(ws);
27 } catch (ex) { 28 window.location.href = downUrl; 29 } 30 var message = ""; 31 socket.onmessage = onMessage; 32 socket.onopen = onOpen; 33 socket.onclose = onClose; 34 socket.onerror = onError; 35 36 if (socket.readyState == WebSocket.CONNECTING) { 37 setTimeout(function () { // websocket建立连接需要一段时间 38 if (socket.readyState == WebSocket.OPEN) { 39 if (schema != '') { 40 window.location.href = schema; 41 socket.send(message); 42 } 43 } else { 44 socket = new WebSocket(ws);
45 if (socket.readyState != WebSocket.OPEN) { 46 window.location.href = downUrl; 47 } 48 } 49 }, 1000); 50 } 51 } 52 } else { 53 window.location.href = downUrl; 54 } 55 };
当点击下载按钮的时候,调用download(schema,downUrl)方法即可。
但是这种方法存在一个严重的问题:当app不在进程中存活时,我们是无法成功call起的,这样,我们就需要在客户端做一些工作,让你的app一直存活在进程中。
二、监听当前页面是否失去焦点,来判断是否需要调用下载
首先,我们的想法是,当用户点击下载后,先尝试call起APP,使用setTimeout做延时处理,在延时中判断是否call起成功,如果不成功,则直接下载,我们如何认为call其成功呢,当一个应用被调用的时候,浏览器会被隐藏,那么当前页面会失去焦点。
首先,我们的想法是,当用户点击下载后,先尝试call起APP,使用setTimeout做延时处理,在延时中判断是否call起成功,如果不成功,则直接下载,我们如何认为call其成功呢,当一个应用被调用的时候,浏览器会被隐藏,那么当前页面会失去焦点。
var isBlur = false; location.href = schema; setTimeout(function() { if (!isBlur) { location.href = url; } }, 1000);
那么如何来设置isBlur的值呢,这里提供两种方法:
1. 监听window的blur事件
// window 每次失去焦点 window.onblur = function() { console.log('失去焦点'); isBlur = true; }; // window 每次获得焦点 // window.onfocus = function() { // console.log('获得焦点'); // isBlur = false; // }
2. 自定义事件监听visibilityChange事件,来判断document的hidden属性,
简单写法:
document.addEventListener("visibilitychange", function(){ console.log(document.hidden ? "失去焦点" : "获得焦点"); isBlur = document.hidden; });
兼容写法:
var hiddenProperty = 'hidden' in document ? 'hidden' : 'webkitHidden' in document ? 'webkitHidden' : 'mozHidden' in document ? 'mozHidden' : null; var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange'); var onVisibilityChange = function(){ if (!document[hiddenProperty]) { console.log('获得焦点'); isBlur = false; } else { console.log('失去焦点'); isBlur = true; } } document.addEventListener(visibilityChangeEvent, onVisibilityChange);
完整代码:
var download = function() { var isBlur = false; location.href = schema; setTimeout(function() { if (!isBlur) { location.href = url; } }, 1000); // window 每次失去焦点 window.onblur = function() { console.log('失去焦点'); isBlur = true; }; var hiddenProperty = 'hidden' in document ? 'hidden' : 'webkitHidden' in document ? 'webkitHidden' : 'mozHidden' in document ? 'mozHidden' : null; var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange'); var onVisibilityChange = function(){ if (document[hiddenProperty]) { console.log('失去焦点'); isBlur = true; } } document.addEventListener(visibilityChangeEvent, onVisibilityChange); }
如果有哪里写的不对的,欢迎讨论!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
WPF 3D编程介绍
原文: WPF 3D编程介绍 上一篇文章简单的介绍了WPF编程的相关的内容,也推荐了本书。今天要来讲一下在WPF如何开展3D编程。 使用的xmal和C#开发的时候:需要使用如下的关键要素: 1:摄像机,是用来模拟成像的,现在WPF支持正交(orthographical)和透视(perspective)摄像机。你需要确定它的位置(position),镜头正对的方向(LookDirection),还有就是摄像机的向上方向(UpDirection),如果不是很明白这个属性,可以参考http://topic.csdn.net/u/20090214/23/f8201d15-be5c-483d-ac97-c0a33151e8fb.html。 2:3D模型:一个3D模型定义了场景中的一个物体,包含一个Geometry对象。Geometry对象是一个网格,和一个材质(Material)对象,材质具有漫反射(diffuse),镜面(specular)或放射(emmisive)几种类型,材质本身具有一个画刷。如果想对材质进一步的了解,可以看:http://app.cnzer.cn/html-85837-1...
- 下一篇
Android 动画初探
前言: 好久没来写文章了,一方面是因为自己懒了,另外一个是因为最近工作比较忙,没有闲时间(其实主要还是因为懒)。话说八月多换了一个新工作,在之前的公司,主要是横向发展,了解了很多技术。在现在的公司主要是纵向发展,更加深入的探索。之前是广而不精,没有深入学习。在现在的公司呢,能够更加深入的学习技术。就拿最近的工作来说吧,动画很多,刚开始只是知道Android动画分为属性动画、帧动画和补间动画。但是,他们之间有什么具体的区别就不是特别清楚了。尤其是属性动画和补间动画的区别,我能说自己被补间动画坑惨了吗?(其实,还是自己学艺不精,需要继续努力了。)好了,废话说多了,还是来看看今天的文章吧。 首先 要学习Android动画,我们以一个例子来深入学习,毕竟都是要把功能实现出来,写一些大而空没有实用性的东西,不但是敷衍别人,更是对自己的不负责任。如下图所示:(原谅我自恋一下,放了自己的图像照) Screenshot_20181023-200259.png Screenshot_20181023-200103.png 分析 1、要实现从大图到小图的过度,我们需要怎么实现呢?又需要用哪些技术呢?首先图...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Mario游戏-低调大师作品
- 2048小游戏-低调大师作品
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- Red5直播服务器,属于Java语言的直播服务器