app文件存储有两种:

  • 独立的,这种是不会随着app删除而删除;
  • 专属的,这种是随着app删除而删除;

独立文件

这种我们通常会存储在外置SD卡上,当然你也可以选择保存在其他的文件。

判断SD卡状态

1
2
3
//判断sd卡是否存在
boolean sdCardExist = Environment.getExternalStorageState()
    .equals(android.os.Environment.MEDIA_MOUNTED); 

获取目录

1
2
3
4
5
6
Environment.getExternalStorageDirectory()
// Environment.getExternalStorageDirectory()
public static File getExternalStorageDirectory() {
    throwIfUserRequired();
    return sCurrentUser.getExternalDirs()[0];
}

getExternalDirs

获取SD卡根目录

1
2
3
4
5
6
7
8
9
public File[] getExternalDirs() {
        final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId,
                StorageManager.FLAG_FOR_WRITE);
        final File[] files = new File[volumes.length];
        for (int i = 0; i < volumes.length; i++) {
            files[i] = volumes[i].getPathFile();
        }
        return files;
    }

通常路径是/sdcard/….

还有其他的别的目录可以获取文件系统的/data目录,/system目录。

1
2
Environment.getDataDirectory();
Environment.getRootDirectory();

专属文件

专属文件有两种:

  • 存储在internal storage
  • 存储在external storage

internal storage

通常用该方法获取目录context.getFilesDir() 该方法最终是获取getDataDir()的根目录中建立files 通常我们的sqlite,shared preference都存储在这

1
2
3
4
5
6
7
8
@Override
    public File getFilesDir() {
    ...
        synchronized (mSync) {
            if (mFilesDir == null) {
                mFilesDir = new File(getDataDir(), "files");
...
    }

### getDataDir()

可以看到关键是在mPackageInfo这个中获取的,mPackageInfoLoadedApk存放了apk相关信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 @Override
    public File getDataDir() {
        if (mPackageInfo != null) {
            File res = null;
            if (isCredentialProtectedStorage()) {
                res = mPackageInfo.getCredentialProtectedDataDirFile();
            } else if (isDeviceProtectedStorage()) {
                res = mPackageInfo.getDeviceProtectedDataDirFile();
            } else {
                res = mPackageInfo.getDataDirFile();
            }

            if (res != null) {
                if (!res.exists() && android.os.Process.myUid() == android.os.Process.SYSTEM_UID) {
                    Log.wtf(TAG, "Data directory doesn't exist for package " + getPackageName(),
                            new Throwable());
                }
                return res;
            } else {
                throw new RuntimeException(
                        "No data directory found for package " + getPackageName());
            }
        } else {
            throw new RuntimeException(
                    "No package details found for package " + getPackageName());
        }
    }

通常命名是/data/data/应用包名/files

external storage

通常方法有:

  • context.getExternalCacheDir()
  • context.getExternalFilesDir()

大同小异,来看context.getExternalCacheDir()

会调用Environment.buildExternalStorageAppCacheDirs

1
2
3
4
5
6
7
@Override
    public File[] getExternalCacheDirs() {
        synchronized (mSync) {
            File[] dirs = Environment.buildExternalStorageAppCacheDirs(getPackageName());
            return ensureExternalDirsExistOrFilter(dirs);
        }
    }

buildExternalStorageAppCacheDirs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public File[] buildExternalStorageAppCacheDirs(String packageName) {
            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE);
    }

public static final String DIR_ANDROID = "Android";
private static final String DIR_DATA = "data";
private static final String DIR_MEDIA = "media";
private static final String DIR_OBB = "obb";
private static final String DIR_FILES = "files";
private static final String DIR_CACHE = "cache";    

所以最后得到路径一般是 /sdcard/Androdi/data/packageName/cache