文件与存储
关于Android平台上的文件与存储,可查阅应用数据和文件概览。Android系统上的存储空间主要划分为内部的和外部的,关于存储空间划分的详细内容,请阅读 数据和文件存储概览
存储路径

内部存储:
context.getCacheDir():示例路径/data/data/com.example.myapp/cachecontext.getFilesDir():示例路径/data/data/com.example.myapp/filescontext.getDir("test.txt", Context.MODE_PRIVATE):示例路径/data/data/com.example.myapp/test.txt
外部存储:
context.getExternalCacheDir():示例路径/storage/sdcard/0/Android/data/com.example.myapp/cachecontext.getExternalFilesDir():示例路径/storage/sdcard/0/Android/data/com.example.myapp/filesEnvironment.getExternalStorageDirectory():获取外部存储的根路径。示例路径/storage/sdcard/0
拓展:
context.getPackageResourcePath()或context.getPackageCodePath():返回 android 上安装包的完整路径,示例路径/data/app/com.example.myapp_xxx/base.apk
//判断外部存储是否可用
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
}else{
//没外部存储就使用内部存储
}
// 遍历手机的外部存储路径
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
File[] files = getExternalFilesDirs(Environment.MEDIA_MOUNTED);
for(File file:files){
Log.d("MainActivity",file.getAbsolutePath());
}
}
注意: Android 10(API 29)及更高版本默认情况下被赋予了对外部存储空间的分区访问权限(即分区存储),因此只能访问外部存储空间上的应用专属目录,以及本应用所创建的特定类型的媒体文件。这意味着,最新版本上,开发者不能任意的操作外部存储空间,否则会报权限异常。针对此问题,目前有两种解决方法:
修改目标版本
在
build.gradle中将targetSdkVersion配置为28或更低暂停分区存储
如果
targetSdkVersion必须为29,则可在清单文件中配置属性暂停分区存储。<application android:requestLegacyExternalStorage="true" ... >
Android 11(API 30)及其之后的版本,必须使用分区存储,开发者从此不能任意操作用户的外部存储空间。详见 暂时停用分区存储
更新媒体库
需要注意,当我们将一张图片保存到Android的储存空间中时,图库之类的应用不能马上查看到这张图片,这是由于MediaStore的数据库未及时扫描更新所致的,因此,当我们没保存一种图片时,都应当主动通知MediaStore去更新。
目前最新的做法是使用MediaScannerConnection
调用静态方法
scanFile,批量更新。最后一个参数可用来设置一个更新完成后的回调,此处直接传null未设置回调。// 指定扫描某个文件, 更新媒体库 MediaScannerConnection.scanFile(context, new String[]{filePath}, new String[]{mimeType}, null);单个更新。使用这种方式,可以返回一个Uri
MediaScannerConnection msc = new MediaScannerConnection(this, new MediaScannerConnectionClient(){ @Override public void onMediaScannerConnected() { msc.scanFile(filePath, null); } @Override public void onScanCompleted(String path, Uri uri) { msc.disconnect(); } }); msc.connect();
文件监听
如果我们需要监听某个文件夹下的文件变化,可以使用 FileObserver
class TestFileObserver extends FileObserver {
// 需要监听的文件或文件夹路径
public TestFileObserver(String path) {
super(path,FileObserver.ALL_EVENTS);
}
@Override
public void onEvent(int event, String path) {
// 如果文件修改了
if(event==FileObserver.MODIFY){
Log.d("TestFileObserver",path);
}
}
}
TestFileObserver testFileObserver = new TestFileObserver(context.getExternalFilesDir());
// 开始监听
testFileObserver.startWatching();
// 停止监听
// testFileObserver.stopWatching();
有几点需要注意
- 文件监听不会自动递归,如需对目录下的所有字级监听,需要手动递归去设置
- 在Android中的所有文件路径操作,千万不要硬编码路径,一定要使用系统提供的方法和常量去获取路径
公众号“编程之路从0到1”