zoukankan      html  css  js  c++  java
  • 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其成功呢,当一个应用被调用的时候,浏览器会被隐藏,那么当前页面会失去焦点。

    这种情况适用于国外使用chrome和uc browser的环境,国内手机浏览器百花齐放,各类厂商对deeplink都有不同的处理方式,所以兼容性不好。

    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);
    }

    如果有哪里写的不对的,欢迎讨论!

  • 相关阅读:
    Spring事务的那些坑,这里都给你总结好了!
    8 种方案解决重复提交问题!你选择哪一种呀?
    一张900w的数据表,16s执行的SQL优化到300ms?
    这 5 个开源的能挣钱的 SpringBoot 项目,真TMD香!
    邮箱mail 发送类 ASP.NET C#
    ValidationSugar表单验证框架-支持ASP.NET MVC ASP.NET WebFroM
    Jquery几个比较实用,但又让很多人忽略的几个函数
    ASP.NET MVC和WebForm 轻松实现前端和后端的双重验证 jquery.validate+ValidationSugar
    让 ASP.NET JS验证和服务端的 双验证 更简单
    ASP.NETC#通用扩展函数之TypeParse 类型转换方便多了
  • 原文地址:https://www.cnblogs.com/huangbx/p/js-call-app-judge-install.html
Copyright © 2011-2022 走看看