常用喚醒APP的方式
前言
開工大吉,祝大家2019諸事順利! 當我們用微信或者瀏覽器開啟一個html5頁面的時候,有時候會有浮層,提示要不要開啟相關APP,當然也有的會自動喚醒到app中。這種喚醒是如何做到的呢?
今天簡單的寫下瀏覽器是如何喚醒APP的。當然,關於喚醒,涉及的東西蠻多,例如地址加引數喚醒,設定喚醒白名單,喚醒黑名單等等。h5地址和Scheme地址的轉換等等。本文簡單寫下喚醒的相關原理。
如下圖:
點選浮層,出現如下提示:
請問這是如何做到的呢?
常見喚醒App方式
一、 Scheme 方式
APP需要註冊自己的URL Scheme,用來唯一標識一個App。
Scheme格式:
1、iframe方式
var _iframe = document.createElement('iframe'); _iframe.src = scheme; _iframe.style.display = 'none'; document.body.appendChild(_iframe);
2、a連結方式
<a href="<scheme域名>://<path>?<params>=<value>">開啟APP</a>
3、location.href 直接跳轉
window.location.href = "<scheme域名>://<path>?<params>=<value>"
問題:
由於我們沒有辦法判斷使用者手機裡面安裝了APP沒有,因此,需要做一個延遲跳轉功能。所以當用戶沒有安裝時,通過延遲會跳轉到AppStore。iOS9+當跳轉App時,會彈出一個彈框,讓使用者選擇是否跳轉,此時還在當前頁,setTimeout中的程式碼會繼續執行,導致使用者還沒來得及選擇,就已經跳到AppStore。 若使用者未安裝App,Android上scheme開啟失敗,沒有任何提示,延遲之後,跳下載頁。但是iOS9+會先彈出個萬惡的跳轉失敗的彈窗,延遲之後,再跳下載頁。
支援情況
URL Scheme方式一直被廣泛使用,但是有些App並不認可,比如:微信、手機百度;站在這些App的角度上考慮,他們並不希望使用者為了看更多分享內容,跳出自己的App,因此他們就在客戶端內攔截了scheme方式呼端,導致URL Scheme方式在微信、手機百度中徹底失效!!!當然微信是存在一個白名單的,對於白名單中的分享連結是不會遮蔽scheme呼叫的。 安卓App廠商差異很大,情況比較多樣化(比如:Android Chrome版本25+通過iframe方式呼端失敗 )
相容性
Android系統:Chrome for Android無法通過iframe方式來呼叫scheme,而通過a連結的方式可以成功呼叫,而針對Chrome核心的瀏覽器如360瀏覽器,對於iframe和a連結的方式都能支援,所以對Chrome核心的瀏覽器採用a連結的方式來呼叫scheme;對於其他瀏覽器,如UC,QQ瀏覽器則採用iframe方式呼叫scheme。 iOS系統:Safari瀏覽器不支援 iframe可直接做頁面跳轉;對於UC、Chrome、QQ只能通過a連結方式呼叫scheme。 上述提到的遮蔽scheme方式的App:呼端失敗跳下載頁。
二、 Android Intent 方式
在安卓手機的chrome瀏覽器或者安卓手機瀏覽器上面,可以intent方式喚醒
intent: HOST/URI-path #Intent; package=[string];//android app包名 action=[string]; category=[string]; component=[string]; scheme=xxxx;// 協議頭 S.browser_fallback_url=[url]// 可選,scheme啟動客戶端失敗時的跳轉頁,一般為下載頁,需編碼 end; <!--Intent方式呼端--> <a href="intent://<role>/<path>#Intent;scheme=<scheme>;package=com.domain;S.browser_fallback_url=[url];end">開啟APP</a>
三、Universal Links方式喚醒
首先要開啟Universal Links開關
步驟如下:
1、註冊一個域名並支援https 2、有許可權上傳到網站根目錄.well-known(這個許可權是為了上傳一個Apple指定的檔案apple-app-site-association) 3、建立一個JSON檔名字為apple-app-site-association的檔案(檔名必須是這個!!!)
// apple-app-site-association檔案配置 { "applinks": { "apps": [], "details": { "ZVC23L5QY4.com.domain.app": { "paths": ["*"] } } } }
微博的配置地址: https://m.weibo.cn/.well-known/apple-app-site-association
攜程的配置地址: https://m.ctrip.com/.well-known/apple-app-site-association
當然,淘寶,京東等等都有。
完整喚醒方案
由於我們無法判斷使用者是否安裝App,所以以上所有的方案都只能嘗試呼端。整合上述這些方案,具體思路如下:
// iOS9+在開啟Universal Link開關的前提下,優先使用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); } // 處理未安裝客戶端情況:延遲跳轉到下載頁 setTimeout(function () { gotoDownload(); },延長時間); } else { // Android支援Intent方式時: intent呼起客戶端 intent(scheme); } }
tips:
前面提到的URL Scheme 方式的iframe和a連結方式,需要考慮使用者未安裝客戶端情況:延遲跳轉到下載頁。這個延長時間的設定很關鍵!!!延長時間的設定需要考慮:如果延長時間小於App的啟動時間,App還未啟動,就執行setTimeout程式碼;如果延長時間較長,當用戶未安裝App時,需要等待特別久的時間才能執行setTimeout程式碼。
對程式碼封裝,根據不同業務呼端需求,可以提煉幾個可配引數:呼端scheme地址、呼端失敗是否跳下載頁、下載頁連結、呼起客戶端失敗超時時間、呼起回撥;這樣做的好處是:呼叫元件時,根據不同需求傳遞引數即可。
優化方案
實際測試時發現:當成功呼起App時,使用者再次返回到Safari瀏覽器的頁面時已經跳轉到下載頁面了,此時需要對setTimeout做清除定時器處理。 當本地App被喚起時,App處於裝置可視視窗的最高層,此時瀏覽器進入後臺程式頁面會被隱藏掉,會觸發pagehide與visibilitychange事件,(關於這兩個API,不瞭解的同學可以檢視我之前文章: https://www.haorooms.com/post/page_api_cst)。此時應先清除setTimeout事件;同時,document.hide屬性設定為true,所以setTimeout內不做跳轉處理,防止頁面跳轉到下載頁面。
實際開發中,為了防止某些瀏覽器不支援這個 Page Visibility API,最好同時監聽pagehide事件,這樣會比較保險(相關程式碼如下)。
// 頁面隱藏時觸發 window.onpagehide = function () { if (timeout) { clearTimeout(timeout); } }; // 頁面的可見狀態變化時,會觸發 visibilitychange = function () { const tag = document.hidden || document.webkitHidden; if (tag && timeout) { clearTimeout(timeout); } } document.addEventListener('visibilitychange', visibilitychange, false); // 相容多的瀏覽器事件 document.addEventListener('webkitvisibilitychange', visibilitychange, false);
關於喚醒更多文章,我後期會補充一些。簡單的喚醒方式就先寫到這裡。