重點摘要
Universal Links(iOS)與 App Links(Android)讓一般的 https 網址,在已安裝 APP 時直接開啟 APP 的指定頁面,未安裝時開啟網站,比自訂的 URL Scheme 更安全、相容性更好。
兩者都要在網站上放一個驗證檔,證明網域與 APP 屬於同一個擁有者;最常見的失效原因就出在這個檔案。
Android 最常見的錯誤是使用了錯誤的簽章指紋:上架 Google Play 時,要用 Play Console 上的「應用程式簽署金鑰」指紋。
在 LINE、Facebook 等 APP 的內建瀏覽器中點擊連結,常常不會開啟 APP,需要另外設計引導方式。
Deep Link 的基本概念可參考Deep Link 是什麼。實作時,常見的方式有三種:
方式 | 網址樣子 | 未安裝 APP 時 | 適合 |
|---|---|---|---|
URL Scheme |
| 無法開啟,可能顯示錯誤 | APP 之間互相呼叫、內部測試 |
Universal Links(iOS) |
| 開啟網站對應的頁面 | 行銷連結、Email、推播、分享 |
App Links(Android) |
| 開啟網站對應的頁面 | 行銷連結、Email、推播、分享 |
URL Scheme 任何 APP 都能註冊同一個名稱,有被冒用的風險;Universal Links 與 App Links 需要驗證網域,只有網域擁有者的 APP 能接手,是對外連結的建議做法。
要讓系統知道「這個網址可以交給這個 APP 開啟」,需要兩邊都宣告:
APP 端宣告要處理哪些網域的連結。
網站端在固定位置放一個驗證檔,列出允許開啟的 APP。
系統會去網站下載驗證檔,兩邊對得上,點擊連結時才會直接開啟 APP。
在 Apple Developer 後台與 Xcode 中,為 APP 啟用 Associated Domains,加入 applinks:example.com。
在網站的 https://example.com/.well-known/apple-app-site-association 放置驗證檔(沒有副檔名),內容為 JSON。
在驗證檔中指定 APP 的識別碼與要處理的路徑。
在 APP 中處理收到的網址,導向對應的畫面。
{
"applinks": {
"details": [
{
"appIDs": ["ABCDE12345.com.example.app"],
"components": [
{ "/": "/product/*" },
{ "/": "/order/*" }
]
}
]
}
}appIDs 由 Team ID 與 APP 的 Bundle ID 組成。只列出真正要交給 APP 處理的路徑,其他路徑維持在網站開啟。
在 APP 的 AndroidManifest 中,為要處理的網址加上 intent filter,並設定 android:autoVerify="true"。
在網站的 https://example.com/.well-known/assetlinks.json 放置驗證檔。
在驗證檔中填入 APP 的套件名稱與簽章的 SHA-256 指紋。
在 APP 中處理收到的網址,導向對應的畫面。
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": ["AA:BB:CC:…"]
}
}
]使用 Google Play 應用程式簽署時,上架的 APP 是由 Google 重新簽署的,指紋要填 Play Console 中「應用程式簽署金鑰」的值,而不是開發者本機的上傳金鑰。開發版與正式版的指紋不同,可以同時列在陣列中。
React Native 開發的 APP,Universal Links 與 App Links 的設定仍在 iOS 與 Android 的原生專案中完成;使用 Expo 時,可以在設定檔中宣告網域與 intent filter,建置時自動產生。收到網址後的頁面導向,則由跨平台的路由統一處理。
項目 | 要求 |
|---|---|
網址 | 必須是 HTTPS,路徑固定在 |
重新導向 | 驗證檔不能經過任何重新導向,例如 http 轉 https、裸網域轉 www |
回應內容 | 直接回傳 JSON,不能是網站的 404 頁面或登入頁 |
防火牆與 CDN | 不能被資安規則或機器人防護擋下,Apple 與 Google 的伺服器要能讀取 |
多個網域 | 每個網域、子網域都要各自放驗證檔 |
Apple 會透過自己的 CDN 快取驗證檔,修改後不一定立即生效,安排上架時程時要預留時間。
情況 | 原因與處理 |
|---|---|
在 LINE、Facebook 等 APP 內點擊沒反應 | 這些 APP 的內建瀏覽器常常不觸發 Universal Links,可以在頁面上加「在 APP 中開啟」的按鈕,或引導使用者用外部瀏覽器開啟,相關限制可參考手機 WebView 常見問題 |
直接在 Safari 網址列輸入網址 | 使用者主動輸入網址時,系統會停留在瀏覽器,這是預期行為 |
以前能開,現在都開在瀏覽器 | 使用者曾選擇「在瀏覽器中開啟」,系統記住了偏好;可長按連結改回在 APP 中開啟 |
Android 跳出選擇器,詢問要用哪個 APP | 網域驗證沒有通過,通常是指紋錯誤或驗證檔無法讀取 |
同網域的頁面內連結不會開 APP | 在同一個網域內點擊連結,iOS 會留在瀏覽器;導流用的連結可以放在不同的子網域 |
使用者還沒安裝 APP 時,理想的流程是:點擊連結 → 前往商店安裝 → 第一次開啟就進到原本要看的頁面,這稱為延遲深層連結(Deferred Deep Link)。這需要在安裝前後傳遞資訊,Universal Links 與 App Links 本身不提供,通常透過第三方歸因服務或自行開發的機制實現。過去常用的 Firebase Dynamic Links 已停止服務,仍在使用的專案需要改用其他方案。
Universal Links 和 App Links 可以用同一個網址嗎?
可以,而且建議這樣做。同一個 https 網址在 iOS 開啟 APP、在 Android 開啟 APP、在電腦或未安裝時開啟網站,行銷與分享只需要一組連結。
驗證檔放好了,為什麼還是開不了 APP?
最常見的原因依序是:驗證檔有重新導向或回傳錯誤內容、Android 指紋使用了上傳金鑰而非應用程式簽署金鑰、APP 端的網域宣告與驗證檔不一致。可以先用瀏覽器直接開啟驗證檔網址,確認回傳的是正確的 JSON。
推播通知可以用 Deep Link 導到指定頁面嗎?
可以。推播的內容帶上對應的網址或路徑,使用者點擊後由 APP 解析並導向指定畫面,例如訂單詳情、活動頁面。
LINE 裡面分享的連結要怎麼開啟 APP?
LINE 的內建瀏覽器常常不會觸發 Universal Links。常見做法是讓網頁偵測內建瀏覽器,顯示「在 APP 中開啟」的按鈕,或提示使用者改用外部瀏覽器開啟。
Universal Links 與 App Links 的設定步驟不多,但牽涉 APP、網站、伺服器三方,任何一處不一致都會失效。上線前用正式版 APP、在實際會分享連結的管道逐一測試,是避免問題最直接的方法。推播導流的設計可參考多管道通知,APP 的整體開發可參考跨平台 APP 開發。