App Context¶
Always have your application Context
at hand with appCtx
.
Supported platforms: Android.
This split provides two read-only properties:
appCtx
that returns your Application ContextdirectBootCtx
for your direct boot aware components where storage is involved, if any.
It also brings these 2 extensions functions on Context
for advanced usages:
- injectAsAppCtx()
- canLeakMemory()
You can use appCtx
and directBootCtx
anywhere in your app (without
risking leaking a short-lived context such as an Activity or a Service).
This makes writing code that needs a Context
for non Activity specific
purposes more convenient.
Important: use the right context!¶
You may not want to use the Application Context in some cases.
Context for storage¶
If you need a Context
to access storage from a library
(for SharedPreferences, a database or other files), you should allow
passing a specific Context
that could default as appCtx
, so it is
possible for target apps to use a special Context
like directBootCtx
.
Configuration dependent or themed Context¶
Devices on which your app/library runs may (will) change configuration during the app’s process lifecycle, such as screen density, language or orientation.
Please, do not use appCtx
or directBootCtx
if you rely on a “scoped”
Context
to access themed resources from an Activity, or
configuration dependent values/resources.
Note that in some cases, configuration dependent context usage may be ok if
your component handles onConfigurationChanged()
properly. More generally,
if you wonder if using Application Context is ok, test your app against
configuration changes that may affect it and check it reacts correctly.
How it works¶
This library takes advantage of Content Providers to automatically
initialize appCtx
for you before even your Application‘s
onCreate()
is called! This library also takes advantage of
manifest placeholders
(with the default ${applicationId}
) and gradle manifest merging to avoid
two apps using this library clashing with same authority Content Providers.
This is the same trick used by Firebase to auto-initialize the library. You can read more on this here.
Advanced use cases¶
Multi-process apps and libraries¶
While most apps run on single-process, on the default one, some need to
run some components in different processes. If your app needs to access
appCtx
or directBootCtx
directly, or indirectly in a component that
has it’s android:process
tag in AndroidManifest.xml
set to
:the_name_of_your_private_process
or
the_fully_qualified_name_of_your_shared_process
, you have 3 solutions:
1. Do nothing and let appCtx
init itself with reflection on first access
2. Call injectAsAppCtx()
in the onCreate()
method of your custom
Application
subclass.
3. Subclass AppCtxInitProvider
and declare it correctly in your
AndroidManifest.xml
for each non default process. This option may be the
best one if you’re making a library that has its own process as no further
configuration will be required on the app side. See instructions below:
How to declare an AppCtxInitProvider correctly (for multi-process usage)¶
- Subclass
AppCtxInitProvider
- Register your subclass as a
provider
in your AndroidManifest.xml file. - Specify it’s
android:process
attribute to the name of your app’s non default process. (beware of typos) - Set
android:exported
to false. - Set
android:authorities
to something other than${applicationId}.appctxinitprovider
. The suggested naming convention is${applicationId}.appctxinitprovider.the_name_of_your_process
so the content provider authority doesn’t clash with another one from your app, or from a third-party app. - If your component is Direct Boot aware, add
android:directBootAware="true"
. - If you use
appCtx
ordirectBootCtx
in another Content Provider, make sure to specifyandroid:initOrder
to a higher value than the one of the other Content Provider which use the ctx properties.
The result should look like this:
<provider
android:name=".SecondProcessInitProvider"
android:authorities="${applicationId}.appctxinitprovider.second_process"
android:exported="false"
android:initOrder="900"
android:process=":second_process"/>
import AppCtxInitProvider
class SecondProcessInitProvider : AppCtxInitProvider()
Download¶
implementation("com.louiscad.splitties:splitties-appctx:3.0.0-beta01")