課題
一部の端末(例えば Zenfone 3など) でアプリが起動しないという事象が発生している。スタックトレースを見るとWokrManagerのgetInstanceするところでクラッシュしていた。
Caused by: java.lang.IllegalStateException: at androidx.work.impl.WorkManagerImpl.getInstance (WorkManagerImpl.java:140) at androidx.work.WorkManager.getInstance (WorkManager.java:180)
どうすればよいか。
原因
WorkManagerImpl.javaのgetInstanceメソッドを参照すると以下のような感じになっている。 https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public static @NonNull WorkManagerImpl getInstance(@NonNull Context context) { synchronized (sLock) { WorkManagerImpl instance = getInstance(); if (instance == null) { Context appContext = context.getApplicationContext(); if (appContext instanceof Configuration.Provider) { initialize( appContext, ((Configuration.Provider) appContext).getWorkManagerConfiguration()); instance = getInstance(appContext); } else { throw new IllegalStateException("WorkManager is not initialized properly. You " + "have explicitly disabled WorkManagerInitializer in your manifest, " + "have not manually called WorkManager#initialize at this point, and " + "your Application does not implement Configuration.Provider."); } } return instance; } }
if (appContext instanceof Configuration.Provider) {
がポイントで、ApplicationクラスではConfiguration.Providerを実装していないので通常 false で例外をくらうことになると思うが、
本来はライブラリの方でアプリの起動時にカスタムContentProviderを使用して自身を初期化してくれているため、特に何もしなくても他の端末だとエラーにはならない。
対応1
追記 Sonyの Xperia Z5 Premium(SO-03H)にて同一箇所でクラッシュ発生 。 なぜ駄目なのかが判然としないが、対応1では解決しないらしい。
ApplicationContextでConfiguration.Providerを実装しといてあげればとりあえずクラッシュは避けられそう。
ということでMyApplicationでConfiguration.Provider
をimplementすることに。
getWorkManagerConfiguration
の実装が必要になるが、WorkManagerInitializer.java
内のデフォルト実装にそろえておけばよいだろう。
class MyApplication : MultiDexApplication(), Configuration.Provider { override fun getWorkManagerConfiguration(): Configuration { return Configuration.Builder().build() } }
対応2
自前で初期化する方法もある。この場合はProvider側でのデフォルト初期化を無効化しておく必要がある(忘れるとクラッシュ)。
<provider android:name="androidx.work.impl.WorkManagerInitializer" android:authorities="${applicationId}.workmanager-init" tools:node="remove" />
class MyApplication : MultiDexApplication(), Configuration.Provider { override fun onCreate() { WorkManager.initialize(this, Configuration.Builder().build()) } }