js判斷是否安裝某個androidapp,沒有安裝下載該應用(websocket通訊,監聽視窗失去焦點事件)

bowenhuang發表於2018-10-23

現在經常有寫場景需要提示使用者下載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);
}

 

如果有哪裡寫的不對的,歡迎討論!

 


相關文章