移動(dòng)互聯(lián)網(wǎng)時(shí)代,“用戶增長”成為每個(gè)公司關(guān)注的重點(diǎn)話題驶社。為了將更多用戶引導(dǎo)到客戶端內(nèi)企量,產(chǎn)品經(jīng)理會(huì)習(xí)慣性地在網(wǎng)頁的各個(gè)地方巧妙隱藏喚醒App的“機(jī)關(guān)”。
常見的出現(xiàn)場景
瀏覽器 —喚醒—> App
??用戶在瀏覽器中瀏覽網(wǎng)頁時(shí)亡电,當(dāng)檢測到該網(wǎng)頁來自于某個(gè)App時(shí)届巩,此時(shí)可以引導(dǎo)用戶呼起或者下載App
微信、QQ —喚醒—> App
??用戶將App中自己喜歡的內(nèi)容分享到微信份乒、QQ恕汇,在站外打開網(wǎng)頁時(shí)腕唧,可以正常瀏覽,也可以引導(dǎo)用戶呼起或者下載App
接下來瘾英,讓我們深入研究下喚醒App的幾種解決方案枣接?
喚醒App的幾種解決方案
1、 URL Scheme 方式
- 條件
- APP需要注冊自己的URL Scheme方咆,用來唯一標(biāo)識(shí)一個(gè)App月腋。
- Scheme格式:
<scheme域名>://<path>?<params>=<value>
- 代碼
1) iframe方式
var _iframe = document.createElement('iframe');
_iframe.src = scheme;
_iframe.style.display = 'none';
document.body.appendChild(_iframe);
window.setTimeout(function(){
document.body.removeChild(_iframe);
if((+new Date()) - openTime > 2500) {
window.location.href = url;
}
}, 2000);
2)a鏈接方式
<a href="<scheme域名>://<path>?<params>=<value>">打開APP</a>
3)location.href 直接跳轉(zhuǎn)
window.location.href = "<scheme域名>://<path>?<params>=<value>"
-
優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn):iOS、Android均支持瓣赂,開發(fā)簡單榆骚;web-native協(xié)議制定簡單。
- 缺點(diǎn):
由于要考慮用戶沒有安裝App的情況煌集,所以當(dāng)用戶沒有安裝時(shí)妓肢,通過延遲會(huì)跳轉(zhuǎn)到AppStore。iOS9+當(dāng)跳轉(zhuǎn)App時(shí)苫纤,會(huì)彈出一個(gè)彈框碉钠,讓用戶選擇是否跳轉(zhuǎn),此時(shí)還在當(dāng)前頁卷拘,setTimeout中的代碼會(huì)繼續(xù)執(zhí)行喊废,導(dǎo)致用戶還沒來得及選擇,就已經(jīng)跳到AppStore栗弟。
若用戶未安裝App污筷,Android上scheme打開失敗,沒有任何提示乍赫,延遲之后瓣蛀,跳下載頁。但是iOS9+會(huì)先彈出個(gè)萬惡的跳轉(zhuǎn)失敗的彈窗雷厂,延遲之后惋增,再跳下載頁。iOS9+呼端確認(rèn)彈窗
iOS9+萬惡的跳轉(zhuǎn)失敗的彈窗
-
支持情況
URL Scheme方式一直被廣泛使用改鲫,但是有些App并不認(rèn)可诈皿,比如:微信、手機(jī)百度像棘;站在這些App的角度上考慮纫塌,他們并不希望用戶為了看更多分享內(nèi)容,跳出自己的App讲弄,因此他們就在客戶端內(nèi)攔截了scheme方式呼端,導(dǎo)致URL Scheme方式在微信依痊、手機(jī)百度中徹底失效1艹T跖!當(dāng)然微信是存在一個(gè)白名單的瓶摆,對于白名單中的分享鏈接是不會(huì)屏蔽scheme調(diào)用的凉逛。
安卓App廠商差異很大,情況比較多樣化(比如:Android Chrome版本25+通過iframe方式呼端失敗 ) 兼容性
Android系統(tǒng):Chrome for Android無法通過iframe方式來調(diào)用scheme群井,而通過a鏈接的方式可以成功調(diào)用状飞,而針對Chrome內(nèi)核的瀏覽器如360瀏覽器,對于iframe和a鏈接的方式都能支持书斜,所以對Chrome內(nèi)核的瀏覽器采用a鏈接的方式來調(diào)用scheme诬辈;對于其他瀏覽器,如UC荐吉,QQ瀏覽器則采用iframe方式調(diào)用scheme焙糟。
iOS系統(tǒng):Safari瀏覽器不支持 iframe可直接做頁面跳轉(zhuǎn);對于UC样屠、Chrome穿撮、QQ只能通過a鏈接方式調(diào)用scheme。
上述提到的屏蔽scheme方式的App:呼端失敗跳下載頁痪欲。
- 適用于安裝就跳轉(zhuǎn)悦穿,不安裝就跳下載的呼端場景
- 參考文檔(有關(guān)客戶端配置scheme)
Android scheme呼起App
iOS 客戶端URL Scheme配置以及使用
2、 Android Intent 方式
- 條件
A little known feature in Android lets you launch apps directly from a web page via an Android Intent. One scenario is launching an app when the user lands on a page, which you can achieve by embedding an iframe in the page with a custom URI-scheme set as the
src
, as follows:<iframe src="paulsawesomeapp://page1"> </iframe>
. This works in the Chrome for Android browser, version 18 and earlier. It also works in the Android browser, of course. - 構(gòu)造intent字符串
intent:
HOST/URI-path
#Intent;
package=[string]; // android app包名
action=[string];
category=[string];
component=[string];
scheme=xxxx; // 協(xié)議頭
S.browser_fallback_url=[url] // 可選业踢,scheme啟動(dòng)客戶端失敗時(shí)的跳轉(zhuǎn)頁栗柒,一般為下載頁,需編碼
end;
- 代碼
<!--Intent方式呼端-->
<a href="intent://<role>/<path>#Intent;scheme=<scheme>;package=com.domain;S.browser_fallback_url=[url];end">打開APP</a>
- 支持情況
- iOS:不支持
- Android:Android的Intent方式比URL Scheme方式要靠譜陨亡,能通過參數(shù)設(shè)置呼端失敗要跳轉(zhuǎn)的地址傍衡;若手機(jī)能匹配到對應(yīng)App,則成功呼到對應(yīng)頁面负蠕,若未安裝蛙埂,會(huì)跳手機(jī)自帶的應(yīng)用市場下載。
- 參考文檔
Android Intents with Chrome
3遮糖、Universal Links
-
條件
- iOS9+系統(tǒng)
- Universal Link是通過標(biāo)準(zhǔn)的http/https協(xié)議鏈接喚起App绣的;若未安裝App,訪問此通用鏈接欲账,可以自定義頁面屡江;
-
優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn)
唯一性:不像自定義的Scheme方式,該方式是通過標(biāo)準(zhǔn)的http/https協(xié)議的鏈接到你的App.未安裝App時(shí)赛不,自定義的Scheme方式無法打開惩嘉,而http/https的Universal Link通用鏈接有很好的兼容性;
安全性:當(dāng)用戶安裝了App時(shí)踢故,iOS會(huì)從網(wǎng)站上去下載說明文件(下面所說的apple-app-site-association的文件文黎,說明這個(gè)App可以打開哪些http鏈接),這個(gè)說明文件是只有開發(fā)者有權(quán)限寫并上傳到網(wǎng)站的根目錄惹苗,所以App與網(wǎng)頁http鏈接的關(guān)聯(lián)是安全的。
可變性:當(dāng)用戶沒有安裝App時(shí)耸峭,Universal Link鏈接也能正常打開桩蓉,也可以設(shè)置:未安裝App時(shí),可以用Safari打開該鏈接劳闹。
簡單性:一個(gè)URL鏈接院究,可以將網(wǎng)站和App做關(guān)聯(lián)。
私有性:其他App在不知道你是否安裝的情況下本涕,也可以和你的App進(jìn)行相互通信(因?yàn)橹皇且粋€(gè)普通的http鏈接耙堤)。 -
缺點(diǎn):只支持 iOS9+系統(tǒng)偏友;在開啟了Universal Link之后蔬胯,用戶可以通過該方式呼端,成功呼端后右上角會(huì)顯示鏈接地址(iOS9位他、 iOS10會(huì)出現(xiàn)面包屑導(dǎo)航氛濒,iOS11+沒有面包屑導(dǎo)航(如下圖)),當(dāng)用戶一不小心手動(dòng)點(diǎn)擊這個(gè)地址時(shí)(俗稱:Universal link誤關(guān))鹅髓,Universal Link會(huì)失效(失效后舞竿,Universal Link呼端就永遠(yuǎn)失敗了,永遠(yuǎn)呼不起來窿冯,跳下載頁骗奖,所以我們要重新激活Universal Link)需要引導(dǎo)用戶到Safari瀏覽器,引導(dǎo)用戶點(diǎn)擊Safari內(nèi)置頂部的系統(tǒng)呼端條醒串,重新激活Universal Link执桌,也可以將鏈接復(fù)制到備忘錄中,長按鏈接出現(xiàn)用App打開芜赌,也可激活Universal Link仰挣。
image.png
image.png
image.png
image.png
- 優(yōu)點(diǎn)
-
開啟Universal Links開關(guān)
- 注冊一個(gè)域名并支持https
- 有權(quán)限上傳到網(wǎng)站根目錄.well-know(這個(gè)權(quán)限是為了上傳一個(gè)Apple指定的文件apple-app-site-association)
- 創(chuàng)建一個(gè)JSON文件名字為apple-app-site-association的文件(文件名必須是這個(gè)!2颉1旌)
// apple-app-site-association文件配置
{
"applinks": {
"apps": [],
"details": {
"ZVC23L5QY4.com.domain.app": {
"paths": ["*"]
}
}
}
}
注意:
大小寫敏感;嚴(yán)格匹配配置的path路徑洲愤;apple-app-site-association文件的讀取颓芭,只在第一次啟動(dòng)App時(shí)加載;iOS9.2開始柬赐,在相同的domain下亡问,Universal Link不work,必須跨域肛宋;
以上只是重點(diǎn)部分內(nèi)容玛界,詳細(xì)說明請參考:
打通 iOS 9 的通用鏈接(Universal Links)
了解了呼端的幾種方式万矾,分享下我們團(tuán)隊(duì)完整的呼端解決方案
完整的解決方案
由于我們無法判斷用戶是否安裝App,所以以上所有的方案都只能嘗試呼端慎框。整合上述這些方案,具體思路如下:
// iOS9+在開啟Universal Link開關(guān)的前提下后添,優(yōu)先使用Universal Links方式呼端
if (!closeUnilink && isios && iosVer && iosVer >= 9) {
// 通過Universal Links方式獲取通用呼端鏈接
const unilink = getUnilink(opts.scheme, opts.unilink);
if (unilink) {
window.location.href = unilink;
}
} else {
// 不支持Intent方式笨枯,采用 URL Scheme 方式
if (!canIntent) {
// iOS9+ Safari 不支持iframe方式
if (!isWv && (ua.indexOf('safari') > -1 && iosVer && iosVer >= 9)) {
link(scheme);
} else {
iframe(scheme);
}
// 處理未安裝客戶端情況:延遲跳轉(zhuǎn)到下載頁
setTimeout(function () {
gotoDownload();
},延長時(shí)間);
} else {
// Android支持Intent方式時(shí): intent呼起客戶端
intent(scheme);
}
}
注意:
??前面提到的URL Scheme 方式的iframe和a鏈接方式,需要考慮用戶未安裝客戶端情況:延遲跳轉(zhuǎn)到下載頁遇西。這個(gè)延長時(shí)間的設(shè)置很關(guān)鍵O诰!粱檀!延長時(shí)間的設(shè)定需要考慮:如果延長時(shí)間小于App的啟動(dòng)時(shí)間洲敢,App還未啟動(dòng),就執(zhí)行setTimeout代碼茄蚯;如果延長時(shí)間較長压彭,當(dāng)用戶未安裝App時(shí),需要等待特別久的時(shí)間才能執(zhí)行setTimeout代碼渗常。
??對代碼封裝壮不,根據(jù)不同業(yè)務(wù)呼端需求,可以提煉幾個(gè)可配參數(shù):呼端scheme地址皱碘、呼端失敗是否跳下載頁询一、下載頁鏈接、呼起客戶端失敗超時(shí)時(shí)間癌椿、呼起回調(diào)健蕊;這樣做的好處是:調(diào)用組件時(shí),根據(jù)不同需求傳遞參數(shù)即可踢俄。
優(yōu)化
- 實(shí)際測試時(shí)發(fā)現(xiàn):當(dāng)成功呼起App時(shí)缩功,用戶再次返回到Safari瀏覽器的頁面時(shí)已經(jīng)跳轉(zhuǎn)到下載頁面了,此時(shí)需要對setTimeout做清除定時(shí)器處理褪贵。
- 當(dāng)本地App被喚起時(shí)掂之,App處于設(shè)備可視窗口的最高層,此時(shí)瀏覽器進(jìn)入后臺(tái)程序頁面會(huì)被隱藏掉脆丁,會(huì)觸發(fā)pagehide與visibilitychange事件世舰,此時(shí)應(yīng)先清除setTimeout事件;同時(shí)槽卫,document.hide屬性設(shè)置為true跟压,所以setTimeout內(nèi)不做跳轉(zhuǎn)處理,防止頁面跳轉(zhuǎn)到下載頁面歼培。
- 實(shí)際開發(fā)中震蒋,為了防止某些瀏覽器不支持這個(gè) Page Visibility API茸塞,最好同時(shí)監(jiān)聽pagehide事件,這樣會(huì)比較保險(xiǎn)(相關(guān)代碼如下)查剖。
// 頁面隱藏時(shí)觸發(fā)
window.onpagehide = function () {
if (timeout) {
clearTimeout(timeout);
}
};
// 頁面的可見狀態(tài)變化時(shí)钾虐,會(huì)觸發(fā)
visibilitychange = function () {
const tag = document.hidden || document.webkitHidden;
if (tag && timeout) {
clearTimeout(timeout);
}
}
document.addEventListener('visibilitychange', visibilitychange, false);
// 兼容多的瀏覽器事件
document.addEventListener('webkitvisibilitychange', visibilitychange, false);
代碼中有關(guān)事件具體參考:Page Visibility API文檔
測試結(jié)果
測試機(jī)型主要針對iOS和Android默認(rèn)瀏覽器、Chrome等一些常用主流瀏覽器笋庄,iOS9+微信內(nèi)嵌請嘗試使用 Universal Link 方式呼起客戶端效扫。
測試反饋
以上完整的呼端解決方案我們完美的使用了很久,直到2018年1月7日直砂,微信封掉了內(nèi)置瀏覽器里的Universal Link呼端菌仁,導(dǎo)致微信內(nèi)引導(dǎo)呼端的流程徹底中斷!>苍荨济丘!
考慮到微信是站外分享很重要的渠道,我們當(dāng)然不能G⒅D∶浴!放過H枋俊@嵯啤!
- 首先:我們有一個(gè)思路:既然微信容器內(nèi)不能使用Universal Link呼端颂碘,那么我們可以脫離微信容器异赫,做一個(gè)中轉(zhuǎn)頁面,引導(dǎo)用戶去瀏覽器呼端头岔。
-
其次:想想用戶之前習(xí)慣性操作都是一次性直接點(diǎn)擊呼端成功的塔拳,引導(dǎo)的話鏈路有點(diǎn)長,用戶難免會(huì)吐槽峡竣。
所以靠抑,針對中轉(zhuǎn)頁面iOS客戶端新增 Universal Link 匹配規(guī)則(以中轉(zhuǎn)頁面鏈接為主),以便在微信內(nèi)适掰,「使用瀏覽器打開」后颂碧,被系統(tǒng)攔截后可以直接打開客戶端,不用引導(dǎo)去瀏覽器类浪。
當(dāng)然载城,對于Android用戶,我們考慮到也可以引導(dǎo)用戶去應(yīng)用寶呼端费就。 - 最后做了一點(diǎn)小優(yōu)化:在瀏覽器的中轉(zhuǎn)頁面中诉瓦,采用雙保險(xiǎn)呼端。當(dāng)客戶端配置好Universal Link鏈接時(shí),Safari瀏覽器訪問中轉(zhuǎn)頁面睬澡,頁面頂部會(huì)出現(xiàn)系統(tǒng)的呼端條固额,引導(dǎo)用戶下拉,用戶可以選擇使用系統(tǒng)呼端條打開煞聪,從而也能激活Universal Link斗躏,防止誤關(guān);采用按鈕點(diǎn)擊嘗試呼端(關(guān)閉Universal Link方式)米绕。
-
針對Universal Link誤關(guān)的現(xiàn)象瑟捣,可以采納這兩種方法
- 用樣式的方式遮擋右上角面包屑導(dǎo)航≌じ桑可以使得iOS9、iOS10和iOS11+達(dá)到視覺的一致性捐祠。但是樣式控制不好碱鳞,用戶體驗(yàn)會(huì)很不好。
- 獲取面包屑導(dǎo)航的觸發(fā)事件踱蛀,可以手動(dòng)的控制觸發(fā)后跳轉(zhuǎn)的地址(可以引導(dǎo)跳轉(zhuǎn)到中轉(zhuǎn)頁面窿给,引導(dǎo)用別的方式呼端)。這種算hack的解決方案率拒。要考慮成本問題崩泡,是否采納。
中轉(zhuǎn)頁面
iOS客戶端采用Universal link進(jìn)行系統(tǒng)攔截
雙保險(xiǎn)呼端
至此猬膨,站外呼端方案完美落幕~~~