The Storage Situation: Removable Storage
Back in 2014, I wrote a series of blog posts to try to clear up confusion around where you can read and write files in Android. I updated them in 2017 to reflect changes in Android… but Android keeps changing.
This post is an updated edition of the 2017 post on removable storage.
Working with files on the filesystem in Android is seriously confusing. It was confusing in 2008, and it has only gotten more confusing as the years rolled on. There are countless Stack Overflow questions and the like where they clearly do not quite grok the various pieces of Android’s storage model.
This is the third post in a series covering this storage model, to help clarify what is going on. Earlier, we looked at internal storage and external storage. Today, we will look at removable storage, the source of an unfortunate amount of angst.
What Your Users Think “Removable Storage” Means
Many of your users will have a device that has some sort of removable media. Often times this is a micro SD card. Some tablets or docks have a full SD card slot. Plus, USB mass storage is possible via USB On-The-Go and USB Type C connectors (not to mention devices or docks with a full USB host port).
Your users will think that they can work with removable storage much like they can with a desktop or notebook.
Unfortunately, your users are largely mistaken, and are even more mistaken with Android 4.4+. That’s because Google’s approach towards removable storage is… unconventional.
What Google Thinks “Removable Storage” Means
In the beginning, external storage was often in the form
of a removable micro SD card. At that time, many developers got in the habit of
thinking that external storage
== removable storage.
However, as Android 3.0 and higher started rolling out en masse, developers soon started to realize two things:
External storage != removable storage on most of those devices
There’s nothing in the Android SDK for removable storage
That’s right: until Android 4.4, there was no official support for removable media in Android. Quoting Dianne Hackborn:
…keep in mind: until Android 4.4, the official Android platform has not supported SD cards at all except for two special cases: the old school storage layout where external storage is an SD card (which is still supported by the platform today), and a small feature added to Android 3.0 where it would scan additional SD cards and add them to the media provider and give apps read-only access to their files (which is also still supported in the platform today).
Android 4.4 is the first release of the platform that has actually allowed applications to use SD cards for storage. Any access to them prior to that was through private, unsupported APIs. We now have a quite rich API in the platform that allows applications to make use of SD cards in a supported way, in better ways than they have been able to before: they can make free use of their app-specific storage area without requiring any permissions in the app, and can access any other files on the SD card as long as they go through the file picker, again without needing any special permissions.
But… But… But… What About All These Apps That Used Removable Media?
They fall into three buckets:
Some are just relying on
MediaStoreindexing. So, for example, a video player can find out about videos on all available media by querying the
MediaStore, and if the device manufacturer hasn’t broken the
MediaStoreindexing of removable media, the player will be able to play back videos on removable media. This strategy is broken on Android 10 and higher.
Some are apps that ship with the hardware. The hardware manufacturer knows the device and what the rules of the game are for that device. The hardware manufacturer is also far less concerned about cross-device compatibility, as their apps aren’t (usually) shipping on the Play Store. Hence, a hardware manufacturer has carte blanche to work with removable media.
Some are apps written by developers who decided to go past the boundaries of the Android SDK. There are various recipes online for examining various Linux system files (and file-like substances) to determine what “mount points” exist, and from there apply some heuristics to determine what represents removable media. While reliability across devices could easily be an issue, beyond that, these techniques at least sorta worked… until Android 4.4, when everything changed.
What Happened in Android 4.4
Starting with Android 4.2, there was a request from Google for device manufacturers to lock down removable media. Generally, this was ignored.
For Android 4.4+, Google amended the Compatibility Test Suite (CTS) that device manufacturers must comply with in order to ship a device containing Google’s proprietary apps (e.g., Play Store, Maps, Gmail; otherwise known as “GMS”). Quoting Dave Smith:
However, new tests were added in CTS for 4.4 that validate whether or not secondary storage has the proper read-only permissions in non app-specific directories, presumably because of the new APIs to finally expose those paths to application developers. As soon as CTS includes these rules, OEMs have to support them to keep shipping devices with GMS (Google Play, etc.) on-board.
As a result, apps were able to read files on removable media using the various undocumented and unsupported tricks for finding removable media. However, apps cannot write to or otherwise modify such removable storage. Note that device manufacturers themselves may have ways of dealing with this, but ordinary app developers do not.
However, we were given
Android 4.4. Android 5.0 added
getExternalMediaDirs(). These methods give us
locations on external and removable storage into which our apps can write. We
do not need any permissions to use them — not even the runtime permissions from
Android 6.0. However, the filesystem locations are a bit user-hostile and the content
that we place in those directories will be removed when the app is uninstalled.
What Happened in Android 10
Removable storage, like external storage, was largely locked down. We still have access to the locations from the aforementioned methods. However, any other “back door” approaches that developers used were completely shut down.
This blog post has much more detail on what Android 10 did to external storage, and all that also applies to removable storage.
Should I Hardcode Paths in My App?
Other Posts in This Series
This series includes:
Interested in learning Kotlin? Check out the Klassbook for Kotlin language lessons that you can run right in your browser!