SharedPreferences: What Is Android Key-Value Storage

Author: IT Sectr Published: 2026-03-12 Reading time: 9 min

SharedPreferences is a key-value data storage on Android designed for saving simple settings and app configurations. Data is stored in an XML file on the device and is accessible only within the app that created it. According to the official documentation Android Developers, 2025, SharedPreferences supports storing primitive types: String, Int, Boolean, Float, Long and Set<String>. This is the simplest and fastest solution for saving small amounts of user settings without needing SQL queries or working with the file system directly.

Key Takeaways

  • SharedPreferences — key-value Android storage for saving simple app settings in an XML file.
  • Supports five data types: String, Int, Boolean, Float, Long and Set<String>.
  • Works synchronously (get) and asynchronously (apply) for write operations with disk persistence.
  • Data is isolated by file name and access mode (PRIVATE, MULTI_PROCESS).
  • For large data volumes Google recommends using DataStore or Room instead of SharedPreferences.

What is SharedPreferences?

SharedPreferences is a built-in Android mechanism for storing key-value pairs in an XML file on the device's internal storage. It has been available since API Level 1 and does not require any additional libraries. Its main purpose is saving user preferences, interface state, first-launch flags, and other simple data that does not require a structured database.

Each SharedPreferences file is associated with a specific name and access mode. By default, Context.MODE_PRIVATE mode is used, which restricts file access to only the current app. Previously Android supported MODE_WORLD_READABLE and MODE_WORLD_WRITEABLE modes, but they were deprecated starting from API Level 17 and completely removed in Android 7.0 (API 24) for security reasons.

Despite its simplicity, SharedPreferences is used in millions of Android apps. According to Google, more than 90% of apps published on Google Play use SharedPreferences for storing settings. However, for complex scenarios (large data volumes, type safety, asynchrony) Google recommends more modern solutions such as Preferences DataStore from the Android Jetpack library.

Storage Format: XML on Device

Physically, SharedPreferences is stored as an XML file in the app's directory: /data/data/{package_name}/shared_prefs/{file_name}.xml. The file contains a root element <map> with child elements <string>, <int>, <boolean>, <float> and <long> depending on the stored value type. The file size is not limited, but for large data volumes (over 100 KB) read and write performance begins to degrade noticeably.

SharedPreferences files are not encrypted by default. Data is stored in plain text on the device's file system. For storing sensitive data (tokens, passwords) it is recommended to use EncryptedSharedPreferences from the AndroidX Security library, which automatically encrypts keys and values using AES256-GCM.

How SharedPreferences Works in Android

SharedPreferences works on the principle of in-memory caching with periodic disk synchronization. On first access to the file (via getSharedPreferences), Android loads the XML file into RAM and parses it into a Map object. All subsequent read operations are performed from memory without re-reading from disk. This ensures high data access speed.

Write operations use Editor — an internal change buffer. When the developer calls putString or putBoolean, changes are stored in the Editor object in memory. The actual disk write occurs when the commit method (synchronous) or apply (asynchronous) is called. Data is not saved until these methods are called, and changes may be lost if the app crashes unexpectedly.

Access Modes and Context

To obtain a SharedPreferences instance, two methods are used: getPreferences and getSharedPreferences. The first is only available inside an Activity and creates a file named after the Activity. The second is more flexible, accepts a file name and access mode, and is accessible from any context (Application, Activity, Service). It is recommended to use getSharedPreferences with a file name corresponding to the module or functionality of the app.

kotlin
// Getting SharedPreferences
val prefs = context.getSharedPreferences(
    "user_settings", Context.MODE_PRIVATE
)

// Writing Data
with(prefs.edit()) {
    putString("username", "Anna")
    putInt("age", 28)
    putBoolean("isLoggedIn", true)
    apply()
}

// Reading Data
val username = prefs.getString("username", "")
val age = prefs.getInt("age", 0)
val isLoggedIn = prefs.getBoolean("isLoggedIn", false)

When using MODE_MULTI_PROCESS (deprecated) SharedPreferences synchronizes between processes. However, this synchronization does not guarantee atomicity, and Google recommends avoiding SharedPreferences in multi-process scenarios. For such cases it is better to use ContentProvider, Room with inter-process access, or DataStore.

SharedPreferences Main Methods

SharedPreferences provides a set of methods for reading data by key and the Editor interface for writing. Each read method takes two parameters: a key and a default value that is returned if the key is not found. The default value also determines the return type: getString returns String, getInt returns Int, and so on.

Read MethodWrite MethodData Type
getStringputStringString
getIntputIntInt
getBooleanputBooleanBoolean
getFloatputFloatFloat
getLongputLongLong
getStringSetputStringSetSet<String>

Editor and apply vs commit

Editor is an internal SharedPreferences object that collects changes in a buffer. After making all changes, the developer calls commit() (synchronous write) or apply() (asynchronous write). The difference is critical: commit blocks the current thread until writing to disk is complete and returns a boolean (success/failure), while apply performs the write in a background thread and immediately returns control but does not return a result.

It is recommended to use apply instead of commit in all cases where you do not need to know the write result. apply is faster and does not block the UI thread. commit should only be used when it is critical to know whether the data was saved successfully, or when working with multi-process mode. To remove individual keys the remove method is used, for full clearing — clear. All delete operations are also performed through Editor.

kotlin
// Multiple changes - one apply
prefs.edit {
    putString("theme", "dark")
    putBoolean("notifications", false)
    remove("old_key")
}

// Value change listener
prefs.registerOnSharedPreferenceChangeListener { prefs, key ->
    Log.d("TAG", "Key changed: $key")
}

Starting from Android 12 (API 31), SharedPreferences was enhanced with support for registerOnSharedPreferenceChangeListener with automatic unsubscription via Lifecycle. This helps avoid memory leaks associated with forgotten listeners. In older versions, the developer must manually call unregisterOnSharedPreferenceChangeListener in onDestroy or onStop of the component.

SharedPreferences vs Storage Alternatives

Despite its widespread use, SharedPreferences is not a universal solution for all data storage scenarios on Android. Depending on data volume, type safety requirements, and performance, Google recommends various alternatives included in Android Jetpack and the standard Android library.

SolutionWhen to UseDrawbacks
SharedPreferencesSmall settings (up to 100 keys)No type safety, synchronous reading
DataStoreMedium complexity settings with coroutinesNo backward compatibility below API 14
RoomStructured data and listsOverkill for 3-5 settings
EncryptedSharedPreferencesSensitive data and tokensDepends on AndroidX Security

DataStore — Modern Alternative

DataStore is an Android Jetpack library presented by Google as a replacement for SharedPreferences. It provides two variants: Preferences DataStore (key-value, like SharedPreferences) and Proto DataStore (typed storage via Protocol Buffers). DataStore uses coroutines and Flow for asynchronous operation, guarantees type safety, and automatically handles version migrations. Google recommends DataStore for all new projects.

The main advantage of DataStore is asynchrony at the API level. All read operations return Flow, and write operations are suspend functions. This completely eliminates UI thread blocking that can occur with synchronous SharedPreferences reading. Additionally, DataStore guarantees data consistency: writes are performed in a transaction, and on failure all changes are rolled back.

Example of Using SharedPreferences in an App

Let us consider a practical example: theme settings (light/dark/system) in an Android app. The user selects a theme, and the choice is saved in SharedPreferences. On subsequent app launches, the theme is restored from saved settings. For reactive UI updates, observing changes via SharedPreferences.OnSharedPreferenceChangeListener is used.

Saving User Settings

Let us create a ThemePreferences class that encapsulates all work with SharedPreferences for the theme. The class provides getTheme (read), setTheme (write), and observeTheme (observation) methods. The settings file name will be "app_preferences" with MODE_PRIVATE mode. For convenience, keys are placed in a companion object as constants.

kotlin
class ThemePreferences(context: Context) {
    companion object {
        private const val PREF_NAME = "app_preferences"
        private const val KEY_THEME = "theme_mode"
        const val THEME_LIGHT = "light"
        const val THEME_DARK = "dark"
        const val THEME_SYSTEM = "system"
    }

    private val prefs = context
        .getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)

    fun getTheme(): String =
        prefs.getString(KEY_THEME, THEME_SYSTEM) ?: THEME_SYSTEM

    fun setTheme(theme: String) {
        prefs.edit { putString(KEY_THEME, theme) }
    }

    fun observeTheme(callback: (String) -> Unit) {
        prefs.registerOnSharedPreferenceChangeListener { _, key ->
            if (key == KEY_THEME) {
                callback.invoke(getTheme())
            }
        }
    }
}

In an Activity or Fragment, obtaining a ThemePreferences instance is done through the app context. On initialization, getTheme is called to set the current theme. When the user selects a new theme, setTheme is called, and via observeTheme the interface updates without restarting the Activity. It is important to unsubscribe from the listener in onDestroy to prevent memory leaks, especially if the Activity is recreated on configuration change.

For apps with a minimum target version of Android 12+, it is recommended to use registerOnSharedPreferenceChangeListener together with LifecycleObserver. This automatically manages subscription and unsubscription upon component lifecycle changes. For older versions, subscription and unsubscription must be managed manually, which is a frequent source of errors in production apps using SharedPreferences.

Frequently Asked Questions

Can objects be stored in SharedPreferences?

SharedPreferences directly supports only primitive types and Set<String>. To store objects, you need to serialize them into a JSON string via Gson or Moshi, save via putString, and deserialize when reading. For complex objects with many fields, it is recommended to use Room instead of SharedPreferences with JSON serialization.

Is SharedPreferences thread-safe?

Yes, SharedPreferences is thread-safe. All read and write operations are synchronized at the SharedPreferences object and its Editor level. However, when using multi-process mode, synchronization is not guaranteed. For concurrent access from multiple threads within a single app, SharedPreferences is safe without additional locks.

How to clear all SharedPreferences data?

To completely clear all data from SharedPreferences, call the clear() method on Editor and apply the changes via apply. If you need to delete the XML file itself, use deleteSharedPreferences(name) on the context. Clearing app data via Settings → Apps → Clear data also removes all SharedPreferences files.

SharedPreferences or DataStore: which to choose?

For new projects, Google recommends DataStore as a replacement for SharedPreferences. DataStore provides asynchronous operation with coroutines, type safety (Proto DataStore), and automatic migrations. SharedPreferences should only be chosen for projects with a minimum version below API 14 or when quick integration without additional dependencies is needed.

How to encrypt data in SharedPreferences?

For data encryption, use EncryptedSharedPreferences from the AndroidX Security library. It automatically encrypts keys and values using AES-256 GCM. The setup process is minimal: getSharedPreferences is replaced with EncryptedSharedPreferences.create specifying a master key from Android Keystore.

Summary

  • SharedPreferences — built-in Android key-value storage for saving simple app settings in XML format.
  • Supports six data types: String, Int, Boolean, Float, Long and Set<String> with default value specification.
  • Read operations are performed from memory (cache), writing — through Editor with synchronous commit or asynchronous apply.
  • Data is isolated by file name and MODE_PRIVATE mode, accessible only within the creating app.
  • For storing sensitive data, use EncryptedSharedPreferences with AES-256 encryption.
  • For new projects, Google recommends DataStore as a modern asynchronous alternative with coroutines and Flow.
  • SharedPreferences remains the best choice for quickly saving 5–50 simple settings without additional dependencies.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also