第一種方法:
<meta name="apple-itunes-app" content="app-id=1359749746">在主頁內加一個meta標簽,讓native給你他們的id放上即可,這種會在頁面的上邊出現一條提示你已經安裝了app問你是否打開
參考網址 https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html
第二種方法:
let last = Date.now();
var frame = document.createElement('iframe');
frame.src = 'xkd://xkd.yirendai.com';
frame.style.display = 'none';
document.body.appendChild(frame);
setTimeout(function() { document.body.removeChild(frame); }, 4)
// window.location.href='xkd://xkd.yirendai.com'
setTimeout(function() {
if (Date.now() - last > 1000) {
_this.$router.push({path:'/loadingPageLogin/'+_this.loginType,query:{channelNo:_this.channelId}})
}
},1200)
上面這種方式喚起如果在某一個app內打開不會報錯了(如果用location.href喚起,在app內打開時喚起的地址會報錯因為是在app內打開的,但是用iframe有些and手機可能喚起不成功)
第三種方法:
https://github.com/AlanZhang001/H5CallUpNative
關於通過H5頁面喚Native戶端的介紹
本文檔用於介紹通過H5端喚起本地NN客戶端的研究過程!剛進新公司,導師讓研究下5頁面喚NNtive戶端的課題,后面公司客戶端產品可能會用到這方面的技術,所以研究了下,寫成文章,保密需要,去掉了和具體客戶端綁定的內容,希望對那些想了解這方面知識的人有用!
背景
-
目前通過H5頁面喚起native App的場景十分常見,比如常見的分享功能;一方面,對於用戶而言,相同的內容在native app上比H5體驗更好,操作更加方便,另一方面,對於app運營來說,可以增加app的用戶粘性度。
-
當前native客戶端內置webview中,比較常用的是通過schema打開登陸頁、觸發分享入口的顯示;而在外部瀏覽器或者webview中喚醒公司的客戶端目前還沒有太多嘗試,有據此展開研究的必要性,以便日后在真實的需求中使用!
喚醒native APP 的幾種方式
在Android端,常用的方式是Schame + Android Itent,在IOS端,常用的方式是Schema + Universal links(IOS9+); 使用的前提都是客戶端程序實現了schema協議。
下面對這3種方式做簡要的介紹:
Schema
在Android和IOS瀏覽器中(非微信瀏覽器),可以通過schema協議的方式喚醒本地app客戶端;schema協議在App注冊之后,與前端進行統一約定,通過H5頁面訪問某個具體的協議地址,即可打開對應的App客戶端 頁面;
訪問協議地址,目前有3種方式,以打開NN客戶端登錄頁為例:
1.通過a標簽打開,點擊標簽是啟動
<a href="ftnn:login">打開登錄頁</a>
2.通過iframe打開,設置iframe.src即會啟動
<iframe src="ftnn:login"></iframe>
3.直接通過window.location 進行跳轉
window.location.href= "ftnn:login";
Android上注冊schema協議,可以參考博文:Android手機上實現WebApp直接調起NativeApp
注:由於微信的白名單限制,無法通過schema來喚起本地app,只有白名單內的app才能通過微信瀏覽器喚醒,這個問題我目前沒有找到合適的解決辦法!
Android Intent
在Android Chrome瀏覽器中,版本號在chrome 25+的版本不在支持通過傳統schema的方法喚醒App,比如通過設置window.location = "xxxx://login"將無法喚醒本地客戶端。需要通過Android Intent 來喚醒APP; 使用方式如下:
1.構件intent字符串:
intent:
login // 特定的schema uri,例如login表示打開NN登陸頁
#Intent;
package=cn.xxxx.xxxxxx; // NN apk 信息
action=android.intent.action.VIEW; // NN apk 信息
category=android.intent.category.DEFAULT; // NN apk 信息
component=[string]; // NN apk 信息,可選
scheme=xxxx; // 協議頭
S.browser_fallback_url=[url] // 可選,schema啟動客戶端失敗時的跳轉頁,一般為下載頁,需編碼
end;
2.構造一個a標簽,將上面schame 字符串作為其href值,當點擊a標簽時,即為通過schema打開某客戶端登陸頁,如果未安裝客戶端,則會跳轉到指定頁,這里會跳轉到下載頁;
<a href="intent://loin#Intent;scheme=ftnn;package=cn.futu.trader;category=android.intent.category.DEFAULT;action=android.intent.action.VIEW;S.browser_fallback_url=http%3A%2F%2Fa.app.qq.com%2Fo%2Fsimple.jsp%3Fpkgname%3Dcn.futu.trader%26g_f%3D991653;end">打開登錄頁</a>
Universal links
Universal links為 iOS 9 上一個所謂 通用鏈接 的深層鏈接特性,一種能夠方便的通過傳統 HTTP 鏈接來啟動 APP, 使用相同的網址打開網站和 APP;通過唯一的網址, 就可以鏈接一個特定的視圖到你的 APP 里面, 不需要特別的 schema;
在IOS中,對比schema的方式,Universal links有以下優點:
-
通過schema啟動app時,瀏覽器會有彈出確認框提示用戶是否打開,而Universal links不會提示,體驗更好;
-
Universal link可在再微信瀏覽器中打開外部App;
網易新聞客戶端IOS 9上目前采用這種Universal links方式
針對這部分內容可以參考博文:
由於公司IOS客戶端目前未實現這種協議,所以無法對這種喚醒方式做測試,日后明確支持此類協議,待測試功能后,再補充這部分詳細內容!
實現過程
首先,通過瀏覽器是無法判斷是否安裝了客戶端程序的,因此整體的思路就是:嘗試去通過上面的喚起方式來喚起本地客戶端,如果喚起超時,則直接跳轉到下載頁;整個實現過程圍繞這一點展開。
在不考慮IOS9 Universal links喚醒方式的條件下,可以分為這幾個步驟;
- 生成schema字符串
首先判斷瀏覽器UA,如果為Chrome for Android,則必須安裝 Android Intent的方式來組織schema字符串;如果為其他瀏覽器,則按照普通的schema方式來返回即可;
注意參數中包含的url地址需要進行encodeURIComponent編碼
2 .通過iframe或者a標簽來加載schema
由於無法確定是否安裝了客戶端,因此通過window.location = schema的方式可能導致瀏覽器跳轉到錯誤頁;所以通過iframe.src或a.href載入schema是目前比較常見的方法;
相比於iframe和a,通過設置其diaplay為none來進行隱藏,這樣即便鏈接錯誤也不會對當前頁構成影響,但是對於a標簽,在未安裝客戶端的情況下,仍然會存在提示訪問不存在的情況(比如opera),所以在選取上的優先級是:iframe>a>window.location,只有在iframe.href 無法調用schema的情況下,才采用a.href的方式。
經過非全面測試:
- Android系統上,Chrome for Android無法通過iframe.src 來調用schema,而通過a.href 的方式可以成功調用,而針對chrome內核的瀏覽器如獵豹,360,小米瀏覽器, opera對於iframe.src和a.href的方式都能支持,所以對chrome及先關的內核的瀏覽器采用a.href的方式來調用scheme;對於其他瀏覽器,如UC,firefox,mobile QQ,sogou瀏覽器則采用iframe.src的方式調用schema。對於微信瀏覽器,則直接跳轉到下載頁。其他未經測試的瀏覽器,默認采用iframe.src來調用schema;
- IOS 9系統上,Safari瀏覽器無法通過iframe.src的方式調用schema,對於UC,Chrome,百度瀏覽器,mobileQQ只能通過a.href的方式進行調用schema;對於微信瀏覽器,默認跳轉到下載頁;
代碼如下:
3 .處理客戶端未安裝的情況
前面提到無法確定客戶端程序是否安裝,所以在通過iframe和a調用schema時,會設置一個settimeout,超時,則跳轉到下載頁;
此處的超時時間設置也十分關鍵,如果超時時間小於app啟動時間,則未待app啟動,就是執行setimeout的方法,如果超時時間較長,則當客戶端程序未安裝時,需要較長時間才能執行settimeout方法進入下載頁。
代碼中,進入到setimeout時,對跳轉過程再次進行了限定;當瀏覽器因為啟動app而切換到后台時,settimeout存在計時推遲或延遲的問題,此時,如果從app切換回瀏覽器端,則執行跳轉代碼時經歷的時間應該大於setimeout所設置的時間;反之,如果本地客戶端程序未安裝,瀏覽器則不會進入后台程序,定時器則會准時執行,故應該跳轉到下載頁!
在實際測試過程,當通過schema成功喚起客戶端,再次返回瀏覽器時,發現頁面已跳轉至下載頁面,因此對已設置的settimeout需要做一個清除處理;
當本地app被喚起,app處於設備可視窗口最上層,則瀏覽器進入后台程序頁面會隱藏掉,會觸發pagehide與visibilitychange事件,此時應該清除setimeout事件,於此同時,document.hide屬性為true,因此setimeout內也不做跳轉動作,防止頁面跳轉至下載頁面; 此時,有幾個事件比較關鍵:
pagehide: 頁面隱藏時觸發
visibilitychange: 頁面隱藏沒有在當前顯示時觸發,比如切換tab,也會觸發該事件
document.hidden 當頁面隱藏時,該值為true,顯示時為false
為了盡可能的兼容多的瀏覽器,所以講這幾個事件都進行綁定! 代碼如下。
測試結果
-
Android平台(小米3 手機測試)
- 經測試,可喚起chrome,Firefox,uc,360,mibrowser,sogou,liebao,mobileQQ瀏覽器;
- 新版opera瀏覽器采用webkit內核,但是當客戶端未安裝時跳轉下載頁會會出錯,提示頁面不存在;
- 微信不支持登陸,直接做了跳轉到下載頁處理;
- Android上啟動相對比較慢,導致很容易啟動超時而跳轉到下載頁面;
- 測試頁面在本機,百度瀏覽器會上報檢測url合法性,導致喚醒不成功
2 . IOS平台(ip4,ip6+,ipad mini2)
- os7上Safari可用,其他瀏覽器為測試,條件限制;
- Safari,UC瀏覽器,Chrome 瀏覽器能喚起nn客戶端,但是Safari會有 是否打開的提示;
- QQ webviwe上能打開,偶爾會失敗;
- IOS上啟動速度相對較快
相關代碼
對代碼進行簡單的封裝,代碼如下,在使用時需要針對當前的app做必要設置,采用UMD的寫法:
調用方式:
// COMMONJS 的方式引用,不能直接在瀏覽器中運行,需要打包轉換
var nativeSchema = require("tool-nativeSchema.js");
// Amd的方式
require(["tool-nativeSchema.js"],function(nativeSchema){
});
// 直接引入
<script type="text/javascript" src="xxxx/tool-nativeSchema.js"></script>
// 使用
nativeSchema.loadSchema({
// 某個schema協議,例如login,
schema: "",
//schema頭協議,
protocal:"xxx",
//發起喚醒請求后,會等待loadWaiting時間,超時則跳轉到failUrl,默認3000ms
loadWaiting:"3000",
//喚起失敗時的跳轉鏈接,默認跳轉到應用商店下載頁
failUrl:"xxx",
// Android 客戶端信息,可以詢問 Android同事
apkInfo:{
PKG:"",
CATEGORY:"",
ACTION:""
}
});
研究意義
便於通過相關H5頁面進入Native客戶端,提升用戶體驗,提升App用戶粘度; 對於未安裝客戶端的用戶,可引導進入下載通道,如下場景圖:
存在的問題
- 在沒有安裝客戶端程序的時候,opera無法跳轉到指定頁的失敗頁;
- 通過微信喚醒客戶端目前不可行,Android上需要微信設置白名單;IOS上,需要微信設置白名單或者通過Universal links(IOS9+)協議;
- 尚未對IOS9的 Universal links協議進行功能測試。
- 代碼中使用的各種時間如:settimeout定時時間均根據本機測試進行的調整,普遍性需要進一步驗證
最后
- 經過自行測試及網上查閱資料,目前尚未找到完美的解決方案;
- 對於文中的不足和錯誤,歡迎指出。
- 轉載請說明出處,以方便追本溯源修正文中錯誤
相關閱讀鏈接
- https://developer.chrome.com/multidevice/android/intents
- https://segmentfault.com/a/1190000005848133?_ea=938555
- http://www.w3ctech.com/topic/287?utm_source=tuicool&utm_medium=referral
- http://blog.html5funny.com/2015/06/19/open-app-from-mobile-web-browser-or-webview/
- http://echozq.github.io/echo-blog/2015/11/13/callapp.html