General
This post describes how to use Android ContentProvider to allow automatic system initialisation for your library, therefore help make your library easier to integrate and control its flow.
While this article mostly demonstrates one use case, you can use the idea in other cases as well.
What is it all about?
Always Strive To Simplify Integration
Let’s assume you are writing code for a software library that would be used by an Android application.
Most common flows require the app using your library to manually call the initialisation of your library and usually, provide it with their own Context.
This will require your client to write a code along these lines:
This article suggests using a Content Provider to allow:
- Completely autonomous initialisation, liberating you from having to ask the client for init at all.
- Avoiding the necessity of asking your client for their Application Context.
Thus the above code line will transform into this:
* Note how your initialisation is now completely independent of publisher. The flow starts in your class and is under your control.
So, What’s Next?
Technical Step by Step:
1. Create a ContentProvider extending class:
2. Add an empty implementation for all required abstract methods of ContentProvider:
3. Override the ContentProvider’s onCreate() to retrieve an Application Context instance:
4. In your AndroidManifest.xml add a “provider” declaration, this provider tag will be merged with the host application manifest:
* Note: If you use ${applicationId} as the value for authorities key, the system will replace it with the package name of the application hosting your library.
Attributes used:
- Authorities: Authority helps the ContentResolver system to find your ContentProvider instance correctly before passing data to it.
- Exported: If set to true then the ContentProvider is available for other applications to use.
- Enabled: If set to true then the operating system can instantiate the ContentProvider.
A Common Pitfall (and how to avoid it)
Registering multiple providers under the same authority can certainly be a serious issue.
The Problem:
Let’s say multiple applications installed on the same device, all embed the DemoSDK in this example. If more than one of those have not properly set their applicationId, then the value declared in the AndroidManifest.xml will fallback to using DemoSDK’s package name.
If this happens then multiple ContentProviders will be registered under the same authority, therefore causing issues with the operating system.
Solution:
If you want to avoid this, in your ContentProvider extending class, then pay special care to the method ‘attachInfo(…)’:
Notice:
- You can get system information on your ContentProvider (ProviderInfo) from the AttachInfo callback.
- To catch the case where the value returned for ${applicationId} in your AndroidManifest.xml request the providerInfo.authority String and compare it to your own ContentProvider’s simple name.
Conclusion
Keep in mind:
If you opt for using the idea of ContentProvider for your projects initialisation, then keep in mind that your code flow will be started by the operating system and not by direct user code. Therefore, this means you might have to adjust how you think of / where you position your code initialisation with respect to the rest of your or your client’s code.
How Firebase does this:
If you’re interested in comparing information against a source you know well, then feel free to hop on to Google Firebase’s blog: https://firebase.googleblog.com/2016/12/how-does-firebase-initialize-on-android.html
Official relevant documentation:
- First of all read here: https://developer.android.com/reference/android/content/ContentProvider
- Another useful page: https://developer.android.com/guide/topics/manifest/provider-element#auth
To read a sample project in Kotlin:
If you prefer working with Kotlin, then here’s a sample project that shows this concept along some other code: