How to Save Files to Device Storage

From wizarPOS
Revision as of 08:28, 25 March 2020 by Jeff (talk | contribs)

Please refer to the specification, Save files on device storage from developer.android.com.

  • Save to a public directory

If you want to save public files on an external store, use the getExternalStoragePublicDirectory() method to get the corresponding directory on the external store. This method takes a parameter, such as DIRECTORY_MUSIC or DIRECTORY_PICTURES, to specify the type of files to save so that they can be classified with other public files. The sample code is as follows:

public File getPublicAlbumStorageDir(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;
}
  • Save to a private directory

If you want to save files on external storage that are private to your app and not accessible by the MediaStore content provider, you can acquire a directory that's used by only your app by calling getExternalFilesDir() and passing it a name indicating the type of directory you'd like. Each directory created this way is added to a parent directory that encapsulates all your app's external storage files, which the system deletes when the user uninstalls your app.

Caution: Files on external storage are not always accessible, because users can mount the external storage to a computer for use as a storage device. So if you need to store files that are critical to your app's functionality, you should instead store them on internal storage.

For example, here's a method you can use to create a directory for an individual photo album:

public File getPrivateAlbumStorageDir(Context context, String albumName) {
    // Get the directory for the app's private pictures directory.
    File file = new File(context.getExternalFilesDir(
            Environment.DIRECTORY_PICTURES), albumName);
    if (!file.mkdirs()) {
        Log.e(LOG_TAG, "Directory not created");
    }
    return file;
}

If none of the pre-defined sub-directory names suit your files, you can instead call getExternalFilesDir() and pass null. This returns the root directory for your app's private directory on the external storage.

Remember that getExternalFilesDir() creates a directory that is deleted when the user uninstalls your app. If the files you're saving should remain available after the user uninstalls your app—such as when your app captures photos and the user should keep those photos—you should instead save the files to a public directory.

Regardless of whether you use getExternalStoragePublicDirectory() for files that are shared or getExternalFilesDir() for files that are private to your app, it's important that you use directory names provided by API constants like DIRECTORY_PICTURES. These directory names ensure that the files are treated properly by the system. For instance, files saved in DIRECTORY_RINGTONES are categorized by the system media scanner as ringtones instead of music.

  • Select between multiple storage locations

Sometimes, a device that allocates a partition of the internal memory for use as the external storage also provides an SD card slot. This means that the device has two different external storage directories, so you need to select which one to use when writing "private" files to the external storage.

Beginning with Android 4.4 (API level 19), you can access both locations by calling getExternalFilesDirs(), which returns a File array with entries for each storage 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 your app supports Android 4.3 and lower, you should use the support library's static method, ContextCompat.getExternalFilesDirs(). This always returns a File array, but if the device is running Android 4.3 and lower, then it contains just one entry for the primary external storage (if there's a second storage location, you cannot access it on Android 4.3 and lower).

getExternalFilesDirs():

    File[] externalFilesDirs = getExternalFilesDirs("test" /* Environment.DIRECTORY_MUSIC/Environment.DIRECTORY_PICTURES等 */ );
    if (externalFilesDirs.length > 1){
        File testFile = new File(externalFilesDirs[1].getAbsolutePath()+"/test.txt");
        try {
            testFile.createNewFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

PS.getExternalStoragePublicDirectory()/getExternalFilesDir(), the return of these method is the primary external storage(/storage/emulated/0/).