Using Android’s external storage effectively and judiciously

All Android devices offer the user some form of external storage. The storage may be a separate partition of flash memory in the device or bone-fide external storage like an SD-memory card.  As developers we need to be aware of the pros and cons of using this type of storage.

Don’t forget to ask permission!

If your App is going to use external memory in any way then you will need to request permission to do so in your AndroidManifest.xml file.

<uses-permission 
  android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Don’t assume that the external memory is available

External memory can be unavailable for many reasons including:

  • User has mounted it as a disk drive on their computer
  • User does not have an SD-Card
  • User has an SD-Card, but it is ejected
  • etc.

Whenever you need to access external storage you should check to see if it is available:

private boolean externalStorageAvailable() {
  return 
    Environment.MEDIA_MOUNTED
      .equals(Environment.getExternalStorageState());
}

This is fine for a one-shot check.  It is also possible to use a BroadcastReceiver to listen continually for events telling you whether the storage is available or not.  Have a look at this file for a good example.

Don’t hardcode the path to external memory

I’ve seen a number of examples of hardcoding “/mnt/sdcard” as the path to external storage but this won’t always work.  To make life more complicated some devices have multiple external storage points.  The safe and recommended way to get this path is to call Environment.getExternalStorageDirectory() and on my Nexus 4 this returns “/storage/emulated/0”.  

Don’t pollute the external memory

The SDK provides us with handy methods to determine where to put our stuff.  These places will be deleted automatically when a user removes our apps and this keeps things tidy.

We developers should not use directories in the root of the external storage unless we have a good reason to do so.  A good reason to do this is if you need to backup some files that need to persist after the user uninstalls your app.  Recently I had to do this to support my users in migrating their data an old version of my dictionary app to a new version.

If you want to support persistence between multiple App uninstall and reinstall cycles a better approach may be to use Android’s cloud based backup APIs.

The SDK gives us two methods that we can use:

Both of these methods will combine Environment.getExternalStorageDirectory() with the package name that we used in our App’s AndroidManifest.xml file.

Let’s look at some examples if our App’s package name is “com.mbcdev.blog.dirs”:

Calling getExternalFilesDir(null) gives us a root directory for any general files that we want to store.

/storage/emulated/0/Android/data/com.mbcdev.blog.dirs/files

We can also specify a type rather than null which will give us the following paths.  Not all of these are super-useful.

Alarms

getExternalFilesDir(Environment.DIRECTORY_ALARMS)
/storage/emulated/0/Android/data/com.mbcdev.blog.dirs/files/Alarms

DCIM (more info here)

getExternalFilesDir(Environment.DIRECTORY_DCIM)
 /storage/emulated/0/Android/data/com.mbcdev.blog.dirs/files/DCIM

Downloads:

getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
/storage/emulated/0/Android/data/com.mbcdev.blog.dirs/files/Download

Movies

getExternalFilesDir(Environment.DIRECTORY_MOVIES)
/storage/emulated/0/Android/data/com.mbcdev.blog.dirs/files/Movies

Ringtones:

getExternalFilesDir(Environment.DIRECTORY_RINGTONES)
/storage/emulated/0/Android/data/com.mbcdev.blog.dirs/files/Ringtones

Music:

getExternalFilesDir(Environment.DIRECTORY_MUSIC)
/storage/emulated/0/Android/data/com.mbcdev.blog.dirs/files/Music

Pictures:

getExternalFilesDir(Environment.DIRECTORY_PICTURES)
/storage/emulated/0/Android/data/com.mbcdev.blog.dirs/files/Pictures

Podcasts:

getExternalFilesDir(Environment.DIRECTORY_PODCASTS)
/storage/emulated/0/Android/data/com.mbcdev.blog.dirs/files/Podcasts

Notifications:

getExternalFilesDir(Environment.DIRECTORY_NOTIFICATIONS)
/storage/emulated/0/Android/data/com.mbcdev.blog.dirs/files/Notifications

The getExternalCacheDir() method provides us with a path in which to store our caches. Unlike cache directories on internal storage this one can be used for large amounts of data.

getExternalCacheDir()
/storage/emulated/0/Android/data/com.mbcdev.blog.dirs/cache

2 thoughts on “Using Android’s external storage effectively and judiciously

  1. Hello, Thanks for the blog.

    I am using MotoXT 1068 with Kitkat installed. When I call getExternalFilesDir(null) I a get the warning in logcat as
    “W/ContextImpl(9130): Failed to ensure directory: /storage/sdcard1/Android/data/com.appPackage.appName/files”

    What could be the reason ? Write permission is given to app. The file system is mounted.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s