Accessing Android Shared Preferences Across Multiple Processes
February 2, 2016Accessing Android Shared Preferences Across Multiple Processes
Shared preferences are the primary way for an app to persist small bits of information such as user-selected settings. You can persist simple Java primitives like int
s, boolean
s and float
s or complex objects like String
s, Parcelable
s, and Serializable
s. Many developers are introduced to shared preferences with a simple example showing how to store and retrieve values through the default shared preferences.
// persist the preference
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putBoolean("PREF_USER_LIKES_COOKIES", true)
.commit();
// retrieve the preference
boolean userLikesCookies =
PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean("PREF_USER_LIKES_COOKIES", false);
Pretty simple, right?
Accessing a Shared Preference From Another Process
Now let’s say that we want to edit this preference in one process and access it from another process.
Let’s set up a LocaleChangeReceiver:
<receiver
android:name=".LocaleChangeReceiver">
<intent-filter>
<action android:name="android.intent.action.LOCALE_CHANGED"/>
</intent-filter>
</receiver>
public class LocaleChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putBoolean("PREF_USER_LIKES_COOKIES", new Random().nextBoolean())
.commit();
}
}
This receiver runs whenever the device’s locale or language is changed but it runs in a separate process from our app’s main process. When we edit and commit the shared preference in LocaleChangeReceiver’s process, the change may or may not have persisted by the time we attempt to read it in the main process. Each process has their own instance of the app’s shared preferences, and when one process edits a shared preference, the changes may not be reflected in another process’s instance for an indeterminate amount of time.
MODE_MULTI_PROCESS
Up to and including Android API level 9 (OS version 2.3), shared preference instances between processes were checked to ensure that the latest changes were reflected amongst all processes. However after API level 9, the MODE_MULTI_PROCESS flag must be set when accessing shared preferences.
In order to use this mode flag you will have to read/write your shared preferences using Context.getSharedPreferences()
where you select a file name and various mode flags.
context.getSharedPreferences(
"shared pref file name",
Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS
);
When you access default shared preferences with
PreferenceManager.getDefaultSharedPreferences(context)
you’re ultimately calling this under the hood:
context.getSharedPreferences(
context.getPackageName() + "_preferences",
Context.MODE_PRIVATE
);
This means that the file name and mode of your existing shared preferences are already set in stone and are unchangeable. To use Context.MODE_MULTI_PROCESS
you will have to migrate your app’s existing shared preferences to a new shared preferences file.
public static void migrateSharedPreferences(Context context) {
// retrieve the preference from the default shared preferences...
boolean oldDefaultSharedPrefUserLikesCookies =
PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean("PREF_USER_LIKES_COOKIES", false);
// ...and set it in a new shared preferences file that uses Context.MODE_MULTI_PROCESS
context.getSharedPreferences(
"{user prefs file name}",
Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS
)
.edit()
.putBoolean("PREF_USER_LIKES_COOKIES", oldDefaultSharedPrefUserLikesCookies)
.commit();
}
Now you can access your migrated shared preferences.
boolean userLikesCookies =
context.getSharedPreferences(
"{user prefs file name}",
Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS
).getBoolean("PREF_USER_LIKES_COOKIES", false);
Once you’ve migrated your default shared preferences to a non-default shared preferences file that uses Context.MODE_MULTI_PROCESS
, your shared preference instances amongst processes are written and read immediately as you would expect.
API Level 23 (6.0) Deprecation
However, as of API Level 23 (OS version 6.0), Context.MODE_MULTI_PROCESS
is deprecated as it has been deemed unreliable in some versions of Android. The documentation recommends that you instead use a ContentProvider (i.e. the system’s underlying SQLite database) to manage shared preferences that need to be shared amongst multiple processes. Again, if you were previously using Context.MODE_MULTI_PROCESS
this means you will need to migrate your existing shared preferences over to being managed by a ContentProvider
.
Setting up a ContentProvider
and its accompanying boilerplate code feels like overkill just to store your simple shared preferences. You don’t have to do it for all your shared preferences but you may not be able to predict which ones will need to be accessed from multiple processes in the future.
The Solution
An elegant solution to this dilemma is Tray, an Android library that uses a ContentProvider
underneath its hood to allow you to read and write shared preferences with an API similar to the Android SharedPreference
API. It even provides a mechanism for migrating over existing preferences to be managed by the library.
Moving forward, it seems prudent to manage all shared preferences by either this library or manually through a ContentProvider
, as one can not predict how shared preferences will need to be accessed in the future, and we can avoid having to migrate old shared preferences. We welcome other developers who have come across this problem to share their experiences and thoughts on the matter. What other methods have you found to be useful for inter-process sharing of shared preferences?
Stay in the loop with our latest content!
Select the topics you’re interested to receive our new relevant content in your inbox. Don’t worry, we won’t spam you.

Download a collection of 3 key articles on the state of digital today
April 14, 2020As presented by Forbes. Download the top-3 most popular articles published by Michigan Software Labs.
Read more
Why I use NextJS
December 21, 2022Is NextJS right for your next project? In this post, David discusses three core functionalities that NextJS excels at, so that you can make a well-informed decision on your project’s major framework.
Read more
Information Experience can make or break a product
January 4, 2023Kai discusses how writing impacts user experience, providing an overview of the types of writing that are involved in product development and how to approach it from a very high level.
Read more