If you follow my writing (here or here), then you know I’ve been working on a new Android app called AfterShoot — it’s an AI-powered Android app that helps users take better pictures while also managing their digital waste.

One of the major features that I had to implement in this app was the ability to query a user’s internal storage for all the images—only then will I be able to run any ML inference on them.

Scoped Storage: What is it?

The task of fetching all the images from a user’s storage might seem trivial; after all, multiple StackOverflow links come up as soon as you search this query on google (here, here, here, and here).

But storage on Android has a checkered past, with the implementation being changed multiple times throughout its lifetime. And if you try to run the code provided in any of the answers above on a device running Android 10, you simply won’t get any images! Why you may ask? The answer is scoped storage, which was introduced in Android 10.

Scoped storage essentially limits your app’s access to the user’s internal storage, especially in terms of where it can write its files. You might be wondering, what was the need for such a system? Well, if an app is granted storage permissions, then by default it can write its files anywhere throughout a device’s entire internal storage.

While a best practice is saving your app’s data in the Android/data folder of the user’s internal storage, a lot of apps abuse this by storing their app’s contents all over the place, which leads to bad storage management, as uninstalling the app doesn’t remove these folders.

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.