WorkManager with Android Libraries

Inder singh
Rapido Labs
Published in
3 min readJun 7, 2022
Android Library with WorkManager

WorkManager is a powerful jetpack library for persistent work. Scheduled work is guaranteed to be executed sometime after its constraints (like metered network, the battery charging, etc.) are met. WorkManager allows observation of work status and the ability to create a complex chain of work.

There are numerous blogs and tutorials available for WorkManager usage in android applications with WorkManagerinitialization at the app startup time or on-demand initialization like the one below

But very few are available on how to use WorkManager in the right way within a SDK.

If workers have custom dependencies, then we have to provide the WorkerFactory to the WorkManager through which it will do the initialization of workers. WorkerFactory we have to provide at the time of initialization of the singleton WorkManager. You can read more about WorkManager custom initialization here.

The problem comes when we want to use the WorkManager in the android library like-

  • WorkManager is a singleton. So it can be initialized only once, either in-app or in the library.
  • If you are using workers with custom dependencies, then you have to provide a WorkerFactory to the configuration at the time of custom initialization. This can be a delegatingWorkerFactory which delegates to other factories, but all factories still need to register with the single delegator. We have to expose the WorkerFactory to the app so that it can be used at the time of initialization.

We had the same set of issues while working in my current organization, Rapido.

We are developing an SDK (comms-SDK) for facilitating communication between the platform and the apps which will be used in the Rider (we call them Captain) app wherein we are periodically syncing data to the server, for that purpose, we used an WorkManager in the library.

We don't want to enforce our apps (which use comms-SDK) to use WorkManager, and they should not know the internal implementation of the library (WorkerFactory).While finding the solution to this problem, we landed on the awesome square team blog where they also had a similar issue with their logging SDK.

Let's go to the solution now.

Problem 1: WorkManager initialization(w.r.to the app using our library)

Solution: For this, the solution was simple, we try to get the instance of WorkManager in the library, if we get an exception like

Caused by: 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.

Then only initialize the WorkManager in the library.

Problem 2: Launching Workers with custom dependencies from the library.

Solution: If we dig deeper into the WorkManager code, we can see that if WorkerFactory is not provided at the time of initialization of the WorkManager for a particular Worker, then it uses the default WorkerFactory which initializes the Workers via reflection until it has no custom dependencies.

if (builder.mWorkerFactory == null) {
mWorkerFactory = WorkerFactory.getDefaultWorkerFactory();
} else {
mWorkerFactory = builder.mWorkerFactory;
}

This means we can create another worker (say, ProxyWorker) with no custom dependency, which will be invoked by WorkManager, and we can use this Worker to invoke other Workers with custom dependency in the library via delegateWorkerFactory.

ProxyWorker can be configured like this:

We can schedule and stop the ProxyWorker in this way:

And that’s it. Now WorkManager will work independently with the app using your library.

I would like to thank Puneet, for the guidance and feedback.

That’s it for now, hope it helps! Enjoy and feel free to leave a comment if something is not clear or if you have questions. Thank you for reading! 🙌🙏

--

--