AndroidのApp Links対応にあたり、AndroidManifest.xmlに対応するスキーム/ホスト/パスなどを設定すると思います。1つのアプリで複数のホストに対応する場合にハマった点があったため、それについてまとめます。
🏁ゴール
アプリのMainActivity
を次の2つのURLパターンから起動できるようにするのをゴールとします。それぞれのURLは異なるホストになっています。
https://foo.example.com/users/.*
https://bar.example.jp/articles/.*
🙅NGな例
こちらがNGな例です。どこがダメかわかりますでしょうか?
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.MyApplication.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- App Links -->
<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="foo.example.com"
android:pathPattern="/users/.*" />
<data
android:scheme="http"
android:host="bar.example.jp"
android:pathPattern="/articles/.*" />
</intent-filter>
</activity>
この場合、Androidは次の4つのURLパターンでアプリを起動しようとしてしまいます。
https://foo.example.com/users/.*
https://foo.example.com/articles/.*
https://bar.example.jp/users/.*
https://bar.example.jp/articles/.*
AndroidがAndroidManifest.xmlに定義されたものをどのように解釈するかは、Android StudioのTools にあるApp Links Assistantを使うとよくわかります。AndroidManifest.xmlが上記の状態でApp Links AssistantのURL Mapping Managerを起動すると次のような画面が表示されます。
🙆OKな例
複数ホストを設定する場合、正しくは次のようにホストごとにintent-filter
を分ける必要があります。
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.MyApplication.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- App Links -->
<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="foo.example.com"
android:pathPattern="/users/.*" />
</intent-filter>
<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="http"
android:host="bar.example.jp"
android:pathPattern="/articles/.*" />
</intent-filter>
</activity>
この状態でURL Mapping Managerを起動すると次のような画面が表示されます。ちゃんと🏁ゴールの状態になっていますね!
ネット上の記事で🙅NGな例の方で書かれているものも散見されていますが、公式ドキュメントでも次のように明確に書かれています。
1 つのフィルタに複数の
<data>
要素を組み込むことは可能ですが、一意の URL(scheme
とhost
の特定の組み合わせなど)を宣言する場合は、それぞれ個別のフィルタを作成する必要があります。1 つのインテント フィルタ内に複数の<data>
要素があると、実際にはマージされ、あらゆる組み合わせの属性バリエーションがすべてサポート対象になります。