iOS/Android 瀏覽器(h5)及微信中喚起本地APP


在移動互聯網,鏈接是比較重要的傳播媒質,但很多時候我們又希望用戶能夠回到APP中,這就要求APP可以通過瀏覽器或在微信中被方便地喚起。

這是一個既直觀又很好的用戶體驗,但在實現過程中會遇到各種問題:

  1. 如何解決未安裝APP時的做好引導頁
  2. 如何在微信中喚醒APP
  3. 在iOS9中如何處理universal link被用戶誤關的情況
  4. 如何解決Android各種機型、各種第三方瀏覽器導致的兼容問題等
  5. 在APP未安裝情況下,引導用戶下載后打開APP后,如何進入之前喚起時指定的頁面或內容,即如何實現場景還原
  6. 在微信中喚醒APP時,如何進入指定的頁面或內容

下面是我一些個人的經驗分享。

瀏覽器中打開

iOS/Android APP配置

這塊內容其實比較簡單,在網上都有很多資料可供查閱,就不再贅述。

原理說明

首先需要說明,不管iOS還是Android,瀏覽器都不可能預知本地是否安裝了某個APP的。或者更嚴謹地說,我們不能通過瀏覽器來預知本地是否安裝。因為就算瀏覽器可以讀取本地應用的安裝列表,但是目前也沒任何一家瀏覽器提供查詢的API,所以這條路是走不通的。

本質上瀏覽器是通過URL scheme打開APP,一個APP可以設置一個或多個打開自己的URL scheme。比如,Twitter就注冊自己能被「twitter://」打開。

其實,如果是做APP間相互跳轉是比較簡單的。iOS就可以使用 UIApplication 的 canOpenUrl 方法來檢測URL scheme 是否能打開對應的APP。比如,如果「twitter://」檢測能被打開,也就說明本地安裝了 Twitter 。再用 UIApplication 的 openURL 方法,就能打開Twitter了。Android 中的做法類似。

實現方案

因為iOS9和之前的iOS系統有區別,所以這里我們也要區別對待。

iOS7/iOS8

iOS中默認通過Safari打開URL scheme,方法一般如下兩種:

  1. 直跳方式:點擊鏈接、修改 window.location 等。
  2. iframe 方式:在 body 上添加 iframe,設置src屬性為跳轉的URL scheme。

第一種情況:

<a href="schemeUrl">喚醒你的APP</a>

或者

window.location.href = schemeUrl;

但在第一種情況,如果APP喚醒失敗,或者APP未安裝的話,很多時候都會跳到錯誤頁,這很影響用戶體驗,而我們的要求可能是跳轉到其他頁面或者下載APP。

后一種方法不會引起頁面可見的變化(例如頁面內容變成一個新頁面),不會導致瀏覽器歷史記錄的變化,大致實現如下:

<a href="APP下載地址">下載或打開APP</a> <script> $('a').click(function() {  var ifr = document.createElement('iframe');  ifr.src = '自定義 URL scheme';  ifr.style.display = 'none';  document.body.appendChild(ifr);  setTimeout(function(){  document.body.removeChild(ifr);  }, 3000); }); </script>

過程是這樣:點擊 a 標簽時,首先會嘗試打開URL scheme,如果成功,就喚起APP;如果失敗,則跳轉到 href 屬性,即下載頁。

Android

但這個方案在很多安卓機型上有問題,為保證可用,改用第一種方案:

$('a').click(function() { location.href = '自定義 URL scheme'; t = Date.now(); setTimeout(function(){ if (Date.now() - t < 1200) { location.href = 'Android 下載地址'; } }, 1000); return false; }

理想過程是這樣:瀏覽器嘗試打開 URL scheme,在1秒計時后,檢查當前時間,如果實際時間已過 1200 毫秒,說明喚起APP 成功(喚起 APP 會讓瀏覽器的定時器變慢);如果沒超過 1200 毫秒,很可能是沒有安裝應用,就跳到下載地址。

或者換種方式:

var ifr = document.createElement('iframe'); ifr.src = 'com.baidu.tieba://'; ifr.style.display = 'none'; document.body.appendChild(ifr); var openTime = +new Date(); window.setTimeout(function(){ document.body.removeChild(ifr); if( (+new Date()) - openTime > 2500 ){ window.location = 'http://exam.com/xxxx.apk'; } },2000)

但原理都是一樣,利用setTimeout。但這其實不穩定,因為Android是基於Linux的分時多任務的,setTimeout的基准偏差可能會沒那么大。

但如果設置比較小的運行間隔(<30ms),在瀏覽器或者webview中,應用切換到后台,setInterval會被很明顯的延遲執行,比如設置一個運行間隔20ms,總計運行100次的定時器,如果頁面一直處於前台,則100次跑完,總耗時與 100x20=2000ms不會有太大差異,但頁面在后台運行時,此時間會明顯超過2000ms。可以利用這一點來實現是否成功打開APP檢測及回調。

function openApp(openUrl, appUrl, action, callback) { //檢查app是否打開 function checkOpen(cb){ var _clickTime = +(new Date()); function check(elsTime) { if ( elsTime > 3000 || document.hidden || document.webkitHidden) { cb(1); } else { cb(0); } } //啟動間隔20ms運行的定時器,並檢測累計消耗時間是否超過3000ms,超過則結束 var _count = 0, intHandle; intHandle = setInterval(function(){ _count++; var elsTime = +(new Date()) - _clickTime; if (_count>=100 || elsTime > 3000 ) { clearInterval(intHandle); check(elsTime); } }, 20); } //在iframe 中打開APP var ifr = document.createElement('iframe'); ifr.src = openUrl; ifr.style.display = 'none'; if (callback) { checkOpen(function(opened){ callback && callback(opened); }); } document.body.appendChild(ifr); setTimeout(function() { document.body.removeChild(ifr); }, 2000); }

另外,可以通過 document.hidden 或 document.[webkit|moz|ms]Hidden 來判斷頁面是否被置入后台(即應用被喚起),或visibilitychange事件,但對於Android 4.4版本一下則不支持。

iOS9

在 iOS 9 上,iframe 方案變得不可用。
按不能使用之前Android的代碼,因為在打開自定義 URL scheme 時,會彈出對話框,詢問是否用 xx 應用來打開。往往用戶還沒來得及點擊打開,定時器又觸發了,導致跳到 App Store。

可以在嘗試打開URL scheme 后,再加一個頁面跳轉,這樣對話框會被覆蓋,再刷新頁面,就能無需確認喚起APP:

$('a').click(function() { location.href = '自定義 URL scheme'; location.href = '下載頁'; location.reload(); }

這里,下載頁延時 2 秒跳轉到 App Store。

APP已安裝這是沒問題的,但如果APP未安裝,跳 App Store 的請求會失敗。
這時可以使用兩個定時器:

$('a').click(function() { location.href = '自定義 URL scheme'; setTimeout(function() { location.href = '下載頁'; }, 250); setTimeout(function() { location.reload(); }, 1000); }

不過在iOS9中其實是支持universal link的,就是一個http域名形式,在微信中都可以喚起APP。如果未安裝的話,可以直接引導用戶去APP store下載。

可以參考這篇文章

http://www.magicwindow.cn/doc/#universal-link-info

沒有完美的解決方案

主要是在安卓上,總歸會有各種兼容問題,知乎的解決辦法是,提供兩個按鈕,一個下載,一個打開APP,讓用戶自己選。

微信中打開

因為微信將喚起本地APP的接口給禁了,所以微信中是不能直接喚起APP的,一般做法是提示用戶在瀏覽器中打開,之后的流程還是我們上面講的內容。

但是,在iOS9中,這個限制是可以突破的,也就是說可以直接喚起APP。方法就是使用我們上文提到的universal link。

在Android和iOS8及其以下系統中,我們可以利用騰訊的親兒子:應用寶。簡單講,就是把你的喚起地址配置成你APP的應用寶地址,微信中跳轉到這個地址后,如果用戶已經安裝了APP,則可直接喚起,如果沒有安裝,則可直接點擊下載,如下圖示:

但這里有坑需要注意。

對於使用universal link來說,如下圖所示用戶在微信中打開APP之后,可能不小心點擊右上角的鏈接(比方說點幾分享,卻不小心點擊了"mlinks.cc"),導致跳到外部瀏覽器中,如下圖所示:

這時候再在微信中就打不開APP了,因為universal link已被關閉,這是iOS9的機制,沒法改變,這時候用戶再在微信中打開,就得需要一個中間頁來引導用戶在外部瀏覽器中打開APP,如下圖所示:

另外,在微信中喚醒APP默認只能到達首頁,即不能到達指定頁面或內容,如果想要做,則需要額外的處理。

拿來主義

從以上內容可以總結出:要做一個兼容性很好的方案,就需要考慮各種情況,在不同的情況適配不同的方案,比方說用戶是在手機瀏覽器打開還是微信中打開,或者是在pc中打開,universal link是否被關閉等,這就使代碼實現變得復雜,且容易出錯,且還有安卓平台機型眾多、瀏覽器眾多等導致的兼容問題。

如果覺得實現難度或者成本太高,你可以考慮使用魔窗的mLink。只要你加了魔窗的sdk,就可以通過類似“https://s.mlinks.cc/AA01”的鏈接,在任何環境下打開你的APP(如果在pc機上打開,瀏覽器中將會出現APP下載地址的二維碼),上面提到的問題都不復存在,並且魔窗已經兼容超過600台以上安卓機型的第三方主流瀏覽器。而且關鍵的是,不管是在手機瀏覽器中,還是在微信中打開,你可以指定喚起APP后直達APP中的某個頁面或內容(某個促銷商品等),就算用戶沒安裝APP,點擊下載安裝之后,再打開,還是跳轉到指定的頁面,這就是場景還原,或者叫做Deffered Deep Linking。

歡迎訪問魔窗官網:http://www.magicwindow.cn/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM