アプリケーションからDynamic Feature Module形式のモジュールに含まれるクラスは見えないので、Activityを呼び出す際には
startActivity(
Intent().setClassName(
this,
"com.example.dynamic_feature.DynamicFeatureActivity"
)
)
のようにクラス名の文字列を指定することになりますが、補完が効かず、Activityのクラス名を変更した際に追随してくれません。
またNavigationでActivityへの遷移を定義している場合は、モジュールがインストールされていない状態だとアプリケーションがクラッシュしてしまいます。
これを何とかする方法です。
以下のコードはPlay Consoleのinternal test trackを使った検証はしていませんのでご注意下さい。
activity-alias
を使います。
まず、アプリケーション側で以下のようなsealed classを作ります。
package com.example.app
import android.app.Activity
sealed class ActivityAlias : Activity()
sealed class DynamicFeatureActivityAlias : ActivityAlias()
ActiivtyAliasクラスがActivityを継承しているのは、Navigationのクラス存在チェックを回避するためです。
DynamicFeatureActivityAliasをsealed classとして定義しているのは、インスタンス化を防ぐためです。
さらに、ProGuard/R8でリネームされないように、アプリケーションのproguard-rules.proに以下の設定を追加しておきます。
-keep class * extends com.example.app.ActivityAlias
最後に、対象モジュールのAndroidManifest.xmlにactivity-alias
を追加し、上記で作成したDynamicFeatureActivityAliasのクラス名をandroid:name
に指定します。
<activity-alias
android:name="com.example.app.DynamicFeatureActivityAlias"
android:targetActivity=".DynamicFeatureActivity" />
モジュールからアプリケーション側のクラスは見えるので、android:name
の値は補完が効き、クラス名の変更にも追随してくれます。
これで、以下のようにIntent(Context, Class)
を使ってIntentを生成することができるようになります。
startActivity(Intent(this, DynamicFeatureActivityAlias::class.java))
Nagivationを使う場合は、以下のようにandroid:name
にDynamicFeatureActivityAliasのクラス名を指定することができます。
<activity
android:id="@+id/dynamic_feature"
android:name="com.example.app.DynamicFeatureActivityAlias" />
DynamicFeatureActivityAliasはActivityのサブクラスなので、エラーにはなりません。
以上です。
参考
マルチモジュールとNavigation
https://medium.com/@star_zero/%E3%83%9E%E3%83%AB%E3%83%81%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%A8navigation-c7aaffbfd76