アプリリンクを確認する

アプリのインテント フィルタの少なくとも 1 つに android:autoVerify="true" が存在する場合、Android 6.0(API レベル 23)以上を搭載しているデバイスにアプリをインストールすると、システムはアプリのインテント フィルタ内の URL に関連付けられているホストを自動的に検証します。Android 12 以降では、検証プロセスを手動で呼び出すことで、検証ロジックをテストすることもできます。

自動確認

システムの自動検証には、次の処理が含まれます。

  1. システムは、下記を含むインテント フィルタをすべて検査します。
    • アクション: android.intent.action.VIEW
    • カテゴリ: android.intent.category.BROWSABLEandroid.intent.category.DEFAULT
    • データスキーム: http または https
  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 以上

デバイスの検証ツールに固有のカスタム エラーコード。

ネットワーク接続が確立されていることを再確認し、もう一度ドメイン検証プロセスを呼び出します

アプリをドメインに関連付けるようユーザーに依頼する

アプリをドメインについて承認するもう 1 つの方法は、アプリをそのドメインに関連付けるようユーザーに依頼することです。

アプリがすでにドメインに対して承認されているかどうかを確認する

ユーザーにプロンプトを表示する前に、アプリが、<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);

インテントが呼び出されると、ユーザーには [デフォルトで開く] という設定画面が表示されます。図 1 に示すように、この画面には [対応リンクを開く] というラジオボタンがあります。

ユーザーが [対応リンクを開く] をオンにすると、[このアプリ内で開くリンク] というセクションに、一連のチェックボックスが表示されます。ユーザーはここから、アプリに関連付けるドメインを選択できます。図 2 に示すように、[リンクを追加] を選択してドメインを追加することもできます。ユーザーが追加したドメイン内のリンクを選択すると、そのリンクがアプリで自動的に開きます。

ラジオボタンをオンにすると下部のセクションにチェックボックスと [リンクを追加] ボタンが表示されます
図 1. アプリでデフォルトで開くリンクをユーザーが選択できるシステム設定画面。
各チェックボックスは追加できるドメインを表しています。ダイアログのボタンは [キャンセル] と [追加] です。
図 2. アプリに関連付ける追加のドメインをユーザーが選択できるダイアログ。

アプリが検証できないドメインをアプリで開く

サードパーティとしてリンクを開くことがアプリの主な機能であって、処理対象ドメインを検証する機能を備えていないこともあります。その場合は、ユーザーがウェブリンクを選択する際に、ファーストパーティ アプリとサードパーティ アプリのどちらかを選択できないことを説明します。ユーザーは、ドメインをサードパーティ アプリに手動で関連付ける必要があります。

さらに、ユーザーが希望する場合はファーストパーティ アプリでリンクを開くことができる、プロキシとして機能するダイアログまたはトランポリン アクティビティの導入を検討します。このようなダイアログまたはトランポリン アクティビティを設定する前に、アプリのウェブ インテント フィルタに一致するファーストパーティ アプリに対してパッケージの公開設定を持つようにアプリを設定します。