文件与存储

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

存储路径

20170618024841308

内部存储:

  • context.getCacheDir():示例路径 /data/data/com.example.myapp/cache
  • context.getFilesDir():示例路径 /data/data/com.example.myapp/files
  • context.getDir("test.txt", Context.MODE_PRIVATE):示例路径 /data/data/com.example.myapp/test.txt

外部存储:

  • context.getExternalCacheDir():示例路径/storage/sdcard/0/Android/data/com.example.myapp/cache
  • context.getExternalFilesDir():示例路径/storage/sdcard/0/Android/data/com.example.myapp/files
  • Environment.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”

20190301102949549

Copyright © Arcticfox 2021 all right reserved,powered by Gitbook文档修订于: 2022-05-01 12:20:20

results matching ""

    No results matching ""