Android store data on device

Hello DataStore, Bye SharedPreferences👋 — Android📱 — Part 1: Preference DataStore

In this article series, we’ll learn how to use the latest Android Jetpack 🚀 library i.e. DataStore in Android apps.

Welcome Android developers 👋. This article is the first part of a series article based on the new Jetpack library🚀 i.e. DataStore🗄️. Currently, it’s alpha version is released. Let’s see what’s DataStore and why DataStore.

What is DataStore 🤷‍♀️?

  • Jetpack DataStore is a data storage solution.
  • It allows us to store key-value pairs (like SharedPreferences ) or typed objects with protocol buffers (We’ll see it in next article).
  • DataStore uses Kotlin, Coroutines and Flow to store data asynchronously with consistency and transaction support 😍.
  • In short, it’s the new data storage solution which is the replacement of SharedPreferences .

Why DataStore 🤷‍♂️

  • First and my favourite reason 😃 — Built with❤️ Kotlin, Coroutines and Flow.
  • If you have used SharedPreferences you might abuse or blamed it for something 😆 then DataStore is here to rescue!
  • SharedPreference has some drawbacks like it provided synchronous APIs -but it’s not MAIN-thread-safe! whereas DataStore is safe to use in UI thread because it uses Dispatchers.IO under the hood👀.
  • It’s safe from runtime exceptions!❌⚠️. What would be more satisfying that? 😅
  • It also provides a way to migrate from SharedPreferences 😍.
  • It provides Type safety! (Using Protocol buffers).

These are some reasons which encourage us to use DataStore and finally say goodbye to beloved SharedPreferences 👋.

# That’s not only the reason —

DataStore provides two different types of implementations to store data.

  • Preference DataStore — This uses key-value pairs to store data. But it doesn’t provide type-safety :
  • Proto DataStore — It stores data as a custom type with specified schema using Protocol Buffers (We’ll see about it in the next article).

I think that’s enough introduction to DataStore . It’s time to write some code👨‍💻😎.

Let’s begin code 👨‍💻

You can simply clone or refer this repository to get example code demonstrating DataStore 📁.

We’ll develop a sample Android application which stores a UI mode preference from user i.e. 🌞 Light Mode or 🌑 Dark Mode.

First of all, let’s add a Gradle dependency in build.gradle of your app module. Currently 1.0.0-alpha01 is the latest release. You can keep an eye here to get info about the latest version.

Start implementing DataStore 📁

  • For UI mode preference i.e. Dark mode or Light mode, we’ll create an enum class as below
  • We’ll create a class — SettingsManager where we’ll be managing setting preferences set by users in our app.

This will initialize the instance dataStore field by creating DataStore using the file name as “settings_pref”. createDataStore() is extension function created on Context .

  • Now we’ll be storing UI mode preference using a key (as we managed in SharedPreference ). Key in DataStore is created as below 👇

Here 👆 we’ve created a 🔑 KEY IS_DARK_MODE which will store a boolean value ( false for Light mode / true for Dark mode). Because Preferences DataStore does not use a predefined schema, you must use Preferences.preferencesKey() to define a key for each value that you need to store in the DataStore

  • Now we’ll create a method which will set UI mode from our UI/Activity i.e. setUiMode() 🔧

Note: Preferences DataStore provides a method edit() which transactional updates value in DataStore .

  • Now it’s time to get preference 🔥. DataStore provides data property which exposes the preference values using Flow . Means it’s time to leverage Flow 🌊 😍. See the code below 👇

👆 You can see we’ve exposed a Flow uiModeFlow which will emit values whenever preferences are edited/updated. If you remember, we have been storing boolean in our DataStore . Using map<> , we’re mapping boolean values to the UiMode i.e UiMode.LIGHT or UiMode.DARK .

Note: DataStore throws IOException when it failed to read a value. So we have handled it by emitting emptyPreferences() .

So that’s all about setting up DataStore 😃. Now let’s design UI.

Setup Activity

In this activity, We have just an ImageButton which will have image resources i.e. 🌞 and 🌘 based on UI mode.

  • In initViews() we’ll update preferences (UI Mode) on click of ImageButton .
  • In observeUiPreferences() , we’ll observe DataStore UI Mode preference using a field which we exposed in SettingsManager which is a Flow 🌊 which will emit values whenever preferences are updated.
Читайте также:  Gun club для андроида

👆 Here we’ve used asLiveData() flow extension function which gives emitted values from Flow in LiveData . (Otherwise, we can also use lifecycleScope.launch<> here if you don’t like to use LiveData ).

  • We’re just updating image resource and background color of root layout when UI mode is changed. (Actual mode can be changed using AppCompatDelegate. setDefaultNightMode() )

Yeah! That’s it 😃. It’s time to run this app 🚀. When you run this app, you’ll see it like 👇

Looking Awesome! 😍, isn’t it?

This is how we implemented Preferences DataStore instead of SharedPreferences .

So, DataStore is cool 🆒, isn’t it? Give it a try 😃. Since it’s currently in alpha, maybe many more is on the way to come 🛣️.

DataStore uses file management mechanism for storing data. But it’s different than managed in SharedPreferences . Now if you want to see how’s your data getting stored then using Android Studio’s ‘Device File Explorer’ you can go to /data/app/YOUR_APP_PACKAGE_NAME/files/datastore and you can see the file there like below 👇.

But it’s content is not readable as you can see in below image 👇

Источник

How to store data locally in an Android app

Almost every app we use or develop has to store data for one purpose or another. It’s not all the same data, either — some apps need access to settings, images, and much more. The big question is how to manage this data so that your device can grab only what it needs. Luckily for developers, Android is full of ways to store data, and we’re here to run you through how they work.

For this article, we’ll discuss the different data storage techniques available to Android developers, along with sample code to get you started or to refresh your memory.

Ways to store data

Using Shared Preferences

Shared Preferences is the way to go if you’re saving primitive data as key-value pairs. It requires a key, which is a String, and the corresponding value for the said key. The value can be any of the following: a boolean, float, int, long, or another string.

Your Android device stores each app’s Shared Preferences inside of an XML file in a private directory. Apps can also have more than one Shared Preferences file, and they’re ideally used to store app preferences.

Before you can store data with shared preferences, you must first get a SharedPreferences object. There are two Context methods that you can use to retrieve a SharedPreferences object.

For when your app will have a single preferences file, and

for when your app could have multiple preferences files, or if you prefer to name your SharedPreferences instance.

On getting the SharedPreferences object, you then access its Editor using the edit() method. To actually add a value, use the Editor’s putXXX() method, where XXX is one of Boolean, String, Float, Long, Int, or StringSet. You can also remove a key-value preference pair with remove().

Finally, make sure to call the Editor’s commit() method after putting or removing values. If you don’t call commit, your changes will not be persisted.

For our sample app, we allow the user to specify a SharedPreferences filename. If the user specifies a name, we request for the SharedPreferences with that name; if not, we request the default SharedPreference object.

Unfortunately, there is no way to get a single list of all SharedPreferences files stored by your app. Instead, you will need a static list or access to the SharedPreferences name if you’re storing more than one file.

You could also save your SharedPreferences names in the default file. If you need to store user preferences, you may want to use the PreferenceActivity or PreferenceFragment command. Just remember that they both use Shared Preferences, too.

Using internal storage

There are plenty of times where you may need to persist data, but you find Shared Preferences too limiting. For example, you may need to persist objects or images in Java. You might also need to persist your data logically with the file system hierarchy. This is where internal storage comes in. It is specifically for when you need to store data on the file system, but you don’t want other apps or users to have access.

This data storage is so private, in fact, that it’s deleted from the device as soon as you uninstall your app.

Using internal storage is similar to saving with any other file system. You can get references to File objects, and you can store data of virtually any type using a FileOutputStream. What sets it apart is the fact that its contents are only accessible by your app.

Читайте также:  Fl studio для андроид инструменты

To get access to your internal file directory, use the Context getFilesDir() method. To create (or access) a directory within this internal file directory, use the getDir(directoryName, Context.MODE_XXX) method. The getDir() method returns a reference to a File object representing the specified directory, creating it first if it doesn’t exist.

In the sample above, if the user-specified filename is empty, we get the base internal storage directory. If the user specifies a name, we get the named directory, creating first if needed.

To read files, use your preferred file reading method. For our example, we read the complete file using a Scanner object. To read a file that’s directly within your internal storage directory (not in any subdirectory), you can use the openFileInput(fileName) method.

Similarly, to access a file for writing directly within the Internal Storage directory, use the openFileOutput(fileName) method. To save files, we use the FileOutputStream write.

As you can see in the image above, the file path is in a folder not accessible by the file manager or other apps. The only exception to this will be if you have a rooted device.

External Storage

Google has made a few key changes to external storage, beginning with Android 10 and continuing in Android 11. To give users better control over their files and cut down on clutter, apps now have scoped access to external storage by default. This means that they can tap into the specific directory on external storage and the media that the app creates.

For more information about requesting scoped directory access, check out this Android developer tutorial.

If your app tries to access a file that it did not create, you will have to permit it to do so every single time. Data you store outside of select folders will also disappear if you delete your app.

Apps are expected to store files in one of two app-specific locations designed for the app’s specific persistent files and cached files, respectively. To access these locations, the app must verify the storage is available (which is not guaranteed, as it is for internal storage). The volume’s state can be queried using:

If MEDIA_MOUNTED is returned, that means you can read and write files to external storage. You will find a number of predefined directories that should aid with logical storage and prevent clutter. These include the likes of DIRECTORY_DOCUMENTS and DIRECTORY_MOVIES.

You can read a full explanation of how to use scoped storage here.

SQLite database

Finally, Android provides support for apps to use SQLite databases for data storage. The databases you create remain specific to your app and can only be accessed inside your app. Of course, you should have at least some knowledge of SQL before you attempt to store data with an SQLite database.

We’ll discuss each of these in turn, and we use data binding techniques for our sample code. Android provides complete support for SQLite databases. The recommended way of creating SQLite databases is to subclass the SQLiteOpenHelper class and override the onCreate() method. For this sample, we create a single table.

Источник

Data and file storage overview

Android uses a file system that’s similar to disk-based file systems on other platforms. The system provides several options for you to save your app data:

  • App-specific storage: Store files that are meant for your app’s use only, either in dedicated directories within an internal storage volume or different dedicated directories within external storage. Use the directories within internal storage to save sensitive information that other apps shouldn’t access.
  • Shared storage: Store files that your app intends to share with other apps, including media, documents, and other files.
  • Preferences: Store private, primitive data in key-value pairs.
  • Databases: Store structured data in a private database using the Room persistence library.

The characteristics of these options are summarized in the following table:

Type of content Access method Permissions needed Can other apps access? Files removed on app uninstall?
App-specific files Files meant for your app’s use only From internal storage, getFilesDir() or getCacheDir()

From external storage, getExternalFilesDir() or getExternalCacheDir()

Never needed for internal storage

Not needed for external storage when your app is used on devices that run Android 4.4 (API level 19) or higher

No Yes
Media Shareable media files (images, audio files, videos) MediaStore API READ_EXTERNAL_STORAGE when accessing other apps’ files on Android 11 (API level 30) or higher

READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE when accessing other apps’ files on Android 10 (API level 29)

Permissions are required for all files on Android 9 (API level 28) or lower

Yes, though the other app needs the READ_EXTERNAL_STORAGE permission No
Documents and other files Other types of shareable content, including downloaded files Storage Access Framework None Yes, through the system file picker No
App preferences Key-value pairs Jetpack Preferences library None No Yes
Database Structured data Room persistence library None No Yes

The solution you choose depends on your specific needs:

How much space does your data require? Internal storage has limited space for app-specific data. Use other types of storage if you need to save a substantial amount of data. How reliable does data access need to be? If your app’s basic functionality requires certain data, such as when your app is starting up, place the data within internal storage directory or a database. App-specific files that are stored in external storage aren’t always accessible because some devices allow users to remove a physical device that corresponds to external storage. What kind of data do you need to store? If you have data that’s only meaningful for your app, use app-specific storage. For shareable media content, use shared storage so that other apps can access the content. For structured data, use either preferences (for key-value data) or a database (for data that contains more than 2 columns). Should the data be private to your app? When storing sensitive data—data that shouldn’t be accessible from any other app—use internal storage, preferences, or a database. Internal storage has the added benefit of the data being hidden from users.

Categories of storage locations

Android provides two types of physical storage locations: internal storage and external storage. On most devices, internal storage is smaller than external storage. However, internal storage is always available on all devices, making it a more reliable place to put data on which your app depends.

Removable volumes, such as an SD card, appear in the file system as part of external storage. Android represents these devices using a path, such as /sdcard .

Apps themselves are stored within internal storage by default. If your APK size is very large, however, you can indicate a preference within your app’s manifest file to install your app on external storage instead:

Permissions and access to external storage

On earlier versions of Android, apps needed to declare the READ_EXTERNAL_STORAGE permission to access any file outside the app-specific directories on external storage. Also, apps needed to declare the WRITE_EXTERNAL_STORAGE permission to write to any file outside the app-specific directory.

More recent versions of Android rely more on a file’s purpose than its location for determining an app’s ability to access, and write to, a given file. In particular, if your app targets Android 11 (API level 30) or higher, the WRITE_EXTERNAL_STORAGE permission doesn’t have any effect on your app’s access to storage. This purpose-based storage model improves user privacy because apps are given access only to the areas of the device’s file system that they actually use.

Android 11 introduces the MANAGE_EXTERNAL_STORAGE permission, which provides write access to files outside the app-specific directory and MediaStore . To learn more about this permission, and why most apps don’t need to declare it to fulfill their use cases, see the guide on how to manage all files on a storage device.

Scoped storage

To give users more control over their files and to limit file clutter, apps that target Android 10 (API level 29) and higher are given scoped access into external storage, or scoped storage, by default. Such apps have access only to the app-specific directory on external storage, as well as specific types of media that the app has created.

Use scoped storage unless your app needs access to a file that’s stored outside of an app-specific directory and outside of a directory that the MediaStore APIs can access. If you store app-specific files on external storage, you can make it easier to adopt scoped storage by placing these files in an app-specific directory on external storage. That way, your app maintains access to these files when scoped storage is enabled.

To prepare your app for scoped storage, view the storage use cases and best practices guide. If your app has another use case that isn’t covered by scoped storage, file a feature request. You can temporarily opt-out of using scoped storage.

View files on a device

To view the files stored on a device, use Android Studio’s Device File Explorer.

Additional resources

For more information about data storage, consult the following resources.

Videos

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.

Источник

Читайте также:  About android developer tools
Оцените статью