目前Android 11上Google推出的fuse文件系统和sdcardfs相结合的文件系统。目前常用目录除了storage/emulated/0/Android/data使用的是sdcardfs其他都使用的是fuse文件系统。由于fuse文件系统的特性,会从file的访问到媒体库相关逻辑,所以引发相关性能问题。
目录建议:
对于共享文件建议存储在storage/emulated/0/Android/media下面。
为了帮助您的应用更顺畅地使用第三方媒体库,Android 11 允许您使用除 MediaStore API 之外的 API 访问共享存储空间中的媒体文件。不过,您也可以转而选择使用以下任一 API 直接访问媒体文件:
如果您的应用没有任何存储权限,您可以使用直接文件路径访问归因于您的应用的媒体文件。如果您的应用具有 READ_EXTERNAL_STORAGE 权限,则可以使用直接文件路径访问所有媒体文件,无论这些文件是否归因于您的应用。如果您直接访问媒体文件,建议您在应用的清单文件中将 requestLegacyExternalStorage 设置为 true 以停用分区存储。这样,您的应用就可以在搭载 Android 10 的设备上正常工作。
当您使用直接文件路径依序读取媒体文件时,其性能与 MediaStore API 相当。但是,当您使用直接文件路径随机读取和写入媒体文件时,进程的速度可能最多会慢一倍。在此类情况下,我们建议您改为使用 MediaStore API。根据目前情况来看,会慢很多,建议使用MediaStore API。
当您访问现有媒体文件时,您可以使用您的逻辑中 DATA 列的值。这是因为,此值包含有效的文件路径。但是,不要假设文件始终可用。请准备好处理可能发生的任何基于文件的 I/O 错误。另一方面,如需创建或更新媒体文件,请勿使用 DATA 列的值。请改用 DISPLAY_NAME 和 RELATIVE_PATH 列的值。详见:https://developer.android.google.cn/preview/privacy/storage#change-details。
由于R版本上使用File写文件目前存在性能问题,因此google推荐使用MediaStore进行写文件。而MediaStore写文件又会存在fuse同步的问题,一旦出现此类同步问题,产生文件无法打开,文件长度不对等异常现象。具体主要一下几点:
以下为录音的部分代码,使用MediaStore方式进行音频录制,该fd传递给MediaRecord后,在录制真正完成前该fd不能被close()。正确的示例代码:
ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "rw");
MediaRecorder mr = new MediaRecorder();
mr.setOutputFile(pfd.getFileDescriptor());
......
private void stopRecord() {
if (mr != null) {
mr.stop();
mr.release();
mr = null;
if (pfd != null) {
try{
pfd.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
详见googleAPI文档:https://developer.android.google.cn/training/data-storage/shared/media。
目录