From d13afd69c062d2dab2063ab90b21a2941f2099ac Mon Sep 17 00:00:00 2001
From: Scott Main
It's possible that a device using a partition of the -internal storage for the external storage may also offer an SD card slot. In this case, -the SD card is not part of the external storage and your app cannot access it (the extra -storage is intended only for user-provided media that the system scans).
-Caution: External storage can become unavailable if the user mounts the external storage on a computer or removes the media, and there's no security enforced upon files you save to the external storage. All applications can read and write files placed on the external storage and the user can remove them.
+In order to read or write files on the external storage, your app must acquire the +{@link android.Manifest.permission#READ_EXTERNAL_STORAGE} +or {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} system +permissions. For example:
++<manifest ...> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + ... +</manifest> ++ +
If you need to both read and write files, then you need to request only the +{@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission, because it +implicitly requires read access as well.
+ +Note: Beginning with Android 4.4, these permissions are not +required if you're reading or writing only files that are private to your app. For more +information, see the section below about +saving files that are app-private.
+ +Before you do any work with the external storage, you should always call {@link android.os.Environment#getExternalStorageState()} to check whether the media is available. The media might be mounted to a computer, missing, read-only, or in some other state. For example, -here's how you can check the availability:
+here are a couple methods you can use to check the availability:-boolean mExternalStorageAvailable = false; -boolean mExternalStorageWriteable = false; -String state = Environment.getExternalStorageState(); - -if (Environment.MEDIA_MOUNTED.equals(state)) { - // We can read and write the media - mExternalStorageAvailable = mExternalStorageWriteable = true; -} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { - // We can only read the media - mExternalStorageAvailable = true; - mExternalStorageWriteable = false; -} else { - // Something else is wrong. It may be one of many other states, but all we need - // to know is we can neither read nor write - mExternalStorageAvailable = mExternalStorageWriteable = false; +/* Checks if external storage is available for read and write */ +public boolean isExternalStorageWritable() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state)) { + return true; + } + return false; +} + +/* Checks if external storage is available to at least read */ +public boolean isExternalStorageReadable() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state) || + Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { + return true; + } + return false; }-
This example checks whether the external storage is available to read and write. The -{@link android.os.Environment#getExternalStorageState()} method returns other states that you +
The {@link android.os.Environment#getExternalStorageState()} method returns other states that you might want to check, such as whether the media is being shared (connected to a computer), is missing entirely, has been removed badly, etc. You can use these to notify the user with more information when your application needs to access the media.
-If you're using API Level 8 or greater, use {@link
-android.content.Context#getExternalFilesDir(String) getExternalFilesDir()} to open a {@link
-java.io.File} that represents the external storage directory where you should save your
-files. This method takes a type
parameter that specifies the type of subdirectory you
-want, such as {@link android.os.Environment#DIRECTORY_MUSIC} and
-{@link android.os.Environment#DIRECTORY_RINGTONES} (pass null
to receive
-the root of your application's file directory). This method will create the
-appropriate directory if necessary. By specifying the type of directory, you
-ensure that the Android's media scanner will properly categorize your files in the system (for
-example, ringtones are identified as ringtones and not music). If the user uninstalls your
-application, this directory and all its contents will be deleted.
If you're using API Level 7 or lower, use {@link -android.os.Environment#getExternalStorageDirectory()}, to open a {@link -java.io.File} representing the root of the external storage. You should then write your data in the -following directory:
--/Android/data/<package_name>/files/ --
The {@code <package_name>} is your Java-style package name, such as "{@code -com.example.android.app}". If the user's device is running API Level 8 or greater and they -uninstall your application, this directory and all its contents will be deleted.
+Include an empty file named {@code .nomedia} in your external files directory (note the dot -prefix in the filename). This will prevent Android's media scanner from reading your media -files and including them in apps like Gallery or Music.
+prefix in the filename). This prevents media scanner from reading your media +files and providing them to other apps through the {@link android.provider.MediaStore} +content provider. However, if your files are truly private to your app, you should +save them in an app-private directory.Generally, new files that the user may acquire through your app should be saved to a "public" +location on the device where other apps can access them and the user can easily copy them from the +device. When doing so, you should use to one of the shared public directories, such as {@code +Music/}, {@code Pictures/}, and {@code Ringtones/}.
-If you want to save files that are not specific to your application and that should not -be deleted when your application is uninstalled, save them to one of the public directories on the -external storage. These directories lay at the root of the external storage, such as {@code -Music/}, {@code Pictures/}, {@code Ringtones/}, and others.
- -In API Level 8 or greater, use {@link +
To get a {@link java.io.File} representing the appropriate public directory, call {@link android.os.Environment#getExternalStoragePublicDirectory(String) -getExternalStoragePublicDirectory()}, passing it the type of public directory you want, such as +getExternalStoragePublicDirectory()}, passing it the type of directory you want, such as {@link android.os.Environment#DIRECTORY_MUSIC}, {@link android.os.Environment#DIRECTORY_PICTURES}, -{@link android.os.Environment#DIRECTORY_RINGTONES}, or others. This method will create the -appropriate directory if necessary.
- -If you're using API Level 7 or lower, use {@link -android.os.Environment#getExternalStorageDirectory()} to open a {@link java.io.File} that represents -the root of the external storage, then save your shared files in one of the following -directories:
- -Music/
- Media scanner classifies all media found here as user music.Podcasts/
- Media scanner classifies all media found here as a podcast.Ringtones/
- Media scanner classifies all media found here as a ringtone.Alarms/
- Media scanner classifies all media found here as an alarm sound.Notifications/
- Media scanner classifies all media found here as a notification
-sound.Pictures/
- All photos (excluding those taken with the camera).Movies/
- All movies (excluding those taken with the camcorder).Download/
- Miscellaneous downloads.For example, here's a method that creates a directory for a new photo album in +the public pictures directory:
-If you're using API Level 8 or greater, use {@link -android.content.Context#getExternalCacheDir()} to open a {@link java.io.File} that represents the -external storage directory where you should save cache files. If the user uninstalls your -application, these files will be automatically deleted. However, during the life of your -application, you should manage these cache files and remove those that aren't needed in order to -preserve file space.
- -If you're using API Level 7 or lower, use {@link -android.os.Environment#getExternalStorageDirectory()} to open a {@link java.io.File} that represents -the root of the external storage, then write your cache data in the following directory:
--/Android/data/<package_name>/cache/ ++public File getAlbumStorageDir(String albumName) { + // Get the directory for the user's public pictures directory. + File file = new File(Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_PICTURES), albumName); + if (!file.mkdirs()) { + Log.e(LOG_TAG, "Directory not created"); + } + return file; +} ++ + + +Saving files that are app-private
+ +If you are handling files that are not intended for other apps to use +(such as graphic textures or sound effects used by only your app), you should use +a private storage directory on the external storage by calling {@link +android.content.Context#getExternalFilesDir(String) getExternalFilesDir()}. +This method also takes a
+ +type
argument to specify the type of subdirectory +(such as {@link android.os.Environment#DIRECTORY_MOVIES}). If you don't need a specific +media directory, passnull
to receive +the root directory of your app's private directory.Beginning with Android 4.4, reading or writing files in your app's private +directories does not require the {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} +or {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} +permissions. So you can declare the permission should be requested only on the lower versions +of Android by adding the {@code maxSdkVersion} +attribute:
++<manifest ...> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" + android:maxSdkVersion="18" /> + ... +</manifest>-The {@code <package_name>} is your Java-style package name, such as "{@code -com.example.android.app}".
+ +Note: +When the user uninstalls your application, this directory and all its contents are deleted. +Also, the system media scanner does not read files in these directories, so they are not accessible +from the {@link android.provider.MediaStore} content provider. As such, you should not +use these directories for media that ultimately belongs to the user, such as photos +captured or edited with your app, or music the user has purchased with your app—those +files should be saved in the public directories.
+ +Sometimes, a device that has allocated a partition of the +internal memory for use as the external storage may also offer an SD card slot. +When such a device is running Android 4.3 and lower, the {@link +android.content.Context#getExternalFilesDir(String) getExternalFilesDir()} method provides +access to only the internal partition and your app cannot read or write to the SD card. +Beginning with Android 4.4, however, you can access both locations by calling +{@link android.content.Context#getExternalFilesDirs getExternalFilesDirs()}, +which returns a {@link +java.io.File} array with entries each location. The first entry in the array is considered +the primary external storage and you should use that location unless it's full or +unavailable. If you'd like to access both possible locations while also supporting Android +4.3 and lower, use the support library's +static method, {@link android.support.v4.content.ContextCompat#getExternalFilesDirs +ContextCompat.getExternalFilesDirs()}. This also returns a {@link +java.io.File} array, but always includes only one entry on Android 4.3 and lower.
+ +Caution Although the directories provided by {@link +android.content.Context#getExternalFilesDir(String) getExternalFilesDir()} and {@link +android.content.Context#getExternalFilesDirs getExternalFilesDirs()} are not accessible by the +{@link android.provider.MediaStore} content provider, other apps with the {@link +android.Manifest.permission#READ_EXTERNAL_STORAGE} permission can access all files on the external +storage, including these. If you need to completely restrict access for your files, you should +instead write your files to the internal storage.
+ + + + + +Saving cache files
+ +To open a {@link java.io.File} that represents the +external storage directory where you should save cache files, call {@link +android.content.Context#getExternalCacheDir()}. If the user uninstalls your +application, these files will be automatically deleted.
+ +Similar to {@link android.support.v4.content.ContextCompat#getExternalFilesDirs +ContextCompat.getExternalFilesDirs()}, mentioned above, you can also access a cache directory on +a secondary external storage (if available) by calling +{@link android.support.v4.content.ContextCompat#getExternalCacheDirs +ContextCompat.getExternalCacheDirs()}.
+ +Tip: +To preserve file space and maintain your app's performance, +it's important that you carefully manage your cache files and remove those that aren't +needed anymore throughout your app's lifecycle.
+ -- cgit v1.1