事象
FirebaseをLeakCanaryを併用するとLeakCanaryのプロセスが以下のログを出力しながらクラッシュします。
Caused by: java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process com.hogehoge:leakcanary.
Make sure to call FirebaseApp.initializeApp(Context) first.
LeakCanaryはアプリのメインプロセスとは別のプロセスで稼働しているのでアプリ自体はクラッシュしません(しばらくフリーズしますが)時と場合による。
原因
FirebaseはContentProviderを利用してライブラリの初期化を行っています。
この手法についてはこちらが詳しいです。
ContentProviderはデフォルトでマルチプロセスが無効となっているため、メインプロセス以外ではFirebaseが初期化されていない状態となってしまいLeakCanaryのプロセスで最初に示したエラーとなってしまいます。
このため、Firebaseに限らずContentProviderで初期化するアプローチを取っているライブラリは何らかの問題が発生する可能性があります。
対応方法
Firebaseには手動で初期化するためのAPIが用意されているのでそちらを使用してApplicationクラスの onCreate
で初期化します。
ref: FirebaseApp | Firebase
@Override
public void onCreate() {
// 必要に応じて他のオーバーロードと使い分ける
FirebaseApp.initializeApp(this)
}
これで、とりあえずクラッシュは回避できますが、初期化のためのContentProviderは残っているため無駄に初期化処理が動いてしまいます。
なのでAndroidManifestに次の記述を追加して、Manifest MergerがContentProviderを追加するのを防ぎます。
<provider
android:authorities="${applicationId}.firebaseinitprovider"
android:name="com.google.firebase.provider.FirebaseInitProvider"
tools:node="remove"/>
他にContentProviderを使用しているライブラリがあれば同様に tools:node="remove"
を指定してAndroidManifestに追加されないようにしていきます。
その際、 android:authorities
はなんでもいいのですが、 android:name
は実際のものと一致している必要があります。
ライブラリのソースを見るか、マージ後のAndroidManifestから探して正しいものを指定してください。
例えば、拙作のライブラリKotprefの場合は次のように指定することで自動初期化用のContentProviderを無効化することができます。
<provider
android:authorities="${applicationId}.KotprefInitProvider"
android:name="com.chibatching.kotpref.KotprefInitProvider"
tools:node="remove"/>
@Override
public void onCreate() {
Kotpref.init(this)
}