白眼鏡のblog

新しく得た知見を備忘録的に書き連ねていく

AppLinks 実装方法

AppLinksを使う事になったけども、 イマイチ日本語情報がなかったので、公式から重要そうな個所だけ抜きだして翻訳してみた。

AppLinks とは

ユーザがリンクからアプリを起動する際、Androidアプリリンクの選択ダイアログを表示させず、 ユーザをリンク先の特定のコンテンツへ誘導することができる。 AndroidAppLinksはHTTP URLと関連付けをウェブサイトを利用して行うため、アプリをインストールしていないユーザは、 サイトのコンテンツに直接アクセスする。

DeepLinkとAppLinksとは

  • DeepLink
    ユーザをアプリ内の特定のコンテンツに誘導するURL。 AndroidManifest.xmlにintentfilterを追加し、受信したインテントからデータを抽出して、 ユーザを適切なアクティビティに誘導する。

    しかし、ユーザの端末に同じインテントを利用する他のアプリがある場合、 複数のアプリが選択ダイアログに表示され、ユーザが意図したアプリを起動しない場合がある。

  • AppLinks
    Android6.0(APILevel23)以上で、使用できる。 指定された種類のリンクのデフォルトhandlerとして特定のコンテンツを指定できる。 システム設定から解除することも可能。

AppLinksの利点

  • Secure abd specific
    AppLinksは、所有するウェブサイトドメインに紐づけるHTTP URLを使用するため、他のアプリでリンクを使用することはできない。
  • Seamless user experience
    ウェブサイトとアプリで同じHTTP URLを使用するため、アプリをインストールしていないユーザは、アプリではなくウェブサイトに移動するだけでエラーは発生しない。
  • Android Instant Apps support
    Android Instant AppではAndroidアプリをインストールせずにAndroidアプリを実行できる。 Android Appにインタントアプリのサポートを追加するには、Android App Linksを設定し、g.co/InstantAppsにアクセスしてください?(よくわかんなかった)
  • Engage users from Google Search
    ユーザがモバイルブラウザ、Google検索アプリ、Androidの画面検索、GoogleアシスタントでURLをクリックすると、特定のコンテンツを直接開くことができる。

AppLinksを追加する

Android App Linksを作成する一般的な手順は以下のとおり。

  1. Create deep links to specific content in your App
    AndroidManifest.xmlにウェブサイトのURLのインテントフィルタを作成する。
  2. Add verification gor your deep links
    アプリリンクの確認をリクエストするようアプリに設定する。
    ウェブサイトにDigital Asset Links JSONファイルを公開して、Google Search Consoleを通じて所有権を確認する。

    Android StudioにあるAndroid App Links Assistantは上記の各ステップをガイドするツール。

Android App Linksの確認

Webサイトとintentfilterの関係を宣言するには、Digital Asset Links JSONファイルを次の場所に配置する。
http://ドメイン名/.well-known/assetlinks.json
AppLinksの処理の確認を有効にするにはandroid.intent.action.VIEW インテントアクションとandroid.intent.category.BROWSABLE インテントカテゴリの定義を含む
インテントフィルタのいずれかに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"がインテントフィルタのいずれかに存在する場合、インストール時に関連付けられているすべてのホストを検証しようとする。

  1. インテントフィルタの以下のものを検証する。
  2. 上記のインテントフィルタに含まれる一意のホスト名毎にAndroidはデジタルアセットリンクファイル
    (https://ホスト名/.well-known/assetlinks.json)を照会する。
    マニフェスト内のすべてのホストに対応するデジタルアセットリンクファイルが見つかった場合にのみ、アプリケーションは指定されたURLパターンの
    デフォルトハンドラとして確立される。

複数のホストのアプリケーション連携をサポート

システムは、インテントフィルタのデータ要素で指定された全てのホストを、それぞれのウェブドメインのデジタルアセットリンクファイルと照合できる必要がある。
検証が失敗した場合、アプリはインテントフィルタで定義されているすべてのURLパターンをデフォルトハンドラであると判定しない。
この場合DeepLinkの動作と同じ動作になる。

例として、

<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>

同じインテントフィルタ内の全てのデータ要素は、結合された属性のすべてのバリエーションを考慮して、一緒にマージされることに注意が必要。
例として、上記の最初のインテントフィルタには、HTTPSスキームのみを宣言するデータ要素が含まれています。
しかし、他のデータ要素と組み合わされるため、実際にはインテントフィルタは

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

デジタルアセットリンクプロトコルでは、インテントフィルタのサブドメインを固有の別々のホストとして扱う。 よって、インテントフィルタでサブドメインが異なる複数のホストがリストされている場合、各ドメインに有効なassetlinks.jsonを公開する必要がある。 例として、以下のインテントフィルタは、受け入れられるインテントURLホストとして www.example.comとmobile.example.comが含まれている。 よって、有効な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など)でホスト名を宣言する場合は、assethosts.jsonファイルをルートホスト名(example.com)に 公開する必要がある。 例えば、次のインテントフィルタを定義されたアプリは、assetlinks.jsonファイルが https://example.com に公開されている限り、example.comの任意のサブ名(ex.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の意図を確認する必要がある。 JSONファイルは、以下のフィールドを使用して、関連するアプリケーションを識別する。

  • パッケージ名
    build.gradleのapplicationIDで定義されている。
  • sha256_cert_fingerprints
    名証明書のsha256 fingerprintは次のコマンドを使用して生成できる。

    $ keytool -list -v -keystore my-release-key.keystore

このフィールドは、複数のfingerprintsをサポートしています。 デバッグやプロダクションビルドなど、様々なバージョンをサポートするために使用できます。

以下の例のassetlinks.jsonファイルはcom.example というパッケージ名のアプリケーションへのリンクオープン権を付与します。

[{
    "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:33:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
        }
}]

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

ウェブサイトは、同じassetlinks.jsonファイル内の複数のアプリケーションとの関連付けを宣言することができます。 次のファイルリストは、2つのアプリケーションとの関連を別々に宣言した例を示しています。

[{
    "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:33:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
    }
}]

異なるアプリは、同じWebホスト下の異なるリソースのリンクを処理することがあります。 例として、app1はhttps://example.com/articleインテントフィルタを宣言し、 app2はhttps://example.com/videosインテントフィルタを宣言することができます。

まとめ

  • AppLinksを利用するにはWebサイトが必要
  • URLのルートに./.well-known/assetlinks.jsonを配備する必要がある。
  • アプリが存在しない場合は、指定されたURLのページがそのまま表示される。

深く考えずにそのまま実装すれば、簡単にできますね。

翻訳元サイト

developer.android.com