Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

Android アプリリンクの検証

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

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

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

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

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

  • Android Studio での URL と App Indexing のサポート
  • ステートメント リストの作成
  • ディープリンクとアプリリンクの違い

    ディープリンクは、ユーザーが Android アプリで特定のアクティビティを直接入力できるようにするインテント フィルタです。これらのリンクのいずれかをクリックすると、曖昧さ回避ダイアログが開きます。このダイアログで、ユーザーは特定の URL に対応する複数のアプリのいずれかを選択できます。たとえば図 1 は、ユーザーがマップリンクをクリックした後に、リンクをマップまたは Chrome のどちらで開くかを尋ねる曖昧さ回避ダイアログを示しています。

    図 1. 曖昧さ回避ダイアログ

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

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

    ディープリンクアプリリンク
    インテント URL スキーム httphttps、またはカスタム スキーム 必須: http または https
    インテント アクション 任意のアクション 必須: android.intent.action.VIEW
    インテント カテゴリ 任意のカテゴリ 必須: android.intent.category.BROWSABLEandroid.intent.category.DEFAULT
    リンクの検証 なし HTTPS を使用してウェブサイトで配信されるデジタル アセットリンク ファイルが必要
    ユーザー エクスペリエンス ユーザーがリンクを開くアプリを選択するための曖昧さ回避ダイアログを表示する場合がある ダイアログなし。アプリが開いてウェブサイトのリンクを処理
    互換性 すべての 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.BROWSABLEandroid.intent.category.DEFAULT
      • データスキーム: http または https
    2. 上記のインテント フィルタで見つかった一意のホスト名ごとに、Android は対応するウェブサイトで https://hostname/.well-known/assetlinks.json のデジタル アセットリンク ファイルをクエリします。

    システムは、マニフェスト内のホストすべてに一致するデジタル アセットリンク ファイルが見つかった場合にのみ、アプリを指定された URL パターンのデフォルト ハンドラとして確立します。

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

    アプリの URI インテント フィルタのデータ要素で指定されたホストはすべて、それぞれのウェブドメインでホストされるデジタル アセットリンク ファイルに対して検証可能である必要があります。検証に失敗した場合、アプリは、アプリのインテント フィルタで定義された URL パターンのデフォルト ハンドラであることが検証されません。その後、アプリ コンテンツへのディープリンクの作成で説明しているように、システムはインテントを解決する標準動作をデフォルト設定します。

    たとえば、次のインテント フィルタを持つアプリは、assetlinks.json ファイルが https://www.example.com/.well-known/assetlinks.jsonhttps://www.example.net/.well-known/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>
        

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

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

    デジタル アセットリンク プロトコルでは、サブドメインは一意の個別のホストとして扱われます。そのため、インテント フィルタが異なるサブドメインを持つ複数のホストをリストする場合、各ドメインで有効な assetlinks.json を公開する必要があります。たとえば次のインテント フィルタには、承認されたインテント URL ホストとして www.example.commobile.example.com が含まれています。そのため、有効な assetlinks.jsonhttps://www.example.com/.well-known/assetlinks.jsonhttps://mobile.example.com/.well-known/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>
        

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

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

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

    次の assetlinks.json ファイルの例では、com.example Android アプリにリンクを開く権限を付与しています。

        [{
          "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 つのウェブサイトを複数のアプリに関連付ける

    ウェブサイトは、同じ assetlinks.json ファイル内で複数のアプリとの関連付けを宣言できます。次のファイルリストは、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"]
          }
        }]
        

    複数のアプリが、同じウェブホストでさまざまなリソースのリンクを処理できます。たとえば、app1 は https://example.com/articles のインテント フィルタを宣言し、app2 は https://example.com/videos のインテント フィルタを宣言するなどです。

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

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

    複数のウェブサイトがそれぞれの assetlinks.json ファイルで、同じアプリとの関連付けを宣言できます。次のファイルリストは、app.1 と example.com、example.net の関連付けを宣言する方法の例を示しています。最初のリストは 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 でのみアクセス可能なものなど)。このような場合の回避策は、ビルド バリアントを構成して、開発ビルド用に別のマニフェスト ファイルを生成することです。

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

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

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

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

    テスト時は、システムがアプリに対して検証する必要がある関連ホストのリストを確認する必要があります。対応するインテント フィルタに次の属性と要素が含まれる、すべての URL のリストを作成します。

    • 値が http または httpsandroid:scheme 属性
    • ドメイン URL パターンを持つ android:host 属性
    • android.intent.action.VIEW カテゴリ要素
    • android.intent.category.BROWSABLE カテゴリ要素

    このリストを使用して、指定されたホストとサブドメインそれぞれでデジタル アセットリンク JSON ファイルが提供されていることをチェックします。

    デジタル アセットリンク ファイルを確認する

    ウェブサイトごとに、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)
        

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