Flutter 實作 DeepLink 完整指南 ⎮ Part 2: Android 與 iOS 設定

Yii Chen
Flutter Taipei
Published in
20 min readJul 31, 2024

不可忽略的 Deep Link 體驗

在第一章中,我們介紹了 Deep Link 的基本觀念,並討論了它對行動應用的好處。快速了解深度連結在提升用戶體驗、改善行銷效果、簡化新用戶入門流程、獲得更佳分析數據以及與其他應用程式整合方面的作用。

在本章中,我們將深入 Android 和 iOS 應用程式的 Deep Link 設定。整理了每一步驟的細節說明,以確保大家在實作上可以輕鬆且無障礙的完成它們。

Android (Web Link)

使用 httphttps 兩種 scheme,稱為 App Links / In-app Links

互動流程

  1. 點擊 URI 連結
  2. 發出意圖 Intent
  3. Android System
  4. 發出意圖 Intent
  5. Flutter MainActivity
  6. Flutter App

前置作業

  • AndroidManifest.xml 需要設定 URI 以處理 Deep Link,Flutter 針對指定 URI 開啟 APP
  • 資源驗證檔案 assetlinks.json 需要放置在 domain server 上

專案設置與流程

首先開啟 AndroidManifest.xml 檔案

1️⃣ 新增 <meta-data>

設置 flutter_deeplinking_enabled,代表允許 Flutter 可以處理 Deep Link,valuetrue

<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />

2️⃣ 新增 <intent-filter>

處理 URI Intent,啟動畫面,autoVerifytrue,此設定代表可以略過開啟應用的選擇對話框,節省步驟後直接跳轉並啟動目標 APP。

當使用者安裝應用程式時,Android 會看到包含 autoVerify 屬性的 <intent-filter>,並查看 <data> 中指定URL下的驗證檔案,檢查是否包含目前當前 APP,如果包含,Android 就認為該網址已經過驗證,允許 APP 開啟 Web links 連結。

📍新增 <action> ,代表可執行的動作,其中 android.intent.action.VIEW,允許讓 Google 搜尋

📍新增 <category>,允許對隱性意圖為預設,android.intent.category.DEFAULT

📍新增 <category>,從網路瀏覽器可觸發意圖,android.intent.category.BROWSABLE

📍新增 <data>,可與 APP 或畫面互動的 Uri 設定

  • scheme → 通常為 httphttps,或是自定義的 scheme,例如:yii
  • hostdomain,例如:flutter.com
  • path → URI 路徑,例如:/users

請保持每一種 Domain 設定使用一個 <intent-filter>,提升準確性與可維護性,以下是範例:

<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:scheme="https" android:host="cat.example"/>
</intent-filter>

<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:scheme="https" android:host="vc.cat.example" android:path="/campaigns"/>
</intent-filter>

以幾種設置方式:

  1. 第一種 → host 給予完整路徑
<data
android:scheme="https"
android:host="vibz.cool" />

2. 第二種 → host 不包含後方的路徑,新增 pathPattern 來設置路徑

<data 
android:scheme="https"
android:host="vibz.cool"
android:pathPattern="/download"/>

3. 第三種 → 不同 Domain、host 請將他們分開,否則 path 相關設定會一起套用,導致後台檢驗時會納入混濁的格式。也可以同時提升可讀性

<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:scheme="https" android:host="vc.vibz.cool" android:pathPattern="/"/>
<data android:scheme="https" android:host="vc.vibz.cool" android:pathPattern="/campaigns"/>
</intent-filter>
<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:scheme="https" android:host="share.vibz.cool" android:pathPattern="/"/>
<data android:scheme="https" android:host="share.vibz.cool" android:pathPattern="/share" />
</intent-filter>

4. 第四種 → 動態路徑的配置,可使用 pathpathPrefix、和 pathPattern 表示

  • 添加一個 path,例如:/、/campaigns
  • 添加一個 pathPattern,後面給予 *,代表動態內容,可能是數字ID。例如:/campaigns/.* 可代表 /campaigns/100、/campaigns/play
  • 添加一個 pathPattern,支援路徑有部分變動。例如:/.*\\.html

例如,需要一個活動連結,點擊後直接跳轉到頁面。如果頁面路徑的後方需要帶入動態資訊,就需要額外設置一個 pathPattern,動態的部分給予 ..*,完成後連結才會正常運行。

有明確意義、類型的內容,最好定義指定路徑,新增階層式巢狀結構。可讓 intent-filter 明確指向,並且讓 Android 擷取到精確的網址

// Good
https:share.vibz.cool/campaigns/xxxxxx

// Avoid
https:share.vibz.cool/xxxxxx

實際 URI:https://share.vibz.cool/campaigns/dthm31/claim?openExternalBrowser=1&claim_code=bmljZQ==

<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:scheme="https" android:host="share.vibz.cool" android:pathPattern="/campaigns"/>
<data android:pathPattern="/campaigns/..*"/>
</intent-filter>

詳細的定義方式,可查看官方 https://developer.android.com/guide/topics/manifest/data-element?hl=zh-tw

3️⃣ launchMode 設置

在外部、第三方應用打開連結時,如果目標 APP 是在來源 APP 上呈現,可以在 AndroidManifest.xml 調整 launchModesingleTask,讓目標 APP 獨立出來。根據 launchMode 設定可以決定 APP 的運行模式。

驗證資源設置(Digital Asset Links)

主要目的是確保用戶在開啟網站連結後,打開設備裡對應的應用程式,而不是開啟一般網頁。

  • 讓應用程式知道可以處理哪種類型的 URL,確保網域將應用程式識別為可信任的
  • 應用和網域兩者之間需要建立關聯。您必須在 Domain 上儲存 assetlinks.json (Google Digital Asset Links) 檔案,才能進行驗證。
  • 驗證元素包含 URI、APP 簽名、package_name,透過它們證明是 Domain 擁有者,可以進行互動。避免其他應用劫持跳轉請求

Google DAL 是一種通訊協定和 API,定義其他應用程式和網站的可驗證資訊

sha256 證書指紋可透過 keytool CLI 取得,存取原本我們創建的 keystore 檔案

keytool -list -v -keystore <release-key>.keystore

或是直接從 Google Play Console 查看,如果有上傳並生成 Production App 簽名,就可以從 App signing 頁面找到。

接著直接從 Google Play Console 的 App signing 取得 assetlinks.json 內容,儲存下來後放置到 Server。

[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.yiichen.example",
"sha256_cert_fingerprints": [
"07:64:58:7A:F4:5C:04:16:D5:35:A7:1B:44:C7:98:84:DV:38:C5:8F:29:EC:6A:3A:A2:2A:FC:69:5B:BB:24:CA",
"2A:96:21:4D:A8:F1:D6:4D:AC:1A:B4:7D:68:F9:6C:EB:A1:9F:66:73:68:75:CE:DF:18:7D:4D:EA:0F:A3:AF:21",
]
}
}
]

請記住,此步驟僅適用於 Web links (HTTP/HTTPS Links),不適用於 Custom Scheme

💡 非必要的本地設置,如果需要從本地驗證 Web links 連結,可以取得 local debug 證書指紋,將它設置到 assetlinks.json 裡面,更新到 Server 上。

keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

Google Play Console / Deep links

快速瀏覽 App 中有設定的 Web links 資訊,包含 Domain 與詳細路徑

在 Web links 區塊中,如果有自定義的 scheme,Android 不會驗證所以會有錯誤訊息,但這部分可忽略。(後面會說明 Custom scheme link )

下方的 Custom schemes 會顯示我們自定義的名稱,這裡的狀態就會是正常的囉。有打勾也就代表連結可以使用,當用戶點擊後能跟 APP 互動

Android (Custom Link)

  • 自定義 Scheme 的連結,稱為 Deep Links。
  • scheme 的設置方式基本上都差不多,而設有自訂配置的連結是很常見的 DeepLink 類型,容易實作
  • 適合沒有網域的開發者,節省驗證的步驟。不過也代表第三方應用都能跟自家應用進行互動
<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:scheme="yii" android:host="cat.example" />
</intent-filter>

實際的連結:

yii://cat.example

iOS (Web Link)

使用 http 和 https 兩種 scheme,稱為 Universal Links

前置作業

  • 專案的 Associated Domains 需要設定 URI 以處理 Deep Link,讓 Flutter 針對指定 URI 格式開啟 APP
  • 放置驗證資源 apple-app-site-association 到 Domain Server,讓 APP 進行驗證,包含 Link details、APP ID、bundleID,證明 APP 是 Domain 互動對象,跟 Android 設定方式類似

專案設置與流程

  1. 首先開啟 info.plist 檔案,新增 FlutterDeepLinkingEnabled 為 true。代表開啟了Flutter DeepLink 功能

2. 針對每個執行環境,要設定 Associated Domains 互動連結,在 Runner → Signing & Capabilities 新增。請注意每個環境、設定檔都需要添加,確保在每個情境都能正常運作

3. 新增有 applinks: 開頭的連結設定,後面為 domain,假設 URL 為 https://vibz.cool,就改成 applinks:vibz.cool。將相關路徑都添加上去,一樣每個環境、模式都要設定完整

驗證資源設置

建立一個名為 apple-app-site-association 的檔案,內容通常包含 APP 資訊也有 Link 的相關路徑 。如果不限制路徑的情境下,主要調整 appIdpaths 兩個欄位。必須確保檔案為 application/json 格式,但是不需要給副檔名。

  1. appID → Apple Team ID 與 Bundle ID 組裝
  2. paths → 設置允許的指定路徑。也可以使用 * 表示全部或任意長度的字元,代表不需要過濾。? 可代表任意一個字元
  3. components → 非必要設置,可以提供完整的路徑資訊,包含路徑與相關描述,針對指定的部分才會處理
// 1.
{
"applinks": {
"apps": [],
"details": [
{
"appID": "SXX342XG9.com.yiichen.hello",
"paths": [
"*",
"/user/*",
],
"components":[
{
"/":"/sign-in",
"comment":"Let URL bring users to /sign-in page"
},
{
"/":"/profile/*",
"comment":"Let URL bring users to check the profile of someone"
},
]
}
]
}
}
// 2. Multiple APP exmaple
{
"applinks": {
"apps": [],
"details": [
{
"appID": "SDZ342XG9.com.yiichen.hello",
"paths": [
"*"
]
},
{
"appID": "ABC123456.com.yiichen.hello",
"paths": [
"/product/*"
]
}
]
}
}

Team ID 在 Apple Developer 的 account 頁面可以找到,查看 Membership details

將檔案編輯後放置到我們的網域路徑儲存,等待應用透過它進行驗證,以範例來看就是 https://vc.vibz.cool/,透過網址存取時就能直接查看到內容。

<https://vc.vibz.cool/.well-known/apple-app-site-association>

官方文件:https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html

Apple Developer Console 設置

針對產品的 BundleID 進行設定,包含每個 flavor 環境的身分證,勾選 Associated Domains,允許 APP 與連結進行互動。

iOS (Custom Link)

  • 自定義 URI Scheme,稱為 custom URL scheme。可選擇任何的 scheme,只要個人和團隊喜歡即可
  • 對於沒有網域、網站但想實現 DeepLink 的效果,那麼此方法非常方便

注意:

  1. 如果 APP 沒有安裝在設備,打開連結時就會顯示錯誤,不會像 Web Link 一樣開啟對應網頁
  2. 缺點是它不太安全,因為任何應用程式取得 scheme 後都可以嘗試打開你的連結,也就是 APP。當然大家也可以使用相同的 scheme

如果 APP 有自己的自定義 scheme 會需要以下的 Info.plist 設定。

  1. 新增一個 URL type
  2. 設置 CFBundleURLName,身分證
  3. 設置 CFBundleURLSchemes,自定義 scheme 名稱

Code:

<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>xyz.passion.vibz</string>
<key>CFBundleURLSchemes</key>
<array>
<string>vibz</string>
</array>
</dict>
</array>

也可以透過 Runner 的 Info 介面設定,新增 URL Type,將 IdentifierURL Schemes 補上即可。

以上步驟只有自定義方案才需要,如果是使用 Web links (HTTP/HTTPS Links) 則可忽略

Conclusion

在本文中我們了解 Android 和 iOS 的深度連結設定,在使用連結吸引用戶之前,這是很重要的前置工作。才能確保應用程式無縫引導使用者至正確的內容、有效推動轉化並培養忠實的用戶群。

第三章,即將進入重頭性,Flutter 開發階段。透過套件工具來協助 Deep Link 的實現。看過後你也覺得不難了!

--

--

Yii Chen
Flutter Taipei

Flutter Lover || Organizer FlutterTaipei || Writer, Speaker || wanna make Flutter strong in Taiwan. https://linktr.ee/yiichenhi