I’ve been writing a couple of android libraries open and closed source ones. At one point, a library(not all of them, but a few) need a context to initialise, which is not such an easy task to achieve since the first time that the context is available is in the onCreate method of the Application Object. That’s why many libraries have an init method, which you have to call in the applications Application Object. In this article I’ll show you another way of doing it.

So I guess many of you have seen something like this before:

Why is this? Well the libraries have to do some initialisation to be able to run. Here for example Jake Whartons (btw. great) library ThreeTenABP.

The bad thing on this kind of initialisation is, that even if we wouldn’t need to implement a custom Application, we need to do it. Additionally, we should not forget about this, otherwise we’ll run into crashes.

As library developers we have to think of the developers using our libraries as “Users”. As we all know “Users” especially developers are lazy, when it comes to writing lines of code.

That’s why we want to avoid having those initialisations. I found this solution in the firebase-common package, so they’re using it to initialise firebase exactly the same way.

How does it work?

We create an empty ContentProvider, register it in our manifest and don’t expose it to other apps.

What happens on Application start is, that it registers all ContentProviders in the system (calling onCreate). This means that at this point no activity has been started, but we have access to the (Application)Context, where we can initialise our library using this Context.

Let’s jump right into it and create an empty ContentProvider:

As you can see in the onCreate Method we’re able to initialise whatever we need to initialise there.

Additionally we have to register the ContentProvider within our Library-Manifest:

And here comes a tricky part. If we would use a fixed authority string, we would only be able to run on one Application per Android Device. This is why you have to make the authorities unique. A good idea is to use the applicationId + some string in this case “.yourlibraryinitprovider”.

The downside of this is, that if we (for some reason) don’t set the applicationId in our gradle file, the library would use the one we set in the library. This is why we have to double check if the applicationId is NOT the one we’re using library internal. We can do this by overriding the attachInfo method of the ContentProvider.

Advantages

This approach could be a game-changing hint for android libraries, since you can register LifecycleCallbacks in the Application, before any Activity actually started. With this you can reduce the amount of Library-Methods that require an Context’s.

Downsides?!

The onCreate-Method of the ContentProvider will be executed on the “main”-Thread, meaning that multiple providers will take at least the same time for initialising as if you would do it in the Applications onCreate plus the system registration. So you want to initialise them asynchronous (in both cases) if possible. Another fact to think about is, what happens if you introduce multiple libraries with this ContentProvider approach. Since all onCreate’s of all ContentProviders will be called, this also is a bit more time consuming, which is a reason more to do initialisation asynchronous. If your library can be initialised independent of the Applications process (probably not), you can try initialising it in a different process using android:process in the provider tag of the manifest. In most cases you don’t want that.

Update:

On the 10th of june 2020, google announced the first version of “startup”, an androidx library that’s supposed to replace the solution provided in this article. Let’s have a closer look.

You are supposed to implement your Initialiser like this:

you have to add it, to the manifest but wait…, that looks familiar to what we’ve seen above.

What does this tell us? Well the “startup” library does more less the same as the provided solution above, with some adjustments:

It merges multiple Initializers together, so that there’s only one Initializer per application. (Remember, in the above’s solution it was one Initializer per library)

Due to the fact that you’re supposed to use meta-data to provide your Initializer, they’re using this Tag to load all Initializers for a (singular) application. Backgrounding the Initializations in order to avoid blocking ui on startup.

Summary

I’ve shown you how to get access to the Application Context from the library Level. Since google introduced their new “startup” library, there are no downsides left, which were provided or have been discussed here.

Finally a nice and convenient way to initialize your library.