文件目录分类
属于应用的文件夹:
Context.getFilesDir(): /data/user/0/com.njfae.filesavedemo/files
Context.cacheDir(): /data/user/0/com.njfae.filesavedemo/cache
Context.externalCacheDir(): /storage/emulated/0/Android/data/com.njfae.filesavedemo/cache
Context.getExternalFilesDir(type): /storage/emulated/0/Android/data/com.njfae.filesavedemo/files/type
不属于应用的文件夹:
Environment.getExternalStorageDirectory(): /storage/emulated/0
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM): /storage/emulated/0/DCIM
注意:
- 带有 cache 的表示缓存文件
- 属于应用的文件夹里面的文件容易被一些第三方文件清理软件清理
- 系统设置中点击 清理缓存 会清理所有缓存文件中的文件,清理数据 会清理所有属于应用的文件
- external 相关的目录不一定有,在手机和电脑做文件交互的时候会被移除。
权限问题
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
属于应用的文件夹的操作不需要权限, 不属于应用的文件夹需要权限
SDCard 不存在问题
在获取应用目录的时候加一个判断。
public File getDiskCacheDir(Context context, String uniqueName) {
String cachePath;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath = context.getExternalCacheDir().getPath();
} else {
cachePath = context.getCacheDir().getPath();
}
return new File(cachePath + File.separator + uniqueName);
}
使用 DiskLruCache 实现缓存文件夹最大内存的限制
FileProvider
作用:Android 7.0 之后和其他应用做文件交互的时候使用。
用于生成 Uri。
public static String getFilePathFromURI(Context context, Uri contentUri) {
//copy file and send new file path
String fileName = getFileName(contentUri);
if (!TextUtils.isEmpty(fileName)) {
File copyFile = new File(TEMP_DIR_PATH + File.separator + fileName);
copy(context, contentUri, copyFile);
return copyFile.getAbsolutePath();
}
return null;
}
public static String getFileName(Uri uri) {
if (uri == null) return null;
String fileName = null;
String path = uri.getPath();
int cut = path.lastIndexOf('/');
if (cut != -1) {
fileName = path.substring(cut + 1);
}
return fileName;
}
public static void copy(Context context, Uri srcUri, File dstFile) {
try {
InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
if (inputStream == null) return;
OutputStream outputStream = new FileOutputStream(dstFile);
IOUtils.copy(inputStream, outputStream);
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}