Android中關於外部儲存的一些重要函式

yangxi_001發表於2017-02-09
一、簡介
關於Android的資料外部儲存,在API Level 8之前,所有的檔案都是建議放在Environment.getExternalStorageState()目錄下的;從API Level 8開始,對於應用程式的私有檔案應該放在Context.getExternalFilesDir目錄下,非私有的(shared)的檔案應該放在目錄下Environment.getExternalStoragePublicDirectory(String)所指定的目錄下。對於快取檔案應該放在Context.getExternalCacheDir()目錄下。另外在準備把資料儲存外部儲存之前應該先通過Environment.getExternalStorageState()獲取其狀態,再根據其狀態確定其是否可用,如果不可用,可以考慮將資料儲存在內部儲存中。
關於Android的內部儲存可以參照《Android中關於內部儲存的一些重要函式
二、Context中關於外部儲存的重要函式

public abstract File getExternalCacheDir ()

Since: API Level 8

Returns the absolute path to the directory on the external filesystem (that is somewhere on Environment.getExternalStorageDirectory() where the application can place cache files it owns.

This is like getCacheDir() in that these files will be deleted when the application is uninstalled, however there are some important differences:

該函式像getCacheDir() 一樣,儲存在該目錄下的檔案會在解除安裝該應用程式時被刪除。然而又有以下幾點不同:

  • The platform does not monitor the space available in external storage, and thus will not automatically delete these files. Note that you should be managing the maximum space you will use for these anyway, just like with getCacheDir()系統並不會監視外部儲存的可用容量。因此程式設計師應該自己管理其佔用的最大空間,自己做檔案的清理機制
  • External files are not always available: they will disappear if the user mounts the external storage on a computer or removes it. See the APIs onEnvironment for information in the storage state.
  • There is no security enforced with these files. All applications can read and write files placed here. 系統對該目錄下的檔案並沒做安全訪問機制,所有的應用程式都可以讀寫該目錄下的檔案。

Returns
  • Returns the path of the directory holding application cache files on external storage. Returns null if external storage is not currently mounted so it could not ensure the path exists; you will need to call this method again when it is available.
See Also

public abstract File getExternalFilesDir (String type)

Since: API Level 8

Returns the absolute path to the directory on the external filesystem (that is somewhere on Environment.getExternalStorageDirectory()) where the application can place persistent files it owns. These files are private to the applications, and not typically visible to the user as media.

該目錄下的檔案對其應用程式是私有的。其目錄下的檔案也不會被當做多媒體檔案而為使用者所見

This is like getFilesDir() in that these files will be deleted when the application is uninstalled, however there are some important differences:

該函式像 getFilesDir()  一樣,儲存在該目錄下的檔案會在解除安裝該應用程式時被刪除。然而又有以下幾點不同:

  • External files are not always available: they will disappear if the user mounts the external storage on a computer or removes it. See the APIs onEnvironment for information in the storage state.
  • There is no security enforced with these files. All applications can read and write files placed here. 系統對該目錄下的檔案並沒做安全訪問機制,所有的應用程式都可以讀寫該目錄下的檔案。

Here is an example of typical code to manipulate a file in an application's private storage:

void createExternalStoragePrivateFile() {
    /* Create a path where we will place our private file on external
     storage.
     */
    File file = new File(getExternalFilesDir(null), "DemoFile.jpg");
    try {
        /* Very simple code to copy a picture from the application's
           resource into the external file.  Note that this code does
           no error checking, and assumes the picture is small (does not
           try to copy it in chunks).  Note that if external storage is
           not currently mounted this will silently fail.
        */
        InputStream is = getResources().openRawResource(R.drawable.balloons);
        OutputStream os = new FileOutputStream(file);
        byte[] data = new byte[is.available()];
        is.read(data);
        os.write(data);
        is.close();
        os.close();
    } catch (IOException e) {
        /* Unable to create file, likely because external storage is
          not currently mounted.
        */
        Log.w("ExternalStorage", "Error writing " + file, e);
    }
}
void deleteExternalStoragePrivateFile() {
    /* Get path for the file on external storage.  If external
      storage is not currently mounted this will fail.
     */
    File file = new File(getExternalFilesDir(null), "DemoFile.jpg");
    if (file != null) {
        file.delete();
    }
}
boolean hasExternalStoragePrivateFile() {
    /* Get path for the file on external storage.  If external
       storage is not currently mounted this will fail.
    */
    File file = new File(getExternalFilesDir(null), "DemoFile.jpg");
    if (file != null) {
        return file.exists();
    }
    return false;
}

If you supply a non-null type to this function, the returned file will be a path to a sub-directory of the given type. Though these files are not automatically scanned by the media scanner, you can explicitly add them to the media database with MediaScannerConnection.scanFile. Note that this is not the same asEnvironment.getExternalStoragePublicDirectory(), which provides directories of media shared by all applications. The directories returned here are owned by the application, and their contents will be removed when the application is uninstalled. UnlikeEnvironment.getExternalStoragePublicDirectory(), the directory returned here will be automatically created for you.

Here is an example of typical code to manipulate a picture in an application's private storage and add it to the media database:

void createExternalStoragePrivatePicture() {
    /* Create a path where we will place our picture in our own private
       pictures directory.  Note that we don't really need to place a
       picture in DIRECTORY_PICTURES, since the media scanner will see
       all media in these directories; this may be useful with other
       media types such as DIRECTORY_MUSIC however to help it classify
       your media for display to the user.
    */
    File path = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File file = new File(path, "DemoPicture.jpg");
    try {
        /* Very simple code to copy a picture from the application's
           resource into the external file.  Note that this code does
           no error checking, and assumes the picture is small (does not
           try to copy it in chunks).  Note that if external storage is
           not currently mounted this will silently fail.
        */
        InputStream is = getResources().openRawResource(R.drawable.balloons);
        OutputStream os = new FileOutputStream(file);
        byte[] data = new byte[is.available()];
        is.read(data);
        os.write(data);
        is.close();
        os.close();
        /* Tell the media scanner about the new file so that it is
          immediately available to the user.
        */
        MediaScannerConnection.scanFile(this,
                new String[] { file.toString() }, null,
                new MediaScannerConnection.OnScanCompletedListener() {
            public void onScanCompleted(String path, Uri uri) {
                Log.i("ExternalStorage", "Scanned " + path + ":");
                Log.i("ExternalStorage", "-> uri=" + uri);
            }
        });
    } catch (IOException e) {
        /* Unable to create file, likely because external storage is
          not currently mounted.
        */
        Log.w("ExternalStorage", "Error writing " + file, e);
    }
}
void deleteExternalStoragePrivatePicture() {
    /* Create a path where we will place our picture in the user's
      public pictures directory and delete the file.  If external
      storage is not currently mounted this will fail.
    */
    File path = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    if (path != null) {
        File file = new File(path, "DemoPicture.jpg");
        file.delete();
    }
}
boolean hasExternalStoragePrivatePicture() {
    /* Create a path where we will place our picture in the user's
       public pictures directory and check if the file exists.  If
       external storage is not currently mounted this will think the
       picture doesn't exist.
    */
    File path = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    if (path != null) {
        File file = new File(path, "DemoPicture.jpg");
        return file.exists();
    }
    return false;
}

Parameters
type The type of files directory to return. May be null for the root of the files directory or one of the following Environment constants for a subdirectory:DIRECTORY_MUSICDIRECTORY_PODCASTSDIRECTORY_RINGTONESDIRECTORY_ALARMSDIRECTORY_NOTIFICATIONSDIRECTORY_PICTURES, or DIRECTORY_MOVIES.
Returns
  • Returns the path of the directory holding application files on external storage. Returns null if external storage is not currently mounted so it could not ensure the path exists; you will need to call this method again when it is available.
該函式返回的地址將是如下形式:/mnt/sdcard/Android/data/com.lenovo.robin/files
其中為context所對應的應用程式的包名
三、Environment關於外部儲存的重要函式

public static File getExternalStorageDirectory ()

Since: API Level 1

Gets the Android external storage directory. This directory may not currently be accessible if it has been mounted by the user on their computer, has been removed from the device, or some other problem has happened. You can determine its current state with getExternalStorageState().

Note: don't be confused by the word "external" here. This directory can better be thought as media/shared storage. It is a filesystem that can hold a relatively large amount of data and that is shared across all applications (does not enforce permissions). Traditionally this is an SD card, but it may also be implemented as built-in storage in a device that is distinct from the protected internal storage and can be mounted as a filesystem on a computer.

In devices with multiple "external" storage directories (such as both secure app storage and mountable shared storage), this directory represents the "primary" external storage that the user will interact with.

Applications should not directly use this top-level directory, in order to avoid polluting the user's root namespace. Any files that are private to the application should be placed in a directory returned by Context.getExternalFilesDir, which the system will take care of deleting if the application is uninstalled. Other shared files should be placed in one of the directories returned by getExternalStoragePublicDirectory(String).

該函式現在已經不合時宜,在API Level 8後,對於應用程式的私有檔案應該放在Context.getExternalFilesDir目錄下,非私有的(shared)的檔案應該放在目錄下Environment提供的函式getExternalStoragePublicDirectory(String)所指定的目錄下

Here is an example of typical code to monitor the state of external storage:

BroadcastReceiver mExternalStorageReceiver;
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
void updateExternalStorageState() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        mExternalStorageAvailable = mExternalStorageWriteable = true;
    } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        mExternalStorageAvailable = true;
        mExternalStorageWriteable = false;
    } else {
        mExternalStorageAvailable = mExternalStorageWriteable = false;
    }
    handleExternalStorageState(mExternalStorageAvailable,
            mExternalStorageWriteable);
}
void startWatchingExternalStorage() {
    mExternalStorageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("test", "Storage: " + intent.getData());
            updateExternalStorageState();
        }
    };
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
    filter.addAction(Intent.ACTION_MEDIA_REMOVED);
    registerReceiver(mExternalStorageReceiver, filter);
    updateExternalStorageState();
}
void stopWatchingExternalStorage() {
    unregisterReceiver(mExternalStorageReceiver);

public static File getExternalStoragePublicDirectory (String type)

Get a top-level public external storage directory for placing files of a particular type. This is where the user will typically place and manage their own files, so you should be careful about what you put here to ensure you don't erase their files or get in the way of their own organization.

Here is an example of typical code to manipulate a picture on the public external storage:

void createExternalStoragePublicPicture() {
    /* Create a path where we will place our picture in the user's
       public pictures directory.  Note that you should be careful about
       what you place here, since the user often manages these files.  For
       pictures and other media owned by the application, consider
       Context.getExternalMediaDir().
    */
    File path = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    File file = new File(path, "DemoPicture.jpg");
    try {
        // Make sure the Pictures directory exists.
        path.mkdirs();
        /* Very simple code to copy a picture from the application's
           resource into the external file.  Note that this code does
           no error checking, and assumes the picture is small (does not
           try to copy it in chunks).  Note that if external storage is
           not currently mounted this will silently fail.
         */
        InputStream is = getResources().openRawResource(R.drawable.balloons);
        OutputStream os = new FileOutputStream(file);
        byte[] data = new byte[is.available()];
        is.read(data);
        os.write(data);
        is.close();
        os.close();
        /* Tell the media scanner about the new file so that it is
           immediately available to the user.
        */
        MediaScannerConnection.scanFile(this,
                new String[] { file.toString() }, null,
                new MediaScannerConnection.OnScanCompletedListener() {
            public void onScanCompleted(String path, Uri uri) {
                Log.i("ExternalStorage", "Scanned " + path + ":");
                Log.i("ExternalStorage", "-> uri=" + uri);
            }
        });
    } catch (IOException e) {
        /* Unable to create file, likely because external storage is
           not currently mounted.
        */
        Log.w("ExternalStorage", "Error writing " + file, e);
    }
}
void deleteExternalStoragePublicPicture() {
    /* Create a path where we will place our picture in the user's
       public pictures directory and delete the file.  If external
       storage is not currently mounted this will fail.
    */
    File path = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    File file = new File(path, "DemoPicture.jpg");
    file.delete();
}
boolean hasExternalStoragePublicPicture() {
    /* Create a path where we will place our picture in the user's
       public pictures directory and check if the file exists.  If
       external storage is not currently mounted this will think the
       picture doesn't exist.
    */
    File path = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    File file = new File(path, "DemoPicture.jpg");
    return file.exists();

Parameters
type The type of storage directory to return. Should be one of DIRECTORY_MUSICDIRECTORY_PODCASTSDIRECTORY_RINGTONESDIRECTORY_ALARMS,DIRECTORY_NOTIFICATIONSDIRECTORY_PICTURES,
 DIRECTORY_MOVIESDIRECTORY_DOWNLOADS, or DIRECTORY_DCIM. May not be null.
Returns
  • Returns the File path for the directory. Note that this directory may not yet exist, so you must make sure it exists before using it such as with File.mkdirs().
對於Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getAbsolutePath()返回的將是/mnt/sdcard/Movies

public static String getExternalStorageState ()

Since: API Level 1

Gets the current state of the primary "external" storage device.

See getExternalStorageDirectory() for more information.

返回值可以為Environment的以下常量之一
Constants
String MEDIA_BAD_REMOVAL getExternalStorageState() returns MEDIA_BAD_REMOVAL 
if the media was removed before it was unmounted.
String MEDIA_CHECKING getExternalStorageState() returns MEDIA_CHECKING 
if the media is present and being disk-checked
String MEDIA_MOUNTED getExternalStorageState() returns MEDIA_MOUNTED 
if the media is present and mounted at its mount point with read/write access.
String MEDIA_MOUNTED_READ_ONLY getExternalStorageState() returns MEDIA_MOUNTED_READ_ONLY
 if the media is present and mounted at its mount point with read only access.
String MEDIA_NOFS getExternalStorageState() returns MEDIA_NOFS 
if the media is present but is blank or is using an unsupported filesystem
String MEDIA_REMOVED getExternalStorageState() returns MEDIA_REMOVED 
if the media is not present.
String MEDIA_SHARED getExternalStorageState() returns MEDIA_SHARED 
if the media is present not mounted, and shared via USB mass storage.
String MEDIA_UNMOUNTABLE getExternalStorageState() returns MEDIA_UNMOUNTABLE 
if the media is present but cannot be mounted.
String MEDIA_UNMOUNTED getExternalStorageState() returns MEDIA_UNMOUNTED 
if the media is present but not mounted.

結束

轉自:

相關文章