H5頁面中喚起native app

如今各種app,分享出去的H5頁面中,通常都會帶着一個當即打開的按鈕,若是本地安裝了app,那麼就直接喚起本地的app,若是沒有安裝,則跳轉到下載。這是一個很正常的推廣和導流量的策略,最近產品經理就提出了這樣的一個需求,作一個像今日頭條功能同樣的帶打開app的下載條。javascript

實現這個功能,咱們須要解決兩個問題
一、js如何喚起本地app
二、js如何知道手機已經安裝了對應的應用php

js如何喚起本地appcss

既然是經過網頁調用app,這個固然涉及到與app的通訊。經過諮詢ios和android的同事,ios與android都支持一種叫作schema協議的連接。這種協議的相似於咱們熟悉的http協議,咱們只要跟app協商好協議頭,app經過攔截到這個協議頭的請求就能夠知道有網頁要求調用。而對於js來講,咱們這要像a標籤的href同樣來激活這個協議的連接就好了。html

好比:java

<a href="myapp://">調起app</a>


這種方式ios和android均可以共用android

二、如何知道手機已經安裝的對應的應用對於這個功能的實現,首先想到的是查詢應用是否存在,可是這種方法顯而易見是行不通的,好比說你在UC瀏覽器,微信中,咱們沒法主動的去查詢咱們系統中是否安裝了該應用。因此這個判斷是沒法實現。因此咱們就須要採用曲線救國的方式來實現。既然咱們能夠喚起app,那咱們就能夠忽略判斷,直接喚起app,若是用戶沒有安裝,咱們作一個容錯處理。ios

結合這個思路,咱們基本能夠獲得咱們的實現方案
web

var iframe = document.createElement('iframe');
var body = document.body;
iframe.style.display = "none";
ar timer = null;

var openapp = document.getElementById('openapp');
openapp.addEventListener('click', function() {
body.appendChild(iframe);
iframe.src = "appschema://";
timer = setTimeout(function() {
wondow.location.href = "download.html"; //容錯的下載頁面
}, 500);
}, false)

寫完代碼,作了測試,發現這樣的實現有不少問題
一、微信沒法調起。微信對於連接的跳轉限制很嚴重,不少下載外鏈都引導到瀏覽器打開
二、調起app返回瀏覽器的時候,會跳轉到下載頁面,既然用戶已經下載了app,再讓頁面跳轉到下載頁很不友好
三、ios9+的safari沒法經過iframe跳轉到其餘頁面瀏覽器

有問題就須要解決微信

一、對於微信或者QQ空間,在網上查找資料,若是是在應用寶上線的應用,應用寶提供了微下載來實現微信和QQ打開app,先跳轉到應用寶的的下載連接,而後下載寶連接會判斷打開對應的app,具體參考(http://wiki.open.qq.com/index.php?title=mobile/%E5%BA%94%E7%94%A8%E5%AE%9D%E5%BE%AE%E4%B8%8B%E8%BD%BD)可是應用寶的微下載有個問題,ios微信和QQ中沒法打開對應的應用,只是會經過你應用寶配置的appstore下載連接跳轉到對應的下載頁面,再從appstore裏面打開應用。因此這個問題仍是不能徹底解決,只能完美解決android的機器

二、針對問題2,網上有人經過監控頁面的pagehide和visibilitychange方法來實現禁止跳轉,具體的實現思路是監控頁面是否隱藏,利用延時若是頁面已經打開app,此時頁面會是隱藏狀態,觸發頁面的隱藏事件,clear延時事件,禁止跳轉,不過這個方案會出現問題,有一些瀏覽器在app打開,離開瀏覽器以後,js事件不在執行,也就是此時沒法監控的頁面的隱藏,在返回頁面的時候,js繼續執行,可是事件監控的仍是頁面展現的狀態,沒法clear延時事件,因此該方式沒法完美解決這個問題

後來找到了另外的解決方案,調起app須要喚起另外的進程,因此js的進程會掛起,致使先後有一個時間差,記錄先後的事件差對比就能夠判斷是否調起了app了

iframe.src = "appschema://";
var timer = null,
t = Date.now();
timer = setTimeout(function() {
if (Date.now() - t > 1200) {
clearTimeout(timer);
return false;
}
}, 1000);

三、對於問題3,Apple爲iOS 9發佈了一個所謂的通用連接的深層連接特性,即Universal links。只要在app中受權好域名,在網頁中只要打開對應域名連接,都會檢測與域名綁定的app是否存在,若是存在,直接調起app,具體參考(http://stackoverflow.com/questions/31891777/ios-9-safari-iframe-src-with-custom-url-scheme-not-working),而且該方法不會被微信攔截,能夠在微信中使用,這樣也就解決了咱們在騰訊平臺下ios沒法經過微下載打開的問題

最後再來整理一下咱們的思路
一、ios經過Universal links,針對ios9一下和之前版本沒有實現Universal links,在綁定好的域名下作一箇中間頁,直接跳轉到中間頁
二、android分平臺,若是是微信或者QQ(能夠經過用戶代理檢測),直接經過微下載,其餘瀏覽器,直接用schema協議

具體代碼實現以下

var url = {
        open: 'duchuang://',
        down: 'http://a.app.qq.com/o/simple.jsp?pkgname=com.nayun.framework'
    },
    iframe = document.createElement('iframe');
iframe.style.cssText = 'display:none;width=0;height=0';
var timer = null,
    //點擊第三方下載
    isAndroid = !!navigator.userAgent.match(/android/ig),
    isIos = !!navigator.userAgent.match(/iphone|ipod/ig),
    isIpad = !!navigator.userAgent.match(/ipad/ig),
    isWeixin = (/MicroMessenger/ig).test(navigator.userAgent),
    isQQ = (/qq/ig).test(navigator.userAgent),
    openapp = document.getElementById('cal-app');
openapp.addEventListener('click', function() {
    if (isIos) {
        window.location.href = "https://appdetail.netwin.cn/download.html"
    }

    if (isAndroid) {
        if (isWeixin || isQQ) { //andorid微信和QQ走微下載
            window.location.href = 'http://a.app.qq.com/o/simple.jsp?pkgname=com.nayun.framework&android_schema=' +  url;
        } else {
            body.appendChild(iframe);
            iframe.src = url.open;
            var t = Date.now();
            timer = setTimeout(function() {
                if (Date.now() - t > 1200) {
                    clearTimeout(timer);
                    return false;
                }
                if (document.webkitHidden || document.hidden) {
                    return false;
                }
                window.location.href = 'http://a.app.qq.com/o/simple.jsp?pkgname=com.nayun.framework';
            }, 1000);
        }
    }
}, false)


document.addEventListener("webkitvisibilitychange", function() {
    var tag = document.hidden || document.webkitHidden;
    if (tag) {
        clearTimeout(timer);
    }
});


window.addEventListener('pagehide', function() {
    clearTimeout(timer);
})
相關文章
相關標籤/搜索