H5喚起App

最近總接到落地頁的需求店枣,落地頁的職責(zé)主要是引流速警,有以下幾種類型
1、引導(dǎo)已經(jīng)下載App的用戶打開App
2鸯两、引導(dǎo)未下載App的用戶下載App
3闷旧、引導(dǎo)未注冊的用戶注冊
4、引導(dǎo)已經(jīng)注冊的用戶進(jìn)入我們的主頁或者其他的操作
從數(shù)據(jù)上可以體現(xiàn)在用戶停留在App的時(shí)間多了钧唐,或者增加了用戶量

喚起App主要的媒介是什么呢忙灼?

URL Scheme

URL Scheme的組成

[scheme:][//authority][path][?query][#fragment]
App 微信 支付寶 淘寶 微博
URL Scheme weixin:// alipay:// taobao:// sinaweibo://
     行為(應(yīng)用的某個(gè)功能)    
            |
scheme://[path][?query]
   |               |
應(yīng)用標(biāo)識       功能需要的參數(shù)

URL Scheme 在 ios 9+ 上諸如 safari、UC、QQ瀏覽器中该园, iframe 均無法成功喚起 APP酸舍,只能通過 window.location 才能成功喚端。

Intent

安卓的原生谷歌瀏覽器自從 chrome25 版本開始對于喚端功能做了一些變化里初,URL Scheme 無法再啟動(dòng)Android應(yīng)用啃勉。 例如,通過 iframe 指向 weixin://双妨,即使用戶安裝了微信也無法打開淮阐。所以,APP需要實(shí)現(xiàn)谷歌官方提供的 intent: 語法斥难,或者實(shí)現(xiàn)讓用戶通過自定義手勢來打開APP枝嘶。
安卓版本 4.4.4 以上機(jī)型的安卓自帶瀏覽器、chrome 瀏覽器哑诊,需要通過 intent 跳轉(zhuǎn)
intents文檔

  • Intent 語法
intent:
   HOST/URI-path // Optional host 
   #Intent; 
      package=[string]; 
      action=[string]; 
      category=[string]; 
      component=[string]; 
      scheme=[string]; 
   end;

如果用戶未安裝 APP群扶,則會跳轉(zhuǎn)到系統(tǒng)默認(rèn)商店。當(dāng)然镀裤,如果你想要指定一個(gè)喚起失敗的跳轉(zhuǎn)地址竞阐,添加下面的字符串在 end; 前就可以了:

S.browser_fallback_url=[encoded_full_url]
  • 示例
    下面是打開 Zxing 二維碼掃描 APP 的 intent。
intent:
   //scan/
   #Intent; 
      package=com.google.zxing.client.android; 
      scheme=zxing; 
   end;
<a href="intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;S.browser_fallback_url=http%3A%2F%2Fzxing.org;end"> Take a QR code </a>

Universal Link

為什么要使用 Universal Link

傳統(tǒng)的 Scheme 鏈接有以下幾個(gè)痛點(diǎn):

  • 在 ios 上會有確認(rèn)彈窗提示用戶是否打開暑劝,對于用戶來說喚端骆莹,多出了一步操作。若用戶未安裝 APP 担猛,也會有一個(gè)提示窗幕垦,告知我們 “打不開該網(wǎng)頁,因?yàn)榫W(wǎng)址無效”
  • 傳統(tǒng) Scheme 跳轉(zhuǎn)無法得知喚端是否成功傅联,Universal Link 喚端失敗可以直接打開此鏈接對應(yīng)的頁面
  • Scheme 在微信先改、微博、QQ瀏覽器蒸走、手百中都已經(jīng)被禁止使用仇奶,使用 Universal Link 可以避開它們的屏蔽( 截止到 18年8月21日,微信和QQ瀏覽器已經(jīng)禁止了 Universal Link比驻,其他主流APP未發(fā)現(xiàn)有禁止 )

如何讓 APP 支持 Universal Link

有大量的文章會詳細(xì)的告訴我們?nèi)绾闻渲酶盟荩阋部梢匀タ?a target="_blank">官方文檔,我這里簡單的寫一個(gè)12345别惦。

  1. 擁有一個(gè)支持 https 的域名
  2. 開發(fā)者中心 狈茉,Identifiers 下 AppIDs 找到自己的 App ID,編輯打開 Associated Domains 服務(wù)掸掸。
  3. 打開工程配置中的 Associated Domains 氯庆,在其中的 Domains 中填入你想支持的域名,必須以 applinks: 為前綴
  4. 配置 apple-app-site-association 文件,文件名必須為 apple-app-site-association 点晴,不帶任何后綴
  5. 上傳該文件到你的 HTTPS 服務(wù)器的 根目錄 或者 .well-known 目錄下

Universal Link 配置中的坑

這里放一下我們在配置過程中遇到的坑,當(dāng)然首先你在配置過程中必須得嚴(yán)格按照上面的要求去做悯周,尤其是加粗的地方粒督。

  • 域名問題

Universal Link 支持的域名最多只能支持到二級域名,如果你用到了三級域名禽翼,Universal Link 喚端是不會生效的屠橄。

  • 跨域問題

IOS 9.2 以后,必須要觸發(fā)跨域才能支持 Universal Link 喚端闰挡。

IOS 那邊有這樣一個(gè)判斷锐墙,如果你要打開的 Universal Link 和 當(dāng)前頁面是同一域名,ios 尊重用戶最可能的意圖长酗,直接打開鏈接所對應(yīng)的頁面溪北。如果不在同一域名下,則在你的 APP 中打開鏈接夺脾,也就是執(zhí)行具體的喚端操作之拨。

  • Universal Link 是空頁面

Universal Link 本質(zhì)上是個(gè)空頁面,如果未安裝 APP咧叭,Universal Link 被當(dāng)做普通的頁面鏈接蚀乔,自然會跳到 404 頁面,所以我們需要將它綁定到我們的中轉(zhuǎn)頁或者下載頁菲茬。

喚端方式

  • Android中,不同瀏覽器對喚起APP有嚴(yán)重的兼容性問題,主要處理方案有以下幾種:
    1灶似、window.location.href
    2幻林、通過創(chuàng)建 iframe 并為其 src 賦值(主要)
    3、通過 intent
    4马胧、通過制造不可見 a 鏈接汉买,并觸發(fā)點(diǎn)擊

  • ios中,不同瀏覽器對喚起APP有嚴(yán)重的兼容性問題佩脊,主要處理方案有以下幾種:
    1蛙粘、系統(tǒng)版本在 8 以下時(shí),可以監(jiān)聽頁面的 pagehide / visibilitychange 事件威彰。
    2出牧、 window.location.href (主要)
    系統(tǒng)版本大于 8 以后可以 URL scheme 進(jìn)行跳轉(zhuǎn)。 IOS9 可以使用 universal Link

這里我們結(jié)合了兩種來處理歇盼。

判斷喚端是否成功

在瀏覽器實(shí)際上是沒有能力判斷手機(jī)里是否安裝了某個(gè)App的舔痕,所以只能夠采取一種投機(jī)取巧的方式。APP 如果被喚起的話,頁面就會進(jìn)入后臺運(yùn)行伯复。setInterval 在 ios 中不會停止運(yùn)行慨代,在 android 中停止運(yùn)行。

  • ios 通過 document.hidden 和 document.webkitHidden 屬性來判斷 APP 在 ios 中是否被正常喚起啸如,2000ms 內(nèi)侍匙,頁面轉(zhuǎn)入后臺運(yùn)行,document.hidden 會返回 true叮雳,代表喚端成功想暗,反之則代表失敗。
  • Android 我們的判斷條件比預(yù)期時(shí)間多設(shè)置了 500ms帘不,所以如果安卓中 setInterval 內(nèi)的函數(shù)執(zhí)行 100 次以內(nèi)所費(fèi)時(shí)間超過 2500ms说莫,則說明 APP 喚起成功,反之則代表失敗寞焙。
    在JavaScript中判斷頁面是否進(jìn)入后臺來判斷打開成功储狭。Html5提供了下列事件和屬性可以利用:
    pagehide : 頁面隱藏時(shí)觸發(fā)
    visibilitychange : 頁面隱藏沒有在當(dāng)前顯示時(shí)觸發(fā)(切換tab也會觸發(fā)該事件)
    document.hidden : 當(dāng)頁面隱藏時(shí),該值為true捣郊,顯示時(shí)為false
const initialTime = new Date();
let counter = 0;
let waitTime = 0;
const checkOpen = setInterval(() => {
   count++;
   waitTime = new Date() - initialTime;
   if (waitTime > 2500) {
      clearInterval(checkOpen);
      cb();
   }
   if (counter < 100) return;
   const hide = document.hidden || document.webkitHidden;
   if (!hide) {
      cb(); // 喚端失敗的回調(diào)函數(shù)
   }
}, 20);

如果喚端失斁堋(APP 未安裝),我們總是要做一些處理的模她,可以是跳轉(zhuǎn)下載頁稻艰,可以是 ios 下跳轉(zhuǎn) App Store… 但是Js 并不能提供給我們獲取 APP 喚起狀態(tài)的能力,Android Intent 以及 Universal Link 倒是不用擔(dān)心侈净,它們倆的自身機(jī)制允許它們喚端失敗后直接導(dǎo)航至相應(yīng)的頁面尊勿,但是 URL Scheme 并不具備這樣的能力,所以我們只能通過一些很 hack 的方式來實(shí)現(xiàn) APP 喚起檢測功能畜侦。

代碼

const browser = {
    getBrowser: function() {
        var u = navigator.userAgent,
            app = navigator.appVersion;
        return {
            trident: u.indexOf('Trident') > -1, //IE內(nèi)核
            presto: u.indexOf('Presto') > -1, //opera內(nèi)核
            webKit: u.indexOf('AppleWebKit') > -1, //蘋果元扔、谷歌內(nèi)核
            gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐內(nèi)核
            opera: u.indexOf('Opera') > -1,
            chrome: u.indexOf('Chrome') > -1,
            firefox: u.indexOf('Firefox') > -1,
            safari: u.indexOf('Safari') > -1, //注意chrome瀏覽器此項(xiàng)也為true,非chrome且此項(xiàng)為true則可確定為Safari
            ie: u.indexOf('compatible') > -1 && u.indexOf('MSIE') > -1 && u.indexOf('Gecko') == -1,
            mobile: u.search(/AppleWebKit.*Mobile/) > -1, //是否為移動(dòng)終端
            ios: u.search(/\(i[^;]+;( U;)? CPU.+Mac OS X/) > -1, //ios終端
            android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, //android終端
            winPhone: u.search(/Windows Phone/) > -1, //windows phone終端
            iPhone: u.indexOf('iPhone') > -1, //是否為iPhon
            iPad: u.indexOf('iPad') > -1, //是否iPad
            webApp: u.indexOf('Safari') == -1, //是否Safari web應(yīng)該程序旋膳,沒有頭部與底部
            weibo: u.search(/WeiBo/i) > -1, //是否微博
            weixin: u.search(/MicroMessenger/i) > -1, //是否微信
            qq: u.search(/\sQQ/i) > -1, //是否QQ
            mQQ: u.search(/MQQBrowser/) > -1, //是否QQ手機(jī)瀏覽器
            uc: u.search(/UCBrowser/) > -1 //是否UC瀏覽器
        };
    }(),
  getIOSVersion:  function getIOSVersion() {
            const verion = navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);
            return parseInt(verion[1], 10);
}()
}
/**
 * [evokeApp 喚起APP]
 * @param  {[Object]} config  [跳轉(zhuǎn)的URL]
 * config.ios.url {[String]} [iOS跳轉(zhuǎn)的URL]
 * config.ios.data {[String]} [iOS URL參數(shù)]
 * config.ios.callback {[function]} //android的回掉如果沒有下載app就執(zhí)行操作
 * config.android.url {[String]} [android跳轉(zhuǎn)的URL]
 * config.android.data {[String]} [android URL參數(shù)]
 * config.android.callback {[function]} //android的回掉如果沒有下載app就執(zhí)行操作
 */
const evokeApp = (config) =>{
//對微信澎语,微博,qq做處理彈窗
if (browser.versions.weibo || browser.versions.weixin || browser.versions.qq) {
        return;
    }
//
let browserVersions = browser.versions;
let evokeAppURL = '';
let cb;
    if (browserVersions.ios) {
        evokeAppURL = config.ios.data ? 'authority://' + config.ios.url + '?' + config.ios.dataArr.join('&') : 'authority://' + config.ios.url;
cb = config.ios.callback;
    } else if (browserVersions.android) {
      evokeAppURL = config.android.data ? 'authority://' + config.android.url + '?' + config.android.dataArr.join('&') : 'authority://' + config.android.url;
cb = config.android.callback;
    };
const initialTime = new Date();
let counter = 0;
let waitTime = 0;
const checkOpen = setInterval(() => {
   count++;
   waitTime = new Date() - initialTime;
   if (waitTime > 2500) {
      clearInterval(checkOpen);
      cb && cb();
   }
   if (counter < 100) return;
   const hide = document.hidden || document.webkitHidden;
   if (!hide) {
      cb && cb(); // 喚端失敗的回調(diào)函數(shù)
   }
}, 20);
}

注意

1验懊、h5在微信中無法喚醒App擅羞,需要“用瀏覽器打開”
微信對所有的分享連接做了scheme屏蔽,也就是說分享連接中所有對于scheme的調(diào)用都被微信封掉了义图。

  1. 在詢問是否打開APP的時(shí)候减俏,如果選擇了“取消”,則再喚起APP的時(shí)候會不起作用碱工。目前并沒有什么解決方案娃承,在chrome Android,UC Android上會復(fù)現(xiàn)問題奏夫。需再次刷新頁面才行。

  2. 在ios手機(jī)中历筝,用location.href喚起app酗昼,本地如果沒裝app,會彈窗提示safari瀏覽器打不開該網(wǎng)頁梳猪,網(wǎng)址無效仔雷,后面在用location.href來下載安裝包的話也會顯示同樣的錯(cuò)誤,即使你的下載鏈接是有效的舔示。解決辦法:IOS9及以上使用 Universal Links

感謝作者
參考博客

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末电抚,一起剝皮案震驚了整個(gè)濱河市惕稻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蝙叛,老刑警劉巖俺祠,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異借帘,居然都是意外死亡蜘渣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門肺然,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蔫缸,“玉大人,你說我怎么就攤上這事际起∈奥担” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵街望,是天一觀的道長校翔。 經(jīng)常有香客問我,道長灾前,這世上最難降的妖魔是什么防症? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮哎甲,結(jié)果婚禮上蔫敲,老公的妹妹穿的比我還像新娘。我一直安慰自己炭玫,他們只是感情好燕偶,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著础嫡,像睡著了一般指么。 火紅的嫁衣襯著肌膚如雪酝惧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天伯诬,我揣著相機(jī)與錄音晚唇,去河邊找鬼。 笑死盗似,一個(gè)胖子當(dāng)著我的面吹牛哩陕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赫舒,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼悍及,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了接癌?” 一聲冷哼從身側(cè)響起心赶,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缺猛,沒想到半個(gè)月后缨叫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荔燎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年耻姥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片有咨。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡琐簇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出座享,到底是詐尸還是另有隱情鸽嫂,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布征讲,位于F島的核電站据某,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏诗箍。R本人自食惡果不足惜癣籽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望滤祖。 院中可真熱鬧筷狼,春花似錦、人聲如沸匠童。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽汤求。三九已至俏险,卻和暖如春严拒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背竖独。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工裤唠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人莹痢。 一個(gè)月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓种蘸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親竞膳。 傳聞我的和親對象是個(gè)殘疾皇子航瞭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容

  • H5喚起APP進(jìn)行分享 最近很久沒有寫blog和note,倒是過家家的開發(fā)日志簡單草草寫了一點(diǎn)坦辟。這次記錄下這個(gè)學(xué)習(xí)...
    二歪求知iSk2y閱讀 27,910評論 3 25
  • 最近遇到一個(gè)需求:點(diǎn)擊一個(gè)按鈕刊侯,如果本機(jī)裝有則喚起app,沒有的話則跳下載頁长窄。 剛一接到需求,覺得很熟悉纲菌,實(shí)際上這...
    tobAlier閱讀 14,150評論 3 2
  • 一般 H5 常見的引導(dǎo)頁挠日,為已安裝 app 的用戶喚起 app,未安裝 app 的用戶引導(dǎo)下載 app 一翰舌、簡介 ...
    Johnson杰閱讀 9,351評論 1 6
  • 最近有個(gè)需求椅贱,公司H5的頁面在瀏覽器中打開的時(shí)候需要喚起自己的app懂算,如果移動(dòng)端沒有安裝本app就跳轉(zhuǎn)到下載頁面。...
    昨日d書生閱讀 8,597評論 2 1
  • 移動(dòng)互聯(lián)網(wǎng)時(shí)代,“用戶增長”成為每個(gè)公司關(guān)注的重點(diǎn)話題山橄。為了將更多用戶引導(dǎo)到客戶端內(nèi)垮媒,產(chǎn)品經(jīng)理會習(xí)慣性地在網(wǎng)頁的各...
    宇曉閱讀 21,784評論 4 20