這是一篇自己寫的舊文,首發於: 原文連結,略有修改。
背景
在H5頁面或者app的webview中調起第三方app
核心
調起app是作業系統(iOS、Android)的機制,在h5頁面,我們可以做的不多。
在調起之前,h5頁面無法判斷當前手機是否安裝了對應的app,我們只能去嘗試調起,並且用一些方法來處理沒有調起的情況。
調起的原理就不介紹了,網上一搜一大堆。直接上核心程式碼。
if(iOS9) {
window.location.href = ${universalLink};
}
else {
var ifr = document.createElement('iframe');
ifr.src = ${scheme};
ifr.style.display = 'none';
document.body.appendChild(ifr);
window.setTimeout(function () {
document.body.removeChild(ifr);
}, 300);
}
舉個栗子:
${universalLink} = 'http://myapp.com'
${scheme} = 'myapp://index'
複製程式碼
解釋一下上面的程式碼,如果是iOS9及以上的iOS系統,直接跳轉到調起app的universal link。如果是安卓或者iOS9一下的iOS系統,就新建一個iframe,把這個iframe的src弄成調起app的scheme,然後把這個iframe直接塞到頁面的DOM樹上,然後『聽天由命』就行。
iOS的調起
iOS是使用universalLink(下面簡稱ulink)的方式來進行調起。具體系統內部的機制就不說了,網上一堆文章,隨便搜一下就行。
universalLink其實就是一個正常的http請求的url。我們在h5頁面使用 location.href=XX進行調起的時候,如果說調起成功了,那麼其實這個url是不會被訪問的,抓包也抓不到。換句話說,如果我們訪問到這個url了,說明我們的調起失敗了。
iOS如何實現【安裝了調起,沒有安裝跳下載頁】
上面說了,iOS下調起失敗後,會訪問到一個url。要實現沒有安轉跳下載頁,那麼就直接把ulink對應的連結做成下載頁就好了。根據需求,我們還可以將ulink對應的url做成任何頁面。但是,如果我們不想要跳轉到這個頁面,還是想停留在之前的頁面呢?很簡單,叫RD哥哥在通鏈那個url的服務端加一個302重定向服務就行。
舉個栗子,我們使用下面的ulink來調起App。
http://myapp.com/index?target=encodeURIComponent('http://www.baidu.com');
調起失敗後,上面那個ulink會被瀏覽器訪問到,我們在服務端加了重定向服務,我們最終會訪問到target對應的地址,即 www.baidu.com 。這樣,我們就實現了【調起失敗時,跳轉到自己想要的頁面】。
iOS如何實現【安裝了調起,沒有安裝時,在當前頁面繼續進行其他操作】
兩種方法:
一、需要後端重定向服務,我們只需要把上面重定向的連結換成一個scheme就行了。這種方法適用於頁面必須要使用者點選才能觸發的互動,比如視訊、音訊的播放等。(另:微信下可以通過監聽jsbridge ready的事件,自動播放視訊、音訊)
這個scheme需要滿足以下的要求:
- 可以被當前瀏覽器識別
- 瀏覽器識別了這個scheme,但是不會進行任何其他操作。
如果這個scheme同時滿足了上述兩個條件,那麼體驗就是最好的。否則,可能就會出現瀏覽器彈框等問題。
舉幾個scheme的例子
...
facetime:// (iOS11以下體驗完美,之後的版本會直接拉起facetime--)
ucbrowser://
...
複製程式碼
二、需要後端重定向服務,我們需要把重定向連結換成【當前連結後加一個特殊引數】的連結。這樣在前端程式碼裡就可以判斷url裡面的特殊引數,從而得知當前頁面是拉起app失敗時進入的。
iOS調起的注意事項
- 2018年初,iOS微信下全面封禁了universalLink,所以在微信下是調不起app的,暫時是沒有什麼辦法。這種時候,一般可以提示使用者,從瀏覽器開啟。當然,也可以找微信開白名單,直接用微信的能力去拉起。
- 其實iOS下用scheme也是可以調起的,比如 window.location.href = scheme 但是這樣有個問題,如果說沒有安裝對應的app,在safari下會彈窗:無法識別該連結,並且就算安裝了該app,也會彈一個窗讓你確認是否調起 。
- 雖說iOS的通鏈是一個url,但是也不是直接貼上到safari等瀏覽器下訪問就能直接調起app。因為iOS的通鏈調起必須要求有使用者操作,比如點選等行為。可以將連結貼上到iOS的備忘錄上,點選這個連結就可以直接調起了。
Android的調起
安卓的調起是用iframe的方式(其實現在的高版本安卓也可以直接window.location.href=scheme)。
安卓調起的最大的特點就是,安卓無法知道是否成功調起了app。安卓下的調起一般都會有自帶的兜底策略,比如下載。程式碼也很簡單
var ifr = document.createElement('iframe');
ifr.src = ${scheme};
ifr.style.display = 'none';
document.body.appendChild(ifr);
window.setTimeout(function () {
document.body.removeChild(ifr);
// 這裡寫兜底策略的邏輯,比如下載。
// 當然,也可以不加任何的兜底策略,調不起就算了。
window.location.href = ${下載地址}
}, 300);
複製程式碼
如果想要實現【安裝了app調起,沒有安裝app下載】的功能,那麼肯定會調起和下載的邏輯同時執行,因為安卓無法知道是否成功調起app。
安卓的調起是很靈活的,你可以任意控制兜底策略的邏輯,想幹嘛幹嘛。只是說,兜底策略是幾乎一定會執行的,不管你調起成功還是失敗。
Android調起注意事項
###各種瀏覽器的遮蔽
很多瀏覽器都對scheme做了遮蔽。所以安卓下調不起app是一件十分正常的事情。
微信下調起
微信太封閉了,自然遮蔽了非自家app的調起。只新建一個iframe的方式在微信下是不能調起的。微信針對webview調起app的策略也一直在修改。最新(2018年3月19日)的想要在微信的webview下調起app的方式是:
- 手機上必須安裝應用寶
- 使用下面的方式,跳轉到應用寶頁面進行調起。
window.location.href = 'http://a.app.qq.com/o/simple.jsp?pkgname=${pkgname}&android_scheme= encodeURIComponent(${scheme})'
${pkgname}表示app的包名,比如 'com.myapp',${scheme}表示調起的scheme
複製程式碼
安卓下判斷是否調起成功
其實有一種方法可以判斷安卓下是否調起成功。執行調起邏輯後,設一定的延時判斷當前頁面是否可見,若不可見了,幾乎就可以確定是調起成功了。但是隻對小部分瀏覽器有效(比如安卓下的chrome)。對大多數瀏覽器而言,調起成功後,會有一個彈框,需要使用者點選確定後,才能喚起app。由於這個彈框的存在,就無法通過頁面是否可見的方法來判斷調起成功與否了。而chrome下,調起成功直接喚起app,是不會彈窗的,所以chrome下可以用延時+頁面是否可見的方式來判斷調起成功與否。