Infinito Nirone 7

白羽の矢を刺すスタイル

Navigation Component で Build Variant ごとに Deep Link を定義する

Build Variant ごとに Deep Link (App Links) の host を変えたいとき、Navigation Component の navigation graph の定義をどうするかを示します。

<deepLink> では String Resources が使えない

navigation graph も XML で記述したリソースだと考えると、次のような定義は一見正しそうですが、生成される AndroidManifest を見ると全く予期しない結果になります。

<navigation>

  <fragment>

    <deepLink app:uri="@string/deep_link_uri" />

  </fragment>

</navigation>

{build_variant}/res/values/strings.xml に deep_link_uri を定義すれば、Build Variant ごとに Deep Link の URI が切り替えられそうですよね。上記の navigation graph から生成される AndroidManifest の 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" />

  <data android:scheme="https" />

  <data android:host="string" />

  <data android:path="/deep_link_uri" />

</intent-filter>

String Resource への参照そのものが URI だと解釈され、string という host で /deep_link_uri という path の URI で Deep Link を設定してしまっています。 Issue Tracker にこの問題の報告がありますが、どうやら <deepLink> での String Resource への参照はサポートしていないようです。代わりに、Manifest Placeholder のような仕組みを導入する予定があるようです。

navigation graph を Build Variant ごとに定義する

仕方がないので navigation graph の XML を Build Variant ごとに定義するしかありません。

navigation graph が十分にシンプルで小さいなら navigation graph 全体を Build Variant ごとに配置してもよいかもしれませんが、Deep Link の設定を切り分けるのであれば、Deep Link を持つ <fragment> だけを切り出した navigation graph を Build Variant ごとに用意し、それを main source set にある navigation graph から <include> するほうが良さそうです。