###H5 喚醒APP功能###
? ? 最近遇到一個需求鸠按,需要在從APP分享出去的H5頁面中醒陆,帶有一個立即打開的按鈕宅广,如果本地安裝了app葫掉,那么就直接喚起本地的app,如果沒有安裝跟狱,則跳轉(zhuǎn)到下載俭厚。這是一個很正常的推廣和導(dǎo)流量的策略椭坚。前端小白從來沒有做過這個需求赁项,只能開始哼唧哼唧地開啟自己的度娘和谷歌之旅。
? ? 經(jīng)過一段時間的探索之旅發(fā)現(xiàn)里面的學(xué)問很多罢浇,要做一個兼容性很好的方案关翎,就需要考慮各種情況扛门,在不同的情況適配不同的方案,比方說用戶是在手機瀏覽器打開還是微信中打開纵寝,或者是在pc中打開论寨,universal騰訊應(yīng)用寶直接打開 APP link是否被關(guān)閉等,這就使代碼實現(xiàn)變得復(fù)雜,且容易出錯葬凳,且還有安卓平臺機型眾多绰垂、瀏覽器眾多等導(dǎo)致的兼容問題。由于時間有限火焰,這次主要先介紹一個比較普遍的使用URL Scheme進行App跳轉(zhuǎn)的方法劲装。
###URL Scheme —— 喚端媒介###
來源
? ? 一般來說,我們使用的智能設(shè)備上有許多我們的個人信息荐健。比如:聯(lián)系方式、銀行卡/信用卡信息琳袄、支付寶/Paypal/各大商城的賬戶密碼江场、照片甚至行程與位置信息等。
? ? 如果說窖逗,你設(shè)備上的每一個應(yīng)用址否,不管是官方的還是你從任何商城安裝的應(yīng)用都可以隨意地獲取這些信息,那么你輕則收到騷擾信息和郵件碎紊、重則后果不堪設(shè)想佑附。如何讓這些信息不被其它應(yīng)用隨意使用,或者說仗考,如何讓這些信息僅在設(shè)備所有者本人知情并允許的情況下被使用音同,是所有智能設(shè)備與操作系統(tǒng)所要在乎的核心安全問題。針對這個問題秃嗜,蘋果使用了名為「沙盒」的機制:應(yīng)用只能訪問它聲明可能訪問的資源权均。一切提交到 App Store 的應(yīng)用都必須遵守這個機制。
? ? 在安全方面沙盒是個很好的解決辦法锅锨,但是有些矯枉過正叽赊。敏感的個人信息我們不愿意透露,卻不代表所有的信息我們都不想與其它應(yīng)用共享必搞。因此必指,我們急需要一個輔助工具來幫助我們實現(xiàn)應(yīng)用通信, URL Schemes 就是這個工具恕洲。
###URL Schemes是什么###
[scheme]://[host]/[path]?[query]
? ? 我們拿 https://www.baidu.com 來舉例塔橡,scheme 自然就是 https 了,后面拼接的是傳遞的參數(shù)霜第。URL Schemes 沒有特別嚴格的規(guī)范谱邪,所以后面參數(shù)的具體定義是app開發(fā)者去自定義。
? ? 就像給服務(wù)器資源分配一個 URL庶诡,以便我們?nèi)ピL問它一樣惦银,我們同樣也可以給手機APP分配一個特殊格式的 URL,用來訪問這個APP或者這個APP中的某個功能(來實現(xiàn)通信)。APP得有一個標識扯俱,好讓我們可以定位到它书蚪,它就是 URL 的 Scheme 部分。
但是迅栅,兩者還有幾個重要的區(qū)別:
? ? 所有網(wǎng)頁都一定有網(wǎng)址殊校,不管是首頁還是子頁。但未必所有的應(yīng)用都有自己的 URL Schemes读存,更不是每個應(yīng)用的每個功能都有相應(yīng)的 URL Schemes为流。幾乎沒有所有功能都有對應(yīng) URL 的應(yīng)用。一個 App 是否支持 URL Schemes 要看那個 App 的作者是否在自己的作品里添加了 URL Schemes 相關(guān)的代碼让簿。
? ? 一個網(wǎng)址只對應(yīng)一個網(wǎng)頁敬察,但并非每個 URL Schemes 都只對應(yīng)一款應(yīng)用。這點是因為蘋果沒有對 URL Schemes 有不允許重復(fù)的硬性要求尔当,所以曾經(jīng)出現(xiàn)過有 App 使用支付寶的 URL Schemes 攔截支付帳號和密碼的事件莲祸。
? ? 一般網(wǎng)頁的 URL 比較好預(yù)測,而URL Scheme 因為沒有統(tǒng)一標準椭迎,所以非常難猜锐帜,通過猜來獲取 應(yīng)用的 URL Schemes 是不現(xiàn)實的。
前面普及了一下URL Schemes的相關(guān)知識畜号,作為個前端開發(fā)者缴阎,就不去深究其中的原理,都交給app開發(fā)者吧简软。接下來開始我們的正題药蜻。首先當(dāng)然是要客戶端提供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">
打開應(yīng)用
</a>
</body>
</html>
? ? 點擊上面的H5頁面中的鏈接將會嘗試喚醒對應(yīng)app视卢,在一些瀏覽器中踱卵,可能會彈出一個提示框,詢問用戶是否允許打開應(yīng)用据过。
? ? 如果打開的 scheme 在本地沒有對應(yīng)的 app惋砂,則點擊不會反應(yīng)。
? ? 當(dāng)然還可以使用 JavaScript 代碼打開绳锅,只需要添加相應(yīng)的事件觸發(fā)和處理即可西饵。
在JavaScript代碼中打開連接有以下幾種方式:
? ? 新建一個隱藏的 iframe ,地址指向需要打開的url鳞芙。
? ? 使用 window.location 或者window.location.href 刷新當(dāng)前頁面眷柔。
? ? 新建一個隱藏的 a 標簽期虾,地址指向打開的url,并觸發(fā)打開鏈接事件驯嘱。
? ? 動態(tài)創(chuàng)建一個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設(shè)備喚醒App的功能鞠评,并不能判斷是否已安裝App茂蚓,沒有安裝即跳轉(zhuǎn)至下載鏈接。
###瀏覽器判斷是否安裝應(yīng)用###
? ? 在瀏覽器實際上是沒有能力判斷手機里是否安裝了某個App的剃幌,所以只能夠采取一種投機取巧的方式聋涨。
? ? 在JavaScript中判斷頁面是否進入后臺來判斷打開成功。Html5提供了下列事件和屬性可以利用:
? ? pagehide : 頁面隱藏時觸發(fā)
? ? visibilitychange : 頁面隱藏沒有在當(dāng)前顯示時觸發(fā)(切換tab也會觸發(fā)該事件)
? ? document.hidden : 當(dāng)頁面隱藏時负乡,該值為true牍白,顯示時為false
? ? 上面這些事件或者屬性并不是所有瀏覽器都支持。下面是一個給出為id為openBtn 的按鈕添加打開scheme或者下載事件的例子敬鬓,但對于Android 4.4版本以下則不支持
? ? vardownloader,
? ? 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 的按鈕添加點擊事件處理函數(shù)
? ? document.getElementById('openBtn').onclick = function () {
? ? window.location.href = scheme; // 嘗試打開 scheme
// 設(shè)置3秒的定時下載任務(wù)淹朋,3秒之后下載app
? ? downloader = setTimeout(function() {
? ? ? ? if(isAndroid) {
? ? ? ? ? window.location.href =andDownload;? ? ? ? ? }
? ? ? if(isIOS) {
? ? ? ? ? window.location.href =iosDownload;?
? ? ? }
}, 3000);
? ?
};
document.addEventListener('visibilitychange webkitvisibilitychange, function() {
// 如果頁面隱藏笙各,推測打開scheme成功钉答,清除下載任務(wù)
if(document.hidden || document.webkitHidden) {
clearTimeout(downloader);
}
});
window.addEventListener('pagehide', function(){
? ? ? ? clearTimeout(downloader);
});
###沒有完美的方案###
? ? 微信中無法喚醒App,需要“用瀏覽器打開”是因為微信對所有的分享鏈接接做了scheme屏蔽杈抢,也就是說分享連接中所有對于scheme的調(diào)用都被微信封掉了数尿。有些app是能在微信打開是因為微信有一個白名單(有關(guān)系就是不錯),對于在白名單中的分享鏈接是不會屏蔽掉scheme調(diào)用的惶楼。
? ? 本文只是小小地拋個磚右蹦,介紹了一種比較常用簡單的方法去喚醒app,該方案兼容性不是特別好吧歼捐。要做出一個比較完美的方案還需要細細去鉆研何陆,還需要不停地去搬磚~不說了,搬磚去了~