移動互聯時代,很多互聯網服務都會同時具備網站以及移動客戶端,很多人認為APP的能幫助建立更穩固的用戶關係,於是經常會接到各種從瀏覽器、webview中喚醒APP的需求,顯然,這對於前端開發人員來說,是一件很糾結的事。
喚醒APP
目前常見的主動喚醒APP方式有幾種:
Url scheme
Url scheme是iOS,Android平台都支持,只需要原生APP開發時註冊scheme, 那麼用戶點擊到此類鏈接時,會自動跳到APP。比如
1
2
3
4
|
<a href="kaola://www.kaola.com">打開APP</a>
<a href="tel://13788889999">打開撥號</a>
|
如果配置scheme的路徑,並在app中識別,則可以直接打開APP特定頁面,如下:
1
2
|
<a href="kaola://www.kaola.com/product/8342.html">打開APP商品詳情</a>
|
上述的鏈接,需要考慮手機是否支持此Scheme:
支持:彈出相應程序;
不支持:錯誤處理情況因平台而異,部分app會直接跳錯誤頁(比如Android
Chrome/41,iOS中老版的Lofter);
也有的停留在原頁面,但彈出提示「無法打開網頁」(比如iOS7);iOS8以及最新的Android Chrome/43
目前都是直接停留在當前頁,不會跳出錯誤提示。
總體來看, iOS的支持程度比Android好,iOS在實際使用中,除非明確禁止的(比如微信),很少碰到不支持的情況;Android平台則各個app廠商差異很大,
比如Chrome從25及以後就不再支持通過js觸發(非用戶點擊),設置iframe src地址等來觸發scheme跳轉。
Android intent
這是Android平台獨有的,使用方式如下
1
2
3
4
5
6
7
8
9
| intent:
HOST/URI-path // Optional host
#Intent;
package=[string];
action=[string];
category=[string];
component=[string];
scheme=[string];
end;
|
這裡的HOST/URI-path, 與普通http URL 的host/path書寫方式相同, package是Android app的包名,其它參數如action、category、component不是很理解, 具體見
文檔 , 比如打開考拉 app的商品詳情,代碼如下
1
2
|
<a href="intent://www.kaola.com/product/8342.html#Intent;scheme=kaola;package=com.kaola;end">打開APP</a>
|
如果手機能匹配到相應的APP,則會直接打開;如沒有安裝,則會跳到手機默認的應用商店,比如Google原生系統Nexus 5,將會直接跳到Google Play, 對於國內各廠商定製過的系統,則跳轉到各自的默認應用商店,或者彈出商店供選擇。
intent 比scheme相對完善的一點是,提供一個打開失敗去向URL的選項,可以通過指定參數
S.browser_fallback_url
來指定去向URL。
比如如下的打開APP動作,如果打開失敗,則跳轉到app下載頁,這對於國內的特殊網絡環境,還是挺有用的。
1
2
|
<a href="intent://www.kaola.com/product/8342.html#Intent;scheme=kaola;package=com.kaola;S.browser_fallback_url=http%3A%2F%2Fapp.kaola.com;end">打開APP</a>
|
HTTP URL訂閱
Android Chrome平台獨有,app中訂閱自有內容相關的URL,在Chrome中瀏覽相關網頁時,會自動彈出提示,讓用戶選擇用瀏覽器還是APP打開,通用性有限。
iOS內置APP廣告條
在頁面Head中增加meta, 添加智能 App 廣告條 (iOS 6+ Safari), 如下
1
| <meta"apple-itunes-app"content"app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL"
|
可以自動判斷是否已安裝應用, 可惜只能用於iOS+Safari, 在第三方應用中就不行了。
效果如下:
Android Chrome內置app安裝提示
這個是Mobile Chrome 43 beta新加入的特性,在用戶瀏覽某一個網站多次後,如果Chrome發現該站點有原生APP,則會提示用戶下載原生APP,此項特性開發者無法干預,完全是Google的推薦行為,在項目中用不上,具體見
新聞報導
實際應用中存在的問題
移動平台提供這麼多喚醒APP的方法,但是功能還不夠完善,以下情況JS無法檢測並做處理:
- APP如果喚醒失敗,很多時候都會跳到錯誤頁,影響用戶體驗,而我們的需求很可能是需要跳到下載或者其它頁。
- APP成功喚醒,頁面無法直接得知,系統沒有提供此類回調。
實際需求、解決方案
- 要在打開APP失敗時,不能使當前頁面跳到錯誤頁,且打開失敗時,有失敗函數回調。
- 如果成功打開APP,有成功函數回調。
針對第一點,可以將打開動作放到iframe中,就算跳轉失敗仍能停留在當前頁面;那剩下的問題就是如何檢測APP是否成功打開;
網上常見解決方案如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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)
|
此腳本利用了程序切換到後台時,計時器回調會被推遲的原理,如果APP被喚醒,那麼此網頁必然進入後台,如果用戶從APP再切換回來,時間一般也會超過2.5s;如果app沒有喚醒,則setTimeout
基本上會準時回調,時間不會超過2s。但是實際上,這個僅僅在iOS平台有效,Android由於是多任務的,應用放到後台,setTimeout
基本上還是會準時觸發,所以這個邏輯還不夠完善。
那Android 瀏覽器有沒有方法檢測應用是否進入了後台呢? 頁面可見性API(
Page Visibility API), 可以通過檢測
document.hidden
或
document.[webkit|moz|ms]Hidden
來檢查頁面是否可見,或者訂閱頁面的
visibilitychange
事件; 如果僅僅應用在新版Android及Chrome上,這個是很美好的,對於老版本(<4.4)及Android Webview, 則不可用。
暮然回首,那人卻在燈火闌珊處,
setInterval
,對,就
setInterval
, 如果設置比較小的運行間隔(<30ms),在瀏覽器或者webview中,應用切換到後台,
setInterval
會被很明顯的延遲執行,比如設置一個運行間隔20ms,總計運行100次的定時器,如果頁面一直處於前台,則100次跑完,總耗時與
100x20=2000ms不會有太大差異,但頁面在後台運行時,此時間會明顯超過2000ms。可以利用這一點來實現是否成功打開APP檢測及回調。
代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| function openApp(openUrl, appUrl, action, callback) {
function checkOpen(cb){
var _clickTime = +(new Date());
function check(elsTime) {
if ( elsTime > 3000 || document.hidden || document.webkitHidden) {
cb(1);
} else {
cb(0);
}
}
var _count = 0, intHandle;
intHandle = setInterval(function(){
_count++;
var elsTime = +(new Date()) - _clickTime;
if (_count>=100 || elsTime > 3000 ) {
clearInterval(intHandle);
check(elsTime);
}
}, 20);
}
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);
}
|
iframe方式打開APP的問題:
- Android Chrome/25+ 無法打開APP,所以最好是APP配合監聽http URL 來實現。
- iOS、Android平台,近期發現在沒有安裝對應app時嘗試喚醒,有少數APP會連當前頁面(iframe的父頁面)也變成錯誤頁的情況。
其它問題:
微信無法打開或者下載,打開APP這個基本無解,下載則只能讓應用進駐應用寶市場,然後檢測到在微信中運行時,跳轉到應用寶頁面下載。
2015-11-01 補充
隨著iOS9, Android M的推出, 原先的Scheme URL喚醒app的方式成功率以及很低,並且蘋果還加入了確認機制,使得通過javascript來自動喚醒APP的方式基本不可用。
這兩大平台都推出了自己的WEB與APP連接的方式: Universal Links, App Link, 這部分需要App的開發人員來做了。
沒有留言:
張貼留言