一、需求描述
寫這篇文章,也是緣于運營的一個需求:在 App 運營過程中,會有大量的推廣短信,里面附有鏈接,目的是引導(dǎo)用戶參與活動。如果用戶手機(jī)沒有安裝我們的 App 就引導(dǎo)其去下載頁,如果用戶已經(jīng)安裝了我們的 App 就直接在 App 中打開對應(yīng)的活動。
二、方案討論
對需求進(jìn)行分析,歸納起來實際上就是一個問題,如何從短信喚起App?
這里有兩種方案。
第一種,也是最理想的直接從短信喚起,也就是點擊短信中的鏈接后如果安裝了 App 就跳轉(zhuǎn)到 App,如果沒有安裝就在瀏覽器打開對應(yīng)頁面,如下圖:

第二種,經(jīng)瀏覽器中轉(zhuǎn)喚起,也就是點擊短信鏈接后先用瀏覽器打開對應(yīng)頁面,在頁面中進(jìn)行“判斷”(實際上不是真正的判斷,而是發(fā)一個scheme給系統(tǒng))如果安裝了 App 就跳轉(zhuǎn)到 App,否則就停留在當(dāng)前頁。

下面將對這兩種方案分別進(jìn)行分析、實施。
三、從短信直接喚起 App
通常,App 監(jiān)聽私有短域名strange.com(不要問我為什么是短域名,因為短信就是按字算錢的,能省一分是一分)地址:
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="strange.com"
android:pathPattern=".*"
android:scheme="https"/>
<data
android:host="strange.com"
android:pathPattern=".*"
android:scheme="http"/>
</intent-filter>
3.1、Android 系統(tǒng)
當(dāng)點擊短信中的鏈接后,系統(tǒng)會自行判斷,如果安裝了 App 就會出一個彈框讓用戶選擇在 App 中打開還是在瀏覽器中打開,如圖。

對用戶來說要多做一次選擇,這絕對不是好的體驗。
為了解決這個問題,Android 6.0 開始支持 Deep Links,讓用戶點擊鏈接直達(dá) App。
首先,在 intent-filter 中添加 android:autoVerify="true"。
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="strange.com"
android:scheme="https"/>
</intent-filter>
其次,在私有域下上傳一個 json 文件:
https://strange.com/.well-known/assetlinks.json
文件內(nèi)容:
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "應(yīng)用ID",
"sha256_cert_fingerprints":["簽名證書指紋"]
}
}
]
系統(tǒng)在安裝應(yīng)用后會自動訪問 json 文件進(jìn)行檢驗,如果檢驗通過,用戶訪問 strange.com 域名下的鏈接會直接跳轉(zhuǎn)到應(yīng)用。
3.2、iOS 系統(tǒng)
必須采用 Universal Links,否則點擊還是直接跳轉(zhuǎn)到瀏覽器。
從短信直接喚起 App 總結(jié):
要實現(xiàn)短信直接喚起 App,Android 可以用 intent-filter 對域名進(jìn)行監(jiān)聽,但是會出彈框讓用戶進(jìn)行選擇,為了更好的體驗,建議采用 Deep Links 技術(shù)方案,只支持 6.0 以上系統(tǒng);iOS 只能采用 Universal Links 技術(shù)方案,只支持 9.0 以上系統(tǒng)。
| 系統(tǒng) | 首選方案 | 備選方案 |
|---|---|---|
| Android | Deep Links(Android 6.0+) | intent-filter |
| iOS | Universal Links(iOS 9.0+) | 無,只能跳瀏覽器 |
四、經(jīng)瀏覽器中轉(zhuǎn)喚起 App
上表所示,如果只能用備選方案,那么用戶就有可能會首先跳轉(zhuǎn)到瀏覽器(對應(yīng)的是下載頁面),經(jīng)過瀏覽器中轉(zhuǎn),喚起 App。
通常的做法是,App 中監(jiān)聽 scheme strange:
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<action android:name="android.intent.action.VIEW"/>
<data android:scheme="strange"/>
</intent-filter>
H5 頁面中內(nèi)嵌:
<iframe src="strange://login" style="display: none;"></iframe>
或者執(zhí)行腳本:
window.location.href="strange://login"
因為瀏覽器只會處理http、https協(xié)議,當(dāng)瀏覽器打開我們的 H5 下載頁面遇到不能處理的私有協(xié)議 strange,就會發(fā) intent 給系統(tǒng),如果有 App 可以處理這個協(xié)議會出彈框詢問用戶是否用該 App 打開,否則什么都不做,具體效果:

雖然彈框體驗欠缺,不過也是目前比較好的方案了。
兼容性問題
可是,重點來了,我們在實際測試過程中發(fā)現(xiàn)了一堆兼容性問題,在說明這些兼容性問題前,我們先解釋一個概念:intent:// 協(xié)議。
Android Chrome 25+ 后已經(jīng)不支持自定義 scheme 的方式,只支持 intent:// 協(xié)議(Android Intents with Chrome),最終要的是需要用戶手動進(jìn)行 點擊 才能跳轉(zhuǎn),舉個例子:
<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>
<iframe href="intent://xxx" style="display: none;">></iframe>// 失效
<iframe href="strange://xxx" style="display: none;">></iframe>// 失效
intent:// 協(xié)議格式說明:
intent:
//scan/
#Intent;
package=com.google.zxing.client.android;
scheme=zxing;
end;
目前市面上大多第三方瀏覽器都是基于 Chrome 開發(fā),這就帶來了兼容性問題(沒有條件覆蓋所有的系統(tǒng)瀏覽器,這里只是有限測試的結(jié)果):

1、部分瀏覽器,只支持
intent:// 協(xié)議 手動 喚起,如chrome、錘子。
2、部分瀏覽器只支持 scheme 喚起,如 UC 瀏覽器。
3、大部分瀏覽器,同時支持 scheme 私有協(xié)議和intent:// 協(xié)議 自動 喚起。但,都沒有按標(biāo)準(zhǔn)的 intent:// 協(xié)議來實現(xiàn)(除了 360 瀏覽器,給 360 點個贊):
- 有的瀏覽器在 App 沒安裝時并沒有執(zhí)行
S.browser_fallback_url,而是跳轉(zhuǎn)到應(yīng)用市場如獵豹瀏覽器 4.46.3、樂視瀏覽器 1.2.1.29。 - 有的瀏覽器不支持
S.browser_fallback_url如搜狗瀏覽器、歐朋瀏覽器、獵豹瀏覽器。 - 有的瀏覽器無論應(yīng)用有無安裝
S.browser_fallback_url一直都會執(zhí)行如 QQ 瀏覽器。
所以對這部分瀏覽器,不能使用 intent:// 協(xié)議。
4、更奇葩者,二者都不支持,如百度瀏覽器。
兼容性問題解決方案
針對上述三個兼容性問題,第 4 種情況無解我們直接忽略,第 2 第 3 種情況只能用自定義 scheme 的方式。
問題出在第 1 種情況,因為只能手動喚起,我們需要對瀏覽器類型進(jìn)行判斷(瀏覽器沒有提供是否支持自定義 scheme、intent://的 API 只能通過 UA 判斷),結(jié)合我們有限的測試結(jié)果,如果是錘子、Chrome 原生瀏覽器,需在頁面中內(nèi)置一個“下載應(yīng)用”的按鈕引導(dǎo)用戶點擊。
// 如果安裝了 App 就跳轉(zhuǎn) strange://login,否則就訪問 S.browser_fallback_url 的值 http://strange.com
<a href="intent://login#Intent;scheme=strange;package=com.strange;S.browser_fallback_url=http%3A%2F%2Fstrange.com;end">跳轉(zhuǎn)到活動頁/下載</a>
我們來分析一下瀏覽器的 UA ,舉幾個例子:
//小米系統(tǒng)瀏覽器
User-Agent:Mozilla/5.0 (Linux; U; Android 6.0.1; zh-cn; MI 3W Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/8.9.5
// 小米 Chrome 原生瀏覽器
User-Agent:Mozilla/5.0 (Linux; Android 6.0.1; MI 3W Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.108 Mobile Safari/537.36
// 錘子系統(tǒng)瀏覽器
User-Agent:Mozilla/5.0 (Linux; Android 5.1.1; YQ603 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.11 Mobile Safari/537.36
// 錘子 Chrome 原生瀏覽器
User-Agent:Mozilla/5.0 (Linux; Android 5.1.1; YQ603 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.89 Mobile Safari/537.36
可以看出小米瀏覽器是在 Chrome 原生瀏覽器的 UA 上增加了 XiaoMi/MiuiBrowser/8.9.5 這部分特征碼。類似的,很多第三方瀏覽器都是在 Chrome 基礎(chǔ)上增加自己的特征碼,換句話說 Chrome 原生瀏覽器 UA 沒有自己的特征。
而錘子系統(tǒng)瀏覽器和 Chrome 原生瀏覽器 UA 幾乎一樣,這就使得判斷是否錘子系統(tǒng)瀏覽器、 Chrome 原生瀏覽器 變得異常困難,要想盡可能完美解決問題只能使用排除法。
排除法由于不可能排除所有非 Chrome 原生瀏覽器,可能會存在誤傷的可能。
經(jīng)瀏覽器中轉(zhuǎn)喚起 App 總結(jié):
要實現(xiàn)經(jīng)瀏覽器中轉(zhuǎn) 自動 喚起 App,Android 和 iOS 都可以通過 自定義 scheme 的方式,但 Android 的情況稍顯復(fù)雜,因為部分瀏覽器并不支持,必須換成 intent:// 協(xié)議的方式 手動 喚起。
考慮到瀏覽器判斷的難度,結(jié)合瀏覽器市場占有率的情況,我們最終的方案是暫時忽略 錘子系統(tǒng)瀏覽器、 Chrome 原生瀏覽器 這部分不支持 自定義 scheme 自動喚起 ?App 的用戶。
五、從短信喚起 App 最終方案
綜合起來就是:
- 通過 Deep Links(iOS 則是Universal Links),可以實現(xiàn)點擊短信鏈接直接喚起 App;
- 如果系統(tǒng)因為各種原因不支持 Deep Links,備選方案是
intent filter,不過會出彈框讓用戶選擇用哪個 App 打開鏈接; - 如果用戶沒有選擇我們的 App 而是選擇了瀏覽器打開,則通過
自定義 scheme嘗試喚起 App; - 由于技術(shù)和成本問題,我們忽略不支持
自定義 scheme的瀏覽器。
如下圖所示:

引用
[1] Handling App Links
[2] Support Universal Links
[3] 手機(jī) User-Agent 大全
[4] 手機(jī)瀏覽器 User-Agent