Preparing for Scoped Storage

Android apps targeting Android 11 will be required to use scoped storage to read and write files. In this tutorial, you’ll learn how to migrate your application and also why scoped storage is such a big improvement for the end user. By Carlos Mota.

Leave a rating/review
Download materials
Save for later
Share

Android 10 put a greater emphasis on privacy and security. Android 11 continues this emphasis and gives you many tools to achieve this. One of those tools is scoped storage. This feature impacts your app in a big way if you’re leveraging local file access.

With scoped storage, an app no longer has direct access to all the files in external storage. If an app wants to manipulate a file that it didn’t create, it has to get explicit authorization from the user. These request prompts appear for each file. This provides a new level of control for the user. They can now decide what an app can or cannot do with their files.

Because this can have a potentially heavy impact on existing apps, Android 10 provides an opt-out mechanism. When enabled, it allows an app to work without any of these requirements. The caveat here is that when your app targets API 30 (Android 11), scoped storage starts to be mandatory.

So if your app uses device storage, it’s time to start preparing it for scoped storage.

Note: If you would like to read up on scoped storage in Android 10, take a look at: Scoped Storage in Android 10: Getting Started.

Le Memeify 👌

To learn more about scoped storage, you’ll work on a meme app. You’ll learn a lot and have fun along the way!

The app you’ll work on is called, “Le Memeify”. This app has a built-in interface that allows you to create, edit or delete a meme from any image on your device.

Feel free to share your best memes with your friends. :]

Note: This tutorial assumes that you’re familiar with Android Studio and the basics of Android development. If you’re new to either, read through Beginning Android Development and Kotlin for Android: An Introduction before you continue this tutorial.

Getting Started

Access the tutorial files by clicking on Download Materials at the top or bottom of this tutorial. You’ll find two projects inside the zip file: Starter has the skeleton of the app you’ll build. And Final gives you something to compare your code to when you’re done.

Images gallery

This is what you’re going to build! You already have a whole gallery of memes in the app but feel free to download others. Here’s a website you can use: imgflip.

The goal of this article is to show you how to prepare your app for scoped storage.

There are different ways to do this. The first way you’ll see is in the Starter project which uses file paths to access images and stores them in external storage.

The other way is to follow scoped storage requirements. This method requests user access to manipulate files that weren’t created by the app. If granted, it uses URIs to access those files. Also, it stores new images inside the Pictures folder per Google’s recommendation.

Ready to dive in?

Understanding the Project Structure

Open the Starter project in Android Studio and wait for it to synchronize. Take a look at the project directory structure:
Project structure

You’ll see a set of subfolders and important files:

  • model: This is the data object used to represent an image. It contains the file path, creation date, timestamp, size, etc.
  • ui: In this folder, you’ll find the activity, fragments, view models and adapters you’ll use to allow your users to view and interact with the app’s data. This folder also has two subfolders for the two main screens of the app: details and images.
  • ui/actions.kt: Here you’ll find the Kotlin sealed classes for any action a view might take. This makes things nice and tidy by explicitly listing these actions.
  • FileOperations.kt: This file contains the class that defines all the file operations.
  • Utils.kt: This file has the set of utility methods you’ll use throughout the project.

Running Le Memeify

In order to access the images on your device, you must grant the storage permission when prompted. Otherwise, you’ll see a toast with the message:

  • “You need to grant media permissions to use the app”.

Build and run the app. After you accept the permissions, you’ll see a screen like this:

Images gallery and selection

…with different images, of course. :]

Grokking Scoped Storage

Scoped storage addresses several issues with the Android file system. Namely, it aims to better define which files a third-party app can access, where to store files needed or created by the app and what to do with them after the user uninstalls the app.

Before you start building this app, think about the two different types of storage a device has:

  • App-specific: internal storage: Only the app itself can access the files in this directory, known as the “app sandbox”. Because of this, you don’t need to declare the storage permission in the manifest file. Also, no third-party apps can access its content so it’s a good place to store sensitive information. And when the user uninstalls the app, the system deletes the directory.
  • External storage: This is the non-internal space on the user’s disk. It can include an external drive, like an SD Card. The system will not delete data here when the user uninstalls the app. As such, the user can end up with unused files that only take up space.

With these limitations, Android more strictly controls where an app can store files. It can be either of the following:

  • App-specific: external storage: This storage differs from internal storage in that there’s no pre-allocated space for it in the sandbox. The available storage for saving is equal to the disk’s remaining space. But it’s like internal storage in that you don’t need to declare writing permissions and the system will delete all its files when the user uninstalls the app.
  • External storage: This storage includes access to the device gallery through the MediaStore API. To view/edit other files, you need to use the system file picker called through the Storage Access Framework or SAF.

You’ll need to request two permissions for this if the app is targeting Android 9 or Android 10 with legacy mode enabled:

  • READ_EXTERNAL_STORAGE
  • WRITE_EXTERNAL_STORAGE

Newer versions only require READ_EXTERNAL_STORAGE.

Note: Take a look at Android’s Data Storage documentation to learn more.