如今各種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); })