IllegalStateException: WorkManager is already initialized
Since WorkManager 2.6, App Startup is used internally within WorkManager. To provide a custom initializer you need to remove the androidx.startup node.
If you don't use App Startup in your app, you can remove it completely.
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove">
</provider>
Otherwise, remove only the WorkManagerInitializer node.
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- If you are using androidx.startup to initialize other components -->
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
While using a version of WorkManager older than 2.6, remove workmanager-init instead:
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />
This is how to substitute provider androidx.work.impl.WorkManagerInitializer
:
<application>
...
<!-- disable default provider -->
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
android:exported="false"
android:enabled="false"/>
<!-- register custom provider -->
<provider
android:name=".CustomWorkManagerInitializer"
android:authorities="${applicationId}.WorkManagerInit"/>
</application>
Source: Custom Work Manager initialization (in Kotlin).
Unless registering another provider, this gives a:
java.lang.IllegalStateException: WorkManager is not initialized properly. The most
likely cause is that you disabled WorkManagerInitializer in your manifest but forgot
to call WorkManager#initialize in your Application#onCreate or a ContentProvider.
And the ContentProvider
registered in the src/debug/Manifest.xml
:
public class WorkManagerInit extends ContentProvider {
@Override
public boolean onCreate() {
if(getContext() != null) {
Configuration config = new Configuration.Builder().build();
WorkManager.initialize(getContext().getApplicationContext(), config);
}
return true;
}
...
}
WorkManager is a singleton, it needs to be configured before being used and you cannot change it's configuration without restarting the application.
A second call to initialize throws an exception to indicate that it cannot use that configuration if WorkManager has already been initialized. This was a design decision taken during the initial alpha releases to avoid to fail silently (workmanager-1.0.0-alpha11).
WorkManager v2.1 adds an on-demand way to initialize the library, so you can move the actual initialization out from the hot-start sequence of your app. However you still have the constraints that WorkManager can only be configured once.
With the new on-demand configuration, you've to add a Configuration.Provider
interface to your application like here:
class MyApplication : Application(), Configuration.Provider {
override fun getWorkManagerConfiguration(): Configuration =
// provide custom configuration
Configuration.Builder()
.setMinimumLoggingLevel(android.util.Log.INFO)
.setWorkerFactory(MyWorkerFactory())
.build()
}
Then, when you need to use WorkManager, instead of using WorkManager#getInstance()
(that is now deprecated), you should use the new:
WorkManager#getInstance(context)
In this case, the getInstance method, check if WorkManager it's already initialized or not. If it's not yet initialized, it retrieves the configuration using the getWorkManagerConfiguration()
method and then it initializes WorkManager. In this way, you don't call anymore WorkManager#initialize()
completely avoiding the problem.
The official documentation has been updated with these additional details.
If you think that WorkManager should allows to update it's configuration after it has been initialized, you should add a feature request to the library's issue tracker.