現在各類app,分享出去的H5頁面中,一般都會帶着一個立即打開的按鈕,如果本地安裝了app,那么就直接喚起本地的app,如果沒有安裝,則跳轉到下載。這是一個很正常的推廣和導流量的策略,最近產品經理就提出了這樣的一個需求,做一個像今日頭條功能一樣的帶打開app的下載條。
實現這個功能,我們需要解決兩個問題
1、js如何喚起本地app
2、js如何知道手機已經安裝了對應的應用
js如何喚起本地app
既然是通過網頁調用app,這個當然涉及到與app的通信。通過咨詢ios和android的同事,ios與android都支持一種叫做schema協議的鏈接。這種協議的類似於我們熟悉的http協議,我們只要跟app協商好協議頭,app通過攔截到這個協議頭的請求就可以知道有網頁要求調用。而對於js來說,我們這要像a標簽的href一樣來激活這個協議的鏈接就行了。
比如:
<a href="myapp://">調起app</a>
這種方式ios和android都可以共用
2、如何知道手機已經安裝的對應的應用對於這個功能的實現,首先想到的是查詢應用是否存在,但是這種方法顯而易見是行不通的,比如說你在UC瀏覽器,微信中,我們無法主動的去查詢我們系統中是否安裝了該應用。所以這個判斷是無法實現。所以我們就需要采用曲線救國的方式來實現。既然我們可以喚起app,那我們就可以忽略判斷,直接喚起app,如果用戶沒有安裝,我們做一個容錯處理。
結合這個思路,我們基本可以得到我們的實現方案
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)
寫完代碼,做了測試,發現這樣的實現有很多問題
1、微信無法調起。微信對於鏈接的跳轉限制很嚴重,很多下載外鏈都引導到瀏覽器打開
2、調起app返回瀏覽器的時候,會跳轉到下載頁面,既然用戶已經下載了app,再讓頁面跳轉到下載頁很不友好
3、ios9+的safari無法通過iframe跳轉到其他頁面
有問題就需要解決
1、對於微信或者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、針對問題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、對於問題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無法通過微下載打開的問題
最后再來整理一下我們的思路
1、ios通過Universal links,針對ios9一下和以前版本沒有實現Universal links,在綁定好的域名下做一個中間頁,直接跳轉到中間頁
2、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); })