1. 程式人生 > >Android檔案儲存路徑分析

Android檔案儲存路徑分析

1.internal or external storage

image
image
內部儲存和外部儲存的對比:
1.內部儲存永遠可以訪問,由於外部儲存可能是SD卡,可能無法訪問;
2.內部儲存檔案只有本App才能訪問,外部儲存檔案可以共享給其他APP;
3.解除安裝APP,相應的內部儲存檔案被系統刪除;對於外部儲存,除非使用getExternalFilesDir()方法,APP刪除,相應的檔案不被刪除;
4.訪問內部儲存檔案,不需要申請許可權;

2.儲存檔案到內部儲存

  在沒有root的前提下,內部儲存目錄是隱藏不可見的;訪問內部儲存目錄時,不需要申請系統許可權;由於從Android6.0開始支援多使用者,內部儲存目錄路徑從之前的/data/data變成了/data/user/0 。
1.getFilesDir();
/data/user/0/packname/files
2.getCacheDir();
/data/user/0/packname/cache

3.儲存檔案到外部儲存

3.1 申請許可權

  同時申請讀寫外部儲存許可權:

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

  從Android4.4開始,getExternalFilesDir()和getExternalCacheDir()方法不需要申請許可權;所以如果你的App支援4.3或者更低版本,並且你要訪問私有檔案,你需要這麼申請許可權:

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

3.2 判斷外部儲存是否可用

  因為外部儲存可能不可用——例如當用戶將儲存掛載到PC上或刪除SD卡時——在訪問卷之前,您必須驗證外部儲存是否可用。您可以通過呼叫getExternalStorageState()方法來查詢外部儲存狀態。

/* 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; }

3.3 Public files

  在申請許可權並且確定外部儲存可用後,外部儲存檔案有兩種型別:
  Public files:公共檔案其他App可以訪問,路徑例如/storage/emulated/0/Documents;解除安裝當前App後,這些檔案仍然保留。例如:DCIM,MUSIC等。

3.4 Private files

  Private files:因為這些檔案本身屬於外部儲存檔案,所以通過一些方法能被其他App訪問;但是這些檔案屬於對應的APP,路徑例如/storage/emulated/0/Android/data/packagename/cache當App刪除後,這些檔案也被刪除。

4.測試Demo

package com.example.davidhuang.storagepath;

import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.support.annotation.RequiresApi;
import android.support.v4.os.EnvironmentCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "Storage Path";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //內部儲存
        Log.i(TAG ,"getCacheDir()---->" + getCacheDir().getAbsolutePath());
        Log.i(TAG ,"getFilesDir()---->" + getFilesDir().getAbsolutePath());
        Log.i(TAG, "getDir()---->" + getDir("myfile", Context.MODE_PRIVATE));

        Log.i(TAG, "Environment.getDataDirectory()---->" + Environment.getDataDirectory().getAbsolutePath());
        Log.i(TAG, "Environment.getRootDirectory()---->" + Environment.getRootDirectory().getAbsolutePath());
        Log.i(TAG, "Environment.getDownloadCacheDirectory()---->" + Environment.getDownloadCacheDirectory().getAbsolutePath());
        Log.i(TAG, "getPackageResourcePath()---->" + getPackageResourcePath());
        //外部儲存
        if(!isExternalStorageWritable()){
            Log.w(TAG, "External Storage is not Writable!");
            return;
        }
        /**
         * 外部儲存公共檔案目錄,手動建立
         * 一個引數,表明目錄所放的檔案型別,傳入的引數是Environment類中的DIRECTORY_XXX靜態變數,比如DIRECTORY_DCIM,DIRECTORY_MUSIC等.
         * 注意:傳入的型別引數不能是null,返回的目錄路徑有可能不存在,所以必須在使用之前確認一下。
         */
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4以前不支援下列獲取路徑的方法
            File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
            if( !path.exists() ){
                path.mkdirs();
            }
            Log.i(TAG, "Environment.getExternalStoragePublicDirectory()---->" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS));
            //外部儲存私有檔案目錄
            Log.i(TAG, "getExternalCacheDir()---->" + getExternalCacheDir().getAbsolutePath());
            Log.i(TAG, "getExternalFilesDir()---->" + getExternalFilesDir(Environment.DIRECTORY_DCIM).getAbsolutePath());
        }
        Log.i(TAG, "Environment.getExternalStorageDirectory()---->" + Environment.getExternalStorageDirectory().getAbsolutePath());
    }
    
    /* 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;
    }
}

輸出:
Android 4.3 模擬器

getCacheDir()---->/data/data/com.example.davidhuang.storagepath/cache
getFilesDir()---->/data/data/com.example.davidhuang.storagepath/files
getDir()---->/data/data/com.example.davidhuang.storagepath/app_myfile
Environment.getDataDirectory()---->/data
Environment.getRootDirectory()---->/system
Environment.getDownloadCacheDirectory()---->/cache
getPackageResourcePath()---->/data/app/com.example.davidhuang.storagepath-2.apk

Environment.getExternalStorageDirectory()---->/storage/sdcard

Android 4.4 ,5.0模擬器

getCacheDir()---->/data/data/com.example.davidhuang.storagepath/cache
getFilesDir()---->/data/data/com.example.davidhuang.storagepath/files
getDir()---->/data/data/com.example.davidhuang.storagepath/app_myfile
Environment.getDataDirectory()---->/data
Environment.getRootDirectory()---->/system
Environment.getDownloadCacheDirectory()---->/cache
getPackageResourcePath()--->/data/app/com.example.davidhuang.storagepath-1.apk
    
Environment.getExternalStoragePublicDirectory()---->
/storage/sdcard/Documents
getExternalCacheDir()---->
/storage/sdcard/Android/data/com.example.davidhuang.storagepath/cache
getExternalFilesDir()---->
/storage/sdcard/Android/data/com.example.davidhuang.storagepath/files/DCIM
Environment.getExternalStorageDirectory()---->/storage/sdcard

Android 6.0,7.0,8.0,9.0模擬器
Android 8.0 魅族16X真機

getCacheDir()---->/data/user/0/com.example.davidhuang.storagepath/cache
getFilesDir()---->/data/user/0/com.example.davidhuang.storagepath/files
getDir()---->/data/user/0/com.example.davidhuang.storagepath/app_myfile
Environment.getDataDirectory()---->/data
Environment.getRootDirectory()---->/system
Environment.getDownloadCacheDirectory()---->/data/cache
getPackageResourcePath()---->/data/app/com.example.davidhuang.storagepath-i1NCmia3ALItNcV3Rkyk8A==/base.apk

Environment.getExternalStoragePublicDirectory()---->/storage/emulated/0/Documents
Environment.getExternalStorageDirectory()---->/storage/emulated/0
getExternalCacheDir()---->
/storage/emulated/0/Android/data/com.example.davidhuang.storagepath/cache
getExternalFilesDir()---->
/storage/emulated/0/Android/data/com.example.davidhuang.storagepath/files/DCIM

4.檔案儲存路徑總結

(1)Android4.4以前

getCacheDir()---->/data/data/packagename/cache
getFilesDir()---->/data/data/packagename/files
getDir()---->/data/data/packagename/app_myfile
Environment.getDataDirectory()---->/data
Environment.getRootDirectory()---->/system
Environment.getDownloadCacheDirectory()---->/cache
getPackageResourcePath()---->/data/app/packagename-2.apk

Environment.getExternalStorageDirectory()---->/storage/sdcard

(2)Android4.4級以後,Android6.0以前

getCacheDir()---->/data/data/packagename/cache
getFilesDir()---->/data/data/packagename/files
getDir()---->/data/data/packagename/app_myfile
Environment.getDataDirectory()---->/data
Environment.getRootDirectory()---->/system
Environment.getDownloadCacheDirectory()---->/cache
getPackageResourcePath()--->/data/app/packagename-1.apk

Environment.getExternalStoragePublicDirectory()---->/storage/sdcard/Documents
getExternalCacheDir()---->/storage/sdcard/Android/data/packagename/cache
getExternalFilesDir()---->/storage/sdcard/Android/data/packagename/files/DCIM
Environment.getExternalStorageDirectory()---->/storage/sdcard

(3)Android6.0以後

getCacheDir()---->/data/user/0/packagename/cache
getFilesDir()---->/data/user/0/packagename/files
getDir()---->/data/user/0/packagename/app_myfile
Environment.getDataDirectory()---->/data
Environment.getRootDirectory()---->/system
Environment.getDownloadCacheDirectory()---->/data/cache
getPackageResourcePath()---->/data/app/packagename-num.apk(8.0以前)
getPackageResourcePath()---->/data/app/packagename-i1NCmia3ALItNcV3Rkyk8A==/base.apk(8.0及以後)

Environment.getExternalStoragePublicDirectory()---->/storage/emulated/0/Documents
Environment.getExternalStorageDirectory()---->/storage/emulated/0
getExternalCacheDir()---->/storage/emulated/0/Android/data/packagename/cache
getExternalFilesDir()---->/storage/emulated/0/Android/data/packagename/files/DCIM