Paulo Pereira Paulo is a Google-certified Associate Android Developer and has five years of work experience as an Android Developer. He is always looking to improve and learn new things.

Kotlin SharedPreferences data storage guide

5 min read 1515

Kotlin Logo

Did you ever wonder how to store some values on your application without losing them after closing the app? Android provides a way to do that if you have a small collection of key values you’d like to save!

In this article, we’ll take a look at Android’s SharedPreferences APIs and then demonstrate how to use SharedPreferences in a use case.

Jetpack DataStore is a modern solution that uses Kotlin coroutines and Flow to store data asynchronously. In the future, you might consider migrating to Jetpack DataStore from SharedPreferences. However, in this article we’ll focus on SharedPreferences since it remains useful and is still very popular as of this writing.

Jump ahead:

What is SharedPreferences?

SharedPreferences is an Android API that allows you to create and access a file containing a key-values collection. A SharedPreferences object provides some methods for reading and writing these values on the file. Each SharedPreferences file is managed by the framework and can be private to the application or shared.

Accessing

To create or access a SharedPreferences file, you can call either of the following methods: getSharedPreferences() or getDefaultSharedPreferences().

Let’s take a look.

getSharedPreferences(name, mode)

Use the getSharedPreferences() method if you need to create or access a SharedPreferences file identified by name.

Here’s an example of this method:

val sharedPreferences = activity?.getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE)

getDefaultSharedPreferences()

Use the getDefaultSharedPreferences() method to get the default SharedPreferences file for an entire app. You should be aware that this method requires extra dependency.

The below example of this method requires an extra dependency to be added to the build.gradle file at the app module level:

Here’s the dependency:

implementation "androidx.preference:preference-ktx:1.2.0"

Here’s an example of the method:

val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)

Sharing files

The second parameter of the getSharedPreferences method is the mode. This parameter relates to permissions for file sharing.

Sharing files with other applications

To share private files with applications that do not share your user ID, you can use MODE_WORLD_READABLE with Android versions older than 7.0. Android 7.0+ will throw a security exception if you attempt to use this mode; it has been deprecated since API level 17.

If you run into this issue, a workaround is to use a FileProvider with the intent set to FLAG_GRANT_READ_URI_PERMISSION. For more information, also see the official documentation on sharing files.

Sharing files with your application

To share private files with any application that shares your user ID, you can use MODE_PRIVATE.

Reading

To retrieve values from a SharedPreferences file, you can call any of the below methods, providing the key for the value you want and an optional default value to return if the key doesn’t exist:

  • contains(key: String)Use this method to check if the preferences file contains a specific preference
  •  

  • edit()Use this method to create a new Editor, through which you can make atomic changes to the data in the SharedPreferences file
  •  

  • getAll()Use this method to retrieve all values in the SharedPreferences file
  •  



  • getInt(key: String, defValue: Integer)Use this method to retrieve an Integer value from the SharedPreferences file
  •  

  • getBoolean(key: String, defValue: Boolean)Use this method to retrieve a Boolean value from the SharedPreferences file
  •  

  • getFloat(key: String, defValue: Float)Use this method to retrieve a Float value from the SharedPreferences file
  •  

  • getLong(key: String, defValue: Long)Use this method to retrieve a Long value from the SharedPreferences file
  •  

  • getString(key: String, defValue: String)Use this method to retrieve a String value from the SharedPreferences file
  •  

  • getStringSet(key: String, defValues: Set)Use this method to retrieve a set of String values from the SharedPreferences file

Writing

To write values in a SharedPreferences file, create a SharedPreferences.Editor by calling edit() on your SharedPreferences object. With edit(), you’ll be able to call the following methods:

  • putInt(key: String, value: Integer)Use this method to insert an Integer value on the SharedPreferences file
  •  

  • putBoolean(key: String, value: Boolean)Use this method to insert a Boolean value on the SharedPreferences file
  •  


    More great articles from LogRocket:


  • putFloat(key: String, value: Float)Use this method to insert a Float value on the SharedPreferences file
  •  

  • putLong(key: String, value: Long)Use this method to insert a Long value on the SharedPreferences file
  •  

  • putString(key: String, value: String)Use this method to insert a String value on the SharedPreferences file
  •  

  • putStringSet(key: String, values: Set)Use this method to insert a set of String values on the SharedPreferences file

After writing changes, be sure to call apply() or commit() to save your changes. According to the official Android documentation, both apply() and commit() change the in-memory SharedPreferences object immediately but write updates to the disk differently. apply() writes updates asynchronously, whereas commit() writes updates synchronously and could result in paused UI rendering if called from the main thread.

Here’s an example illustrating some of the above functions to retrieve and write values in a SharedPreferences file:

val sharedPref = activity?.getPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE) ?: return
with (sharedPref.edit()) {
    putInt(getString(R.string.saved_high_score_key), newHighScore)
    apply()
}

Detecting changes

To detect changes in a SharedPreferences file, you can call the following methods:

  • registerOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferencechangeListener)Use this method to register a callback that gets invoked when a change happens in the SharedPreferences file
  • unregisterOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferencechangeListener)Use this method to unregister a callback that gets invoked when a change happens in the SharedPreferences file

SharedPreferences use case

Now, we’ll take a look at a common scenario in which SharedPreferences may be useful. Let’s say you want to display an onboarding page the first time a user opens an app.

To make this work, you’ll need to have a Boolean value stored in a SharedPreferences file indicating whether or not it is the first time a particular user has opened the app.

Implementation

To start, open res/values/strings.xml and add the name of our SharedPreferences file.

Next, add the following code to the strings.xml file:

<string name="app_shared_prefs">com.pp.sharedprefs.PREFERENCES_FILE_KEY</string>

You’ll also need to add a key that identifies our stored value. Let’s call it FIRST_TIME_OPENING_KEY.

Add the following code to the strings.xml file:

<string name="first_time_opening">FIRST_TIME_OPENING_KEY</string>

Now, go to your activity and add the following code inside onCreate(savedInstanceState: Bundle?) after setContentView() is called:

getSharedPreferences(getString(R.string.app_shared_prefs), Context.MODE_PRIVATE)?.let { sharedPreferences ->
        val isFirstTimeOpening = sharedPreferences.getBoolean(getString(R.string.first_time_opening), true)

        if (isFirstTimeOpening) {
            showOnboarding()
            with (sharedPreferences.edit()) {
                putBoolean(getString(R.string.first_time_opening), false)
                apply()
            }
        }
}

In the above code, we get access to the file by calling getSharedPreferences(name, mode).

Next, we try to get the value of our FIRST_TIME_OPENING_KEY from the SharedPreferences file. If the value is nonexistent, we return true.

If we return true, this is the first time the user is opening the app. In this case, we show the onboarding screen and change the value of FIRST_TIME_OPENING_KEY to false so the user will not see the onboarding screen again. Then, we call apply() to conclude the changes.

That should do it!

In our use case example, we handled an onboarding screen. However, this solution works for anything that you want to be run only once, when the user opens the app for the first time.

A small extra: Reducing the code length

Since we’re using Kotlin, we can use its power to reduce the code length a bit with Kotlin extensions.

To use Kotlin extensions, create a separate file called SharedPreferencesHelper and then add the following:

fun SharedPreferences.edit(actions: SharedPreferences.Editor.() -> Unit) {
    with (edit()) {
        actions(this)
        apply()
    }
}

The above code will add an extension function called edit to the SharedPreferences interface. The edit() function takes a Kotlin lambda function, which is defined by curly braces and is an extension of SharedPreferences.Editor.

On this extension function, we are already calling apply() at the end, so there’s no need to repeat that when using this extension to add values in the SharedPreferences file.

Go back to the Activity, and replace the following code:

with (sharedPreferences.edit()) {
        putBoolean(getString(R.string.first_time_opening), false)
        apply()
}

With the following snippet:

sharedPreferences.edit {
        putBoolean(getString(R.string.first_time_opening), false)
}

This shorter code should provide the same result!

Conclusion

In this article, we investigated and offered solutions to use SharedPreferences API. We demonstrated how to use SharedPreferences in an example involving an onboarding screen.

For more information on this topic, check out the official docs on: SharedPreferences, Jetpack DataStore, and Kotlin extensions.

Thank you for reading. I hope this article makes your life easier while working with SharedPreferences!

LogRocket: Instantly recreate issues in your Android apps.

LogRocket is an Android monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your Android apps.

LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.

Start proactively monitoring your Android apps — .

Paulo Pereira Paulo is a Google-certified Associate Android Developer and has five years of work experience as an Android Developer. He is always looking to improve and learn new things.

Leave a Reply