Android アプリリンクを検証する

Android アプリリンクは特別なタイプのディープリンクであり、ウェブサイト URL から直接 Android アプリ内の対応コンテンツを開けるようになります(ユーザーがアプリを選択する必要はありません)。

Android アプリリンクをアプリに追加するには、HTTP URL を使用してアプリ コンテンツを開くインテント フィルタを定義して(アプリ コンテンツ用のディープリンクを作成するを参照)、アプリとウェブサイト URL の両方のオーナーであることを証明します(下記を参照)。URL を所有していることが正常に検証されると、システムは自動的に URL インテントをアプリにルーティングします。

アプリとウェブサイトの両方の所有権を証明するには、次の手順が必要です。

  • マニフェストでアプリの自動リンク検証をリクエストします。これにより、アプリがインテント フィルタで使用されている URL ドメインに属しているか検証する必要があるというシグナルが Android システムに送られます。
  • 以下の場所に Digital Asset Links JSON ファイルをホストすることにより、ウェブサイトとインテント フィルタの関係を宣言します。
    https://domain.name/.well-known/assetlinks.json
    .

関連情報については、以下のリソースをご覧ください。

  • Android Studio 内で URL と App Indexing をサポートする
  • ステートメント リストを作成する
  • ディープリンクとアプリリンクの相違点

    ディープリンクは、ユーザーが直接 Android アプリ内の特定アクティビティにアクセス可能になるインテント フィルタです。ディープリンクをタップすると、確認ダイアログが開きます。このダイアログで、ユーザーは、タップした URL を処理できる複数のアプリの中から 1 つのアプリを選択できます。たとえば、ユーザーが地図リンクをタップしたときに表示される確認ダイアログを図 1 に示します。このダイアログは、リンクを Google マップで開くのか Chrome で開くのかをユーザーに尋ねています。

    図 1: 確認ダイアログ

    Android アプリリンクは、ウェブサイトに属していることが検証されたウェブサイトの URL に基づくディープリンクです。そのため、これらのいずれかをクリックすると、アプリがインストールされている場合すぐに開きます。曖昧さ回避ダイアログは表示されません。ただし、ユーザーは後でこれらのリンクを処理するための設定を変更できます。

    より具体的な違いを次の表に示します。

    ディープリンクアプリリンク
    インテント URL スキーム httphttps、カスタム スキームのいずれか 必須要件: http または https
    インテント アクション 任意のアクション 必須要件: android.intent.action.VIEW
    インテント カテゴリ 任意のカテゴリ 必須要件: android.intent.category.BROWSABLE および android.intent.category.DEFAULT
    リンク証明 なし 必須要件: HTTPS を使用してウェブサイト上で Digital Asset Links ファイルを配信
    ユーザー エクスペリエンス ユーザーがリンクを開くアプリを選択するための曖昧さ回避ダイアログを表示する場合がある ダイアログなし。アプリが開いてウェブサイトのリンクを処理
    互換性 すべての Android バージョン Android 6.0 以降

    アプリリンクの検証をリクエストする

    アプリのリンク処理の検証を有効にするには、アプリ マニフェストにおいて、android.intent.action.VIEW インテント アクションと android.intent.category.BROWSABLE インテント カテゴリを含むいずれかのウェブ URL インテント フィルタ内で android:autoVerify="true" を設定します。次のマニフェスト コード スニペットをご覧ください。

        <activity ...>
    
            <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="http" android:host="www.example.com" />
                <data android:scheme="https" />
            </intent-filter>
    
        </activity>
        

    いずれかのインテント フィルタ内に android:autoVerify="true" が存在している場合、Android 6.0 以降を搭載しているデバイスにアプリがインストールされると、システムは、アプリのすべてのインテント フィルタ内にある URL に関連付けられているすべてのホストを検証します。検証は以下のように行われます。

    1. システムは、下記を含むインテント フィルタをすべて検査します。
      • アクション: android.intent.action.VIEW
      • カテゴリ: android.intent.category.BROWSABLE および android.intent.category.DEFAULT
      • データスキーム: http または https
    2. Android は、上記のインテント フィルタ内で検出された一意のホスト名ごとに、対象ウェブサイトの https://hostname/.well-known/assetlinks.json に Digital Asset Links ファイルが存在しているかクエリを実行します。

    システムは、マニフェスト内のすべてのホストで条件に合致する Digital Asset Links ファイルが見つかった場合に限り、アプリを指定 URL パターンのデフォルト ハンドラとして確立します。

    複数のホスト用のアプリリンク機能をサポートする

    アプリの URL インテント フィルタのデータ要素内で指定されている各ホストは、それぞれのウェブドメイン上でホストしている Digital Asset Links ファイルに基づいて、検証できる必要があります。1 つでも検証に失敗した場合、アプリは、アプリのインテント フィルタ内で定義されている URL パターンのデフォルト ハンドラであると証明されなくなります。この場合、システムは、インテント解決用の標準動作をデフォルト動作に設定します。デフォルト動作については、アプリ コンテンツ用のディープリンクを作成するをご覧ください。

    たとえば、次のインテント フィルタを持つアプリの場合、https://www.example.com/.well-known/assetlinks.jsonhttps://www.example.net/.well-known/assetlinks.json の両方で assetlinks.json ファイルが検出されなかった場合、検証は失敗になります。

        <application>
    
          <activity android:name=”MainActivity”>
            <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="http" android:host="www.example.com" />
              <data android:scheme="https" />
            </intent-filter>
          </activity>
          <activity android:name=”SecondActivity”>
            <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:scheme="https" android:host="www.example.net" />
            </intent-filter>
          </activity>
    
        </application>
        

    なお、1 つのインテント フィルタ内に複数の <data> 要素があった場合、すべてマージされ、あらゆる組み合わせの属性バリエーションがサポート対象になる点にご注意ください。たとえば、上記の最初のインテント フィルタには、HTTPS スキームだけを宣言している <data> 要素が含まれています。しかし、この要素は他の <data> 要素と結合されるため、結局、このインテント フィルタは、http://www.example.comhttps://www.example.com の両方をサポートすることになります。したがって、URI スキームとドメインの特定の組み合わせを定義したい場合は、個別のインテント フィルタを作成する必要があります。

    複数のサブドメイン用のアプリリンク機能をサポートする

    Digital Asset Links プロトコルは、インテント フィルタ内の各サブドメインを、それぞれ一意の個別ホストとして扱います。そのため、インテント フィルタ内に、サブドメインが異なる複数のホストを登録する場合、それぞれのドメイン上で、有効な assetlinks.json を公開する必要があります。たとえば、次のインテント フィルタの場合、受け入れるインテント URL ホストとして www.example.commobile.example.com が指定されています。そのため、https://www.example.com/.well-known/assetlinks.jsonhttps://mobile.example.com/.well-known/assetlinks.json の両方で、有効な assetlinks.json を公開する必要があります。

        <application>
          <activity android:name=”MainActivity”>
            <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="www.example.com" />
              <data android:scheme="https" android:host="mobile.example.com" />
            </intent-filter>
          </activity>
        </application>
        

    また、ワイルドカードを使用してホスト名を宣言する場合(*.example.com など)は、ルートホスト名(example.com)の場所で、assetlinks.json ファイルを公開する必要があります。たとえば、次のようなインテント フィルタを持つアプリの場合、assetlinks.json ファイルが https://example.com/.well- known/assetlinks.json で公開されていれば、example.com のサブ名(foo.example.com など)に関しても検証に合格します。

        <application>
          <activity android:name=”MainActivity”>
            <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="*.example.com" />
            </intent-filter>
          </activity>
        </application>
        

    ウェブサイトの関連付けを宣言する

    ウェブサイトに関連付けられている Android アプリを示し、アプリの URL インテントを証明するために、Digital Asset Links JSON ファイルをウェブサイト上で公開する必要があります。JSON ファイルは、関連付けられたアプリを識別するために次のフィールドと使用します。

    • package_name: アプリの build.gradle ファイル内で宣言されているアプリ ID
    • sha256_cert_fingerprints: アプリの署名証明書の SHA256 フィンガープリント。このフィンガープリントは、Java Keytool で次のコマンドを使用することで生成できます。
          $ keytool -list -v -keystore my-release-key.keystore
          
      このフィールドは複数のフィンガープリントをサポートしており、デバッグビルドや実稼働ビルドなど、アプリのさまざまなバージョンをサポートすることができます。

    com.example Android アプリにリンクを開く権限を付与する assetlinks.json ファイルの例を以下に示します。

        [{
          "relation": ["delegate_permission/common.handle_all_urls"],
          "target": {
            "namespace": "android_app",
            "package_name": "com.example",
            "sha256_cert_fingerprints":
            ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
          }
        }]
        

    1 つのウェブサイトを複数のアプリに関連付ける

    1 つの assetlinks.json ファイル内で、1 つのウェブサイトを複数のアプリに関連付けることを宣言できます。ファイルリストを通じて 2 つのアプリとの関連付けを個別に宣言するステートメント ファイルの例を以下に示します(このファイルは、https://www.example.com/.well-known/assetlinks.json に配置します)。

        [{
          "relation": ["delegate_permission/common.handle_all_urls"],
          "target": {
            "namespace": "android_app",
            "package_name": "com.example.puppies.app",
            "sha256_cert_fingerprints":
            ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
          }
          },
          {
          "relation": ["delegate_permission/common.handle_all_urls"],
          "target": {
            "namespace": "android_app",
            "package_name": "com.example.monkeys.app",
            "sha256_cert_fingerprints":
            ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
          }
        }]
        

    1 つのウェブホストにある複数のリソースに対してそれぞれ個別のリンクを用意し、各リンクを別のアプリで処理することができます。たとえば、app1 は https://example.com/articles 用のインテント フィルタを宣言し、app2 は https://example.com/videos 用のインテント フィルタを宣言する、というように指定できます。

    注: 1 つのドメインに関連付けられた複数のアプリは、同じ証明書で署名することも、異なる証明書で署名することもできます。

    複数のウェブサイトを 1 つのアプリに関連付ける

    複数のウェブサイトが、それぞれ独自の assetlinks.json ファイルを使用して、同一のアプリに対して関連付けを宣言することができます。ファイルリストを通じて example.com と example.net の両方が同一の app1 に対して関連付けを宣言する方法の例を以下に示します。最初のリストは example.com と app1 の関連付けを示しています。

    https://www.example.com/.well-known/assetlinks.json

        [{
          "relation": ["delegate_permission/common.handle_all_urls"],
          "target": {
            "namespace": "android_app",
            "package_name": "com.mycompany.app1",
            "sha256_cert_fingerprints":
            ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
          }
        }]
        

    次のリストアイテムは、example.net と app1 の関連付けを示しています。ファイルがホストされている場所だけが異なります(.com.net)。

    https://www.example.net/.well-known/assetlinks.json

        [{
          "relation": ["delegate_permission/common.handle_all_urls"],
          "target": {
            "namespace": "android_app",
            "package_name": "com.mycompany.app1",
            "sha256_cert_fingerprints":
            ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
          }
        }]
        

    JSON 検証ファイルの公開

    次の場所で JSON 検証ファイルを公開する必要があります。

    https://domain.name/.well-known/assetlinks.json

    注:

    • assetlinks.json ファイルは、content-type application/json で配信されます。
    • アプリのインテント フィルタが HTTPS をデータスキームとして宣言しているかどうかにかかわらず、assetlinks.json ファイルは HTTPS 接続でアクセスできる必要があります。
    • assetlinks.json ファイルは、リダイレクトなしでアクセスできる必要があります(301 リダイレクトや 302 リダイレクトなし)。また、bot がアクセスできる必要があります(robots.txt/.well-known/assetlinks.json のクロールを許可している必要があります)。
    • アプリリンクが複数のホストドメインをサポートしている場合、各ドメインで assetlinks.json ファイルを公開する必要があります。複数のホスト用のアプリリンク機能をサポートするをご覧ください。
    • 誰もがアクセスできるわけでない dev / test URL をマニフェスト ファイル内で使用してアプリを公開しないでください(VPN 内に限りアクセス可能な dev / test URL など)。このような場合の回避策は、ビルド バリアントを構成して、開発ビルド用に別のマニフェスト ファイルを生成することです。

    アプリリンクをテストする

    アプリリンク機能を実装する場合は、リンク機能をテストして、想定どおりにシステムがアプリとウェブサイトを関連付けているか、URL リクエストを処理できているか確認する必要があります。

    既存のステートメント ファイルをテストする場合は、ステートメント リスト生成テストツールを使用できます。

    検証するホストのリストを確定する

    テストを行う際は、アプリに関して検証が必要な関連ホストのリストを確定する必要があります。対象インテント フィルタが以下の属性と要素を含むすべての URL のリストを作成します。

    • http または https の値が指定されている android:scheme 属性
    • ドメイン URL パターンが指定されている android:host 属性
    • android.intent.action.VIEW アクション要素
    • android.intent.category.BROWSABLE カテゴリ要素

    このリストを使用して、指定された名前の各ホストおよび各サブドメイン上に Digital Asset Links JSON ファイルが用意されているかチェックします。

    Digital Asset Links ファイルを確認する

    ウェブサイトごとに、Digital Asset Links API を使用して、デジタル アセットリンク JSON ファイルが正しくホストされ定義されていることを確認します。

        https://digitalassetlinks.googleapis.com/v1/statements:list?
           source.web.site=https://domain.name:optional_port&
           relation=delegate_permission/common.handle_all_urls
        

    URL インテントをテストする

    アプリに関連付けるウェブサイトのリストを確定し、ホストされている JSON ファイルが有効であることを確認したら、アプリをデバイスにインストールします。非同期検証プロセスが完了するまで、少なくとも 20 秒待ちます。次のコマンドを使用して、システムでアプリが検証されたかどうかをチェックし、正しいリンク処理ポリシーを設定します。

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

    テストプロセスの一部として、リンク処理の現在のシステム設定をチェックできます。次のコマンドを使用して、コネクテッド デバイス上のすべてのアプリを対象に、既存のリンク処理ポリシーのリストを取得します。

        adb shell dumpsys package domain-preferred-apps
        

    あるいは、次のコマンドでも同じ処理を行うことができます。

        adb shell dumpsys package d
        

    注: アプリのインストール後、システムが検証プロセスを完了するまで、少なくとも 20 秒待つようにしてください。

    このコマンドにより、デバイス上で定義されている各ユーザーまたはプロファイルのリストが返されます。リストの先頭には、次の形式のヘッダーが付きます。

        App linkages for user 0:
        

    このヘッダーに続いて、次の形式のリストを使用して、対象ユーザーのリンク処理設定が出力されます。

        Package: com.android.vending
        Domains: play.google.com market.android.com
        Status: always : 200000002
        

    このリストは、対象ユーザーに関して、どのアプリがどのドメインに関連付けられているのかを示しています。

    • Package - マニフェスト内で宣言されているパッケージ名に基づいて、アプリを識別します。
    • Domains - このアプリがウェブリンクを処理するホストの全リストを示します。区切り文字としてスペースを使用します。
    • Status - このアプリの現在のリンク処理設定を示します。検証に合格したアプリがマニフェスト内に android:autoVerify="true" を含んでいる場合、ステータス always が示されます。このステータスの後ろにある 16 進数は、ユーザーのアプリリンク設定に関して Android システムが記録する際に使用するものです。検証が成功したかどうかを示す値ではありません。

    注: 検証が完了する前にユーザーがアプリのアプリリンク設定を変更した場合、検証が失敗していても、検証成功として誤検知されることがあります。ただし、サポートされているリンクを確認なしでアプリで開くように、ユーザーが明示的に設定している場合、この検証失敗は問題ありません。ユーザー環境設定は、プログラマティック検証よりも優先されます(あるいは、プログラマティック検証がない場合もあります)。その結果、ダイアログは表示されず、検証が成功したかのようにリンクは直接アプリにつながります。

    テストの例

    アプリリンクの検証が成功するには、アプリのインテント フィルタ内で指定されているウェブサイトのうち、アプリリンクの基準を満たすすべてのウェブサイトを対象にして、アプリを検証できる必要があります。複数のアプリリンクが定義されているマニフェスト構成の例を以下に示します。

        <application>
    
            <activity android:name=”MainActivity”>
                <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="www.example.com" />
                    <data android:scheme="https" android:host="mobile.example.com" />
                </intent-filter>
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                    <category android:name="android.intent.category.BROWSABLE" />
                    <data android:scheme="https" android:host="www.example2.com" />
                </intent-filter>
            </activity>
    
            <activity android:name=”SecondActivity”>
                <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:scheme="https" android:host="account.example.com" />
                </intent-filter>
            </activity>
    
              <activity android:name=”ThirdActivity”>
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:scheme="https" android:host="map.example.com" />
                </intent-filter>
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                    <category android:name="android.intent.category.BROWSABLE" />
                    <data android:scheme="market" android:host="example.com" />
                </intent-filter>
              </activity>
    
        </application>
        

    上記のマニフェストで、プラットフォームが検証を試みるホストのリストは次のとおりです。

        www.example.com
        mobile.example.com
        www.example2.com
        account.example.com
        

    上記のマニフェストで、プラットフォームが検証を試みないホストのリストは次のとおりです。

        map.example.com (it does not have android.intent.category.BROWSABLE)
        market://example.com (it does not have either an “http” or “https” scheme)
        

    ステートメント リストの詳細については、ステートメント リストを作成するをご覧ください。