驗證應用程式連結

如果應用程式的意圖篩選器中至少有一個包含 android:autoVerify="true",在搭載 Android 6.0 (API 級別 23) 以上版本的裝置上安裝應用程式時,系統會自動驗證與應用程式意圖篩選器中網址相關聯的主機。在 Android 12 以上版本中,您也可以手動叫用驗證程序,測試驗證邏輯。

自動驗證

系統的自動驗證程序包括:

  1. 系統會檢查所有包含下列任一項目的意圖篩選器:
    • 動作:android.intent.action.VIEW
    • 類別:android.intent.category.BROWSABLEandroid.intent.category.DEFAULT
    • 資料結構定義:httphttps
  2. 針對上述意圖篩選器中找到的每個專屬主機名稱,Android 會在 https:///.well-known/assetlinks.json 查詢對應網站的 Digital Asset Links 檔案。

確認要與應用程式建立關聯的網站清單,並確認代管的 JSON 檔案有效後,請在裝置上安裝應用程式。請等待至少 20 秒,非同步驗證程序才會完成。使用下列指令,檢查系統是否已驗證您的應用程式,並設定正確的連結處理政策:

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d "http://domain.name:optional_port"

手動驗證

從 Android 12 開始,您可以手動為裝置上安裝的應用程式叫用網域驗證。無論應用程式是否指定 Android 12,您都可以執行這項程序。

建立網際網路連線

如要驗證網域,測試裝置必須連上網際網路。

支援更新後的網域驗證程序

如果應用程式指定 Android 12 以上版本,系統會自動使用更新後的網域驗證程序。

否則,您可以手動啟用更新後的驗證程序。如要這麼做,請在終端機視窗中執行下列指令:

adb shell am compat enable 175408749 PACKAGE_NAME

在裝置上重設 Android 應用程式連結的狀態

在裝置上手動叫用網域驗證前,請務必重設測試裝置上的 Android 應用程式連結狀態。方法是在終端機視窗中執行下列指令:

adb shell pm set-app-links --package PACKAGE_NAME 0 all

這項指令會將裝置恢復到使用者為任何網域選擇預設應用程式前的狀態。

啟動網域驗證程序

重設裝置上的 Android 應用程式連結狀態後,您就可以執行驗證。方法是在終端機視窗中執行下列指令:

adb shell pm verify-app-links --re-verify PACKAGE_NAME

查看驗證結果

驗證代理程式完成要求後,請查看驗證結果。如要進行這項操作,請執行下列指令:

adb shell pm get-app-links PACKAGE_NAME

這個指令會輸出類似以下的結果:

com.example.pkg:
    ID: 01234567-89ab-cdef-0123-456789abcdef
    Signatures: [***]
    Domain verification state:
      example.com: verified
      sub.example.com: legacy_failure
      example.net: verified
      example.org: 1026

成功通過驗證的網域,網域驗證狀態會顯示為 verified。如果顯示其他狀態,表示系統無法驗證網域。特別是 none 狀態,表示驗證代理人可能尚未完成驗證程序。

以下列出網域驗證可能為特定網域傳回的值:

none
尚未記錄這個網域的資料。請再等幾分鐘,讓驗證代理程式完成與網域驗證相關的要求,然後再次啟動網域驗證程序
verified
已成功驗證聲明應用程式的網域。
approved
網域已強制獲准,通常是透過執行殼層指令。
denied
網域遭到強制拒絕,通常是透過執行殼層指令。
migrated
系統保留了先前使用舊版網域驗證程序的結果。
restored
使用者還原資料後,網域已獲准。前提是網域先前已通過驗證。
legacy_failure
網域遭舊版驗證器拒絕。具體失敗原因不明。
system_configured
裝置設定自動核准了網域。
錯誤代碼大於或等於 1024

裝置驗證器專屬的自訂錯誤代碼。

建立網路連線,然後再次啟動網域驗證程序

要求使用者將應用程式與網域建立關聯

應用程式取得網域核准的另一種方式,是要求使用者將應用程式與該網域建立關聯。

檢查應用程式是否已獲准使用該網域

在提示使用者之前,請先檢查應用程式是否為 <intent-filter> 元素中定義網域的預設處理常式。您可以使用下列其中一種方法查詢核准狀態:

DomainVerificationManager

下列程式碼片段展示如何使用 DomainVerificationManager API:

Kotlin

val context: Context = TODO("Your activity or fragment's Context")
val manager = context.getSystemService(DomainVerificationManager::class.java)
val userState = manager.getDomainVerificationUserState(context.packageName)

// Domains that have passed Android App Links verification.
val verifiedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_VERIFIED }

// Domains that haven't passed Android App Links verification but that the user
// has associated with an app.
val selectedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_SELECTED }

// All other domains.
val unapprovedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_NONE }

Java

Context context = TODO("Your activity or fragment's Context");
DomainVerificationManager manager =
        context.getSystemService(DomainVerificationManager.class);
DomainVerificationUserState userState =
        manager.getDomainVerificationUserState(context.getPackageName());

Map<String, Integer> hostToStateMap = userState.getHostToStateMap();
List<String> verifiedDomains = new ArrayList<>();
List<String> selectedDomains = new ArrayList<>();
List<String> unapprovedDomains = new ArrayList<>();
for (String key : hostToStateMap.keySet()) {
    Integer stateValue = hostToStateMap.get(key);
    if (stateValue == DomainVerificationUserState.DOMAIN_STATE_VERIFIED) {
        // Domain has passed Android App Links verification.
        verifiedDomains.add(key);
    } else if (stateValue == DomainVerificationUserState.DOMAIN_STATE_SELECTED) {
        // Domain hasn't passed Android App Links verification, but the user has
        // associated it with an app.
        selectedDomains.add(key);
    } else {
        // All other domains.
        unapprovedDomains.add(key);
    }
}

指令列程式

在開發期間測試應用程式時,您可以執行下列指令,查詢貴機構擁有的網域驗證狀態:

adb shell pm get-app-links --user cur PACKAGE_NAME

在下列範例輸出中,即使應用程式未通過「example.org」網域的驗證,使用者 0 仍在系統設定中手動核准了該應用程式,且沒有其他套件通過該網域的驗證。

com.example.pkg:
ID: ***
Signatures: [***]
Domain verification state:
  example.com: verified
  example.net: verified
  example.org: 1026
User 0:
  Verification link handling allowed: true
  Selection state:
    Enabled:
      example.org
    Disabled:
      example.com
      example.net

您也可以使用殼層指令模擬使用者選取與特定網域相關聯應用程式的程序。如要查看這些指令的完整說明,請參閱 adb shell pm 的輸出內容。

提供要求背景資訊

提出網域核准要求前,請先向使用者說明情況。舉例來說,您可以向使用者顯示啟動畫面、對話方塊或類似的 UI 元素,說明應用程式應成為特定網域的預設處理常式。

提出要求

使用者瞭解應用程式要求執行的動作後,再提出要求。 如要執行此操作,請叫用含有 ACTION_APP_OPEN_BY_DEFAULT_SETTINGS 意圖動作的意圖,以及與目標應用程式的 package:com.example.pkg 相符的資料字串,如以下程式碼片段所示:

Kotlin

val context: Context = TODO("Your activity or fragment's Context")
val intent = Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
    Uri.parse("package:${context.packageName}"))
context.startActivity(intent)

Java

Context context = TODO("Your activity or fragment's Context");
Intent intent = new Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
    Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);

意圖叫用後,使用者會看到名為「Open by default」(依預設開啟) 的設定畫面。這個畫面包含名為「開啟支援的連結」的單選按鈕,如圖 1 所示。

使用者開啟「開啟支援的連結」後,系統會在「要在這個應用程式中開啟的連結」部分下方顯示一組核取方塊。使用者可以在這裡選取要與應用程式建立關聯的網域。他們也可以選取「新增連結」來新增網域,如圖 2 所示。使用者之後選取所加入網域中的任何連結時,系統會自動在您的應用程式中開啟該連結。

啟用圓形按鈕後,畫面底部的附近會顯示一個區段,內含核取方塊和「新增連結」按鈕
圖 1. 系統設定畫面,使用者可以在其中選擇預設在應用程式中開啟的連結。
每個核取方塊代表一個可新增的網域。對話方塊的按鈕為「取消」和「新增」。
圖 2. 對話方塊,使用者可選擇要與應用程式建立關聯的其他網域。

開啟應用程式中無法驗證的網域

您的應用程式主要功能可能是以第三方的身分開啟連結,但無法驗證處理的網域。如果是這種情況,請向使用者說明,他們選取網頁連結時,無法在第一方應用程式和您的 (第三方) 應用程式之間選擇。使用者必須手動將網域與您的第三方應用程式建立關聯。

此外,如果使用者偏好在第一方應用程式中開啟連結,請考慮導入對話方塊或 Trampoline 活動,讓使用者開啟連結,做為 Proxy。設定這類對話方塊或暫時性活動前,請先設定應用程式,讓應用程式具有與應用程式網頁意圖篩選器相符的第一方應用程式套件瀏覽權限