H5喚起APP進行分享
最近很久沒有寫blog和note,倒是過家家的開發日誌簡單草草寫了一點。這次記錄下這個學習過程
由來
我們的 "通達有你",web h5頁面的分享功能體驗太差了,我一直想改變提高體驗度。
通常點分享然後跳轉到另一個頁面,比如QQ、空間、微博,還有微信。微信通常要掃二維碼分享,(我們只有一個手機啊,還要再屏幕上掃二維碼,通常要是我是嘗試分享者,微信這麼麻煩的分享我肯定是不會繼續分享了)
所以剛有空我就想試試更好的方法
疑問?
然後我平時留意幾大互聯網的巨頭的h5頁面,他也是可以進行APP喚起的,這到底是怎麼做到的?
不過這種情況分爲兩種:
-
喚起自己產品的APP
-
喚起第三方APP
image
image
而我的目的是第二種,我們是要喚起第三方APP進行分享
分析實現方式
經過我 面向搜索引擎 的一頓操作,瞭解到一些資料和方式,其中要實現在h5喚起APP的主要採用
- URL Scheme | Intent | Universal Link(也稱:深度鏈接)
- 通過瀏覽器的內置native分享接口
URLScheme
URL Scheme 是什麼
我們來看一下 URL 的組成:
[scheme:][//authority][path][?query][#fragment]
我們拿 https://www.baidu.com
來舉例,scheme 自然就是 https
了。
就像給服務器資源分配一個 URL,以便我們去訪問它一樣,我們同樣也可以給手機APP分配一個特殊格式的 URL,用來訪問這個APP或者這個APP中的某個功能(來實現通信)。APP得有一個標識,好讓我們可以定位到它,它就是 URL 的 Scheme 部分。
常用APP的 URL Scheme
APP | 微信 | 支付寶 | 淘寶 | 微博 | 知乎 | 短信 | |
---|---|---|---|---|---|---|---|
URL Scheme | weixin:// | alipay:// | taobao:// | sinaweibo:// | mqq:// | zhihu:// | sms:// |
URL Scheme 語法
上面表格中都是最簡單的用於打開 APP 的 URL Scheme,下面纔是我們常用的 URL Scheme 格式:
行爲(應用的某個功能)
|
scheme://[path][?query]
| |
應用標識 功能需要的參數
蒐集到的常用Scheme
應用名稱 | URL Scheme |
---|---|
微博 | weibo:// |
mqq:// | |
QQ羣組 | mqqapi://card/show_pslcard?src_type=internal&version=1&card_type=group&uin={QQ羣號} |
QQ聯繫人 | mqqapi://card/show_pslcard?src_type=internal&version=1&uin={QQ號碼} |
支付寶 | alipay:// |
微信 | weixin:// |
微信 | wechat:// |
微信-掃一掃 | weixin://dl/scan |
微信-反饋 | weixin://dl/feedback |
微信-朋友圈 | weixin://dl/moments |
微信-設置 | weixin://dl/settings |
微信-消息通知設置 | weixin://dl/notifications |
微信-聊天設置 | weixin://dl/chat |
微信-通用設置 | weixin://dl/general |
微信-公衆號 | weixin://dl/officialaccounts |
微信-遊戲 | weixin://dl/games |
微信-幫助 | weixin://dl/help |
微信-反饋 | weixin://dl/feedback |
微信-個人信息 | weixin://dl/profile |
微信-功能插件 | weixin://dl/features |
蝦米音樂 | xiami:// |
chrome | googlechrome:// |
微博國際版 | weibointernational:// |
摩拜單車 | mobike:// |
ofo | ofoapp:// |
有道雲筆記 | youdaonote:// |
印象筆記 | evernote:// |
今日頭條 | snssdk141:// |
網易新聞 | newsapp:// |
網易雲音樂 | orpheuswidget:// |
QQ音樂 | qqmusic:// |
QQ音樂最近播放 | qqmusic://today?mid=31&k1=2&k4=0 |
美團外賣 | meituanwaimai:// |
美團 | imeituan:// |
Gmail | googlegmail:// |
網易郵箱 | neteasemail:// |
QQ郵箱 | qqmail:// |
騰訊視頻 | tenvideo:// |
愛奇藝 | iqiyi:// |
12306 | cn.12306:// |
有道詞典 | yddict:// |
釘釘 | dingtalk:// |
我進入深坑
看到上面這些資料的我,思考了很久如何去找具體的path和query部分。如果能找到這兩塊的詳細參數,那麼我們就可以在APP間相互調用和傳參了,就和普通URL一樣了
但是,我尋找了好久,或許是我不懂這裏面的方式吧,或許是我也不太懂Android方面的知識,就是沒人在網上提及到具體的path和query,
後來想想,也是挺正常的,大多網站和企業只是想喚起自己的APP,那如何使用這些URL Scheme呢
大坑
先預告一下還有比較大的坑就是,scheme的觸發方式會被瀏覽器攔截,如果是QQ和微信自帶的內置瀏覽器,使用Scheme是無效的,除非是自家人或者在它的白名單內(比如幾大巨頭),這就導致瞭如果你在QQ和微信內點擊網頁內的分享,不好意思,啥用沒有。。。不過可以做個遮罩層用他們內置瀏覽器的右上角分享功能。
-
微信、微博、手百、QQ瀏覽器等。
這些應用能阻止喚端是因爲它們直接屏蔽掉了 URL Scheme 。接下來可能就有看官疑惑了,微信中是可以打開大衆點評的呀,微博裏面可以打開優酷呀,那是如何實現的呢?
它們都各自維護着一個白名單,如果你的域名在白名單內,那這個域名下所有的頁面發起的 URL Scheme 就都會被允許。就像微信,如果你是騰訊的“家屬”,你就可以加入白名單了,微信的白名單一般只包含着“家屬”,除此外很難申請到白名單資質。但是微博之類的都是可以聯繫他們的渠道童鞋進行申請的,只是條件各不相同,比如微博的就是在你的 APP 中添加打開微博的入口,三個月內喚起超過 100w 次,就可以加入白名單了。
-
騰訊應用寶直接打開 APP 的某個功能
剛剛我們說到,如果你不是微信的家屬,那你是很難進入白名單的,所以在安卓中我們一般都是直接打開騰訊應用寶,ios 中 直接打開 App Store。點擊騰訊應用寶中的“打開”按鈕,可以直接喚起我們的 APP,但是無法打開 APP 中的某個功能(就是無法打開指定頁面)。
騰訊應用寶對外開放了一個叫做 APP Link 的申請,只要你申請了 APP Link,就可以通過在打開應用寶的時候在應用寶地址後面添加上
&android_schema={your_scheme}
,來打開指定的頁面了。
感覺騰訊應用寶是個做文章的很地方,沒準之後會嘗試下
瀏覽器的內置分享原生分享
瀏覽器自帶有分享到微信和QQ的功能,但不是每個都提供接口來供網頁調用。即使有提供,瀏覽器暴露的api不一樣,各家有各家的規則和方式。
但好在網上找到了兩個前輩造的輪子NativeShare和uc-qq-share-to-wechat ,也都是調用各個瀏覽器的原生分享功能,但前者裏面我還看到了部分Scheme的方式。
主要的瀏覽器有:
- QQ瀏覽器
- UC瀏覽器
- 微信自帶瀏覽器
- QQ自帶瀏覽器
- QQ空間APP
- 百度瀏覽器
- 百度APP自帶瀏覽器
- ios 搜狗瀏覽器
- Safari瀏覽器
- 其他
觸發方式
現在來說說觸發方式,大致上有三種:
iframe方案
<iframe src="sinaweibo://qrcode">
在未安裝 app 的情況下,不會去跳轉錯誤頁面。但是 iframe 在各個系統以及各個應用中的兼容問題還是挺多的,我自己並沒有使用這種。
var last = Date.now(),
doc = window.document,
ifr = doc.createElement('iframe');
//創建一個隱藏的iframe
ifr.src = nativeUrl;
ifr.style.cssText = 'display:none;border:0;width:0;height:0;';
doc.body.appendChild(ifr);
setTimeout(function() {
doc.body.removeChild(ifr);
//setTimeout回小於2000一般爲喚起失敗
if (Date.now() - last < 2000) {
if (typeof onFail == 'function') {
onFail();
} else {
//彈窗提示或下載處理等
}
} else {
if (typeof onSuccess == 'function') {
onSuccess();
}
}
}, 1000);
iframe方案的喚起原理是: 程序切換到後臺時,計時器會被推遲(計時器不準的又一種情況)。如果app被喚醒那麼網頁必然就進入了後臺,如果用戶從app切回來,那麼時間一般會超過2s;若app沒有被喚起,那麼網頁不會進入後臺,setTimeout基本準時觸發,那麼時間不會超過2s。
a標籤喚起
<a href="mqqapi://card/show_pslcard?src_type=internal&version=1&uin=123456">QQ臨時交流</a>
上面這個a標籤你可以自己嘗試一下,是可以直接喚起的,a標籤如果目標scheme錯誤,即應用不存在也不會報錯。
location.href跳轉
window.location.href = 'sinaweibo://qrcode';
我自己大多使用click的方式配合location來進行跳轉,自己沒有在各大平臺和各個瀏覽器版本上做太多實驗,在一個博文中看到
URL Scheme 在 ios 9+ 上諸如 safari、UC、QQ瀏覽器中, iframe 均無法成功喚起 APP,只能通過 window.location 才能成功喚端。
某篇博文中對三種喚起方式進行了測試
。X表示喚起失敗,√表示喚起成功
。紅色標記表示進入頁面直接喚起,綠色表示人工事件操作後喚起
。ios測試機:iphone 6p;android測試機:小米1s
iframe喚起app測試結果
圖片顯示
window.location.href喚起app測試結果
圖片顯示
a標籤喚起app測試結果
圖片顯示
iframe和window.location.href喚起對比
圖片顯示
iframe、window.location.href和a標籤喚起三者對比
圖片顯示
對比iframe喚起和location.href,我們可以發現:
- 對於ios來說,location.href跳轉更合適,因爲這種方式可以在Safari中成功喚起app。Safari作爲iphone默認瀏覽器其重要性就不用多說了,而對於微信和qq客戶端,ios中這兩種方式都沒有什麼卵用==
- 對於Android來說,在進入頁面直接喚起的情況下,iframe和location.href是一樣的,但是如果是事件驅動的喚起,iframe喚起的表現比location.href要更好一點。
- 通過測試可以發現,進入頁面直接喚起和事件驅動的喚起,對於很多瀏覽器,兩者的表現是不同的,簡單來說,直接喚起的失敗更多。
以上測試可能隨時間已經有出入和變化,僅供參考
選擇
看了這些資料後,開始動手對網站的分享功能再次二開,目前都是採用a標籤進行一個簡單的跳轉,去對應社交平臺的分享url的api接口提交各個參數。
image
嘗試
準備先引入大佬的NativeShare輪子,因爲我在他的在線demo嘗試了,我手機自帶瀏覽器、模擬器的自帶瀏覽器、模擬器的QQ瀏覽器,都可以很好的分享出來,於是首先引入他的方式。
思路
$(document).ready(function () {
$(".social-share-icon ").on("click",function (e) {
e.preventDefault();
shareHref = $(this).attr("href");
if ($(this).hasClass("icon-qq")){
call('qqFriend',shareHref);
}
})
})
對目前的各個a標籤,在dom加載完成時添加一個click事件,阻止a標籤的觸發,然後把href地址記錄下來。然後再去觸發相應的NativeShare中的call方法。
但是我發現在原生的瀏覽器裏面竟然沒觸發。。那就做個降級處理吧。
function call(command) {
try {
nativeShare.call(command)
} catch (err) {
// 在這裏寫降級處理的內容
alert(err.message)
}
}
在catch到拋出到異常後,自己在用原生的URL scheme 嘗試觸發,如果還是不能觸發,那就沒辦法咯~~
var url_scheme = '//share/to_fri?src_type=web&version=1&file_type=news&title=' + Base64.encode(shareData.title) + '&thirdAppDisplayName=5o6M5LiK55CG5bel5aSn&url=' + Base64.encode(shareData.link) + '&description=' + Base64.encode(shareData.desc);
location.assign('mqqapi:' + url_scheme)
setTimeout(function () {
location.assign('timapi:' + url_scheme)
}, 2000)
這個是我在網上找到的一個qq 分享的URL scheme,記得要base64處理下各個內容,還有個缺陷就是沒有icon了,圖片顯示不了了。
細節處理
剛剛都是說手機移動端訪問,如果要是電腦端訪問的話,還是觸發這個肯定不成功。所以在最開始要先判斷下ua。根據ua來做出下一步動作。簡單的放下ua判斷代碼
var browser = {
versions: function() {
var u = navigator.userAgent, app = navigator.appVersion;
return { //移動終端瀏覽器版本信息
trident: u.indexOf('Trident') > -1, //IE內核
presto: u.indexOf('Presto') > -1, //opera內核
webKit: u.indexOf('AppleWebKit') > -1, //蘋果、谷歌內核
gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐內核
mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否爲移動終端
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios終端
android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android終端或uc瀏覽器
iPhone: u.indexOf('iPhone') > -1, //是否爲iPhone或者QQHD瀏覽器
iPad: u.indexOf('iPad') > -1, //是否iPad
webApp: u.indexOf('Safari') == -1, //是否web應該程序,沒有頭部與底部
qq: u.indexOf('MQQBrowser') > -1,//QQ瀏覽器
uc: u.indexOf('UCBrowser') > -1// UC瀏覽器
};
} (),
language: (navigator.browserLanguage || navigator.language).toLowerCase()
}
// 先判斷是否是PC,如果是PC端 就直接使用鏈接來分享
if (browser.versions.mobile || browser.versions.android || browser.versions.ios){
// if (browser.versions.qq && command==='qqFriend' || command==='qZone'){
// throw new Error;
// }
nativeShare.call(command)
}else{
// 使用原鏈接分享
location.assign(e)
}
效果
最後測試了幾個瀏覽器分享效果
瀏覽器 | 華爲自帶 | X瀏覽器 | 模擬器自帶 | 模擬中QQ瀏覽器 | APK內置 |
---|---|---|---|---|---|
QQ好友 | N | Y | Y | Y | Y |
QQ空間 | N | Y | Y | Y | Y |
微信朋友圈 | Y | N | N | Y | N |
image
image
看來QQ瀏覽器果然通過原生的內置分享api都能達到分享喚起,但是在其他瀏覽器就有部分不兼容了。後面有需要在繼續調整優化吧,
Reference
H5喚起APP指南 https://suanmei.github.io/2018/08/23/h5_call_app/
h5喚起app http://echozq.github.io/echo-blog/2015/11/13/callapp.html
兼容是重點
作者:二歪求知iSk2y
鏈接:https://www.jianshu.com/p/500f4be528e3
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。