小米开发平台应用读写文件API标准建议
1.背景与介绍
目前Android 11上Google推出的fuse文件系统和sdcardfs相结合的文件系统。目前常用目录除了storage/emulated/0/Android/data使用的是sdcardfs其他都使用的是fuse文件系统。由于fuse文件系统的特性,会从file的访问到媒体库相关逻辑,所以引发相关性能问题。
2.读写文件API建议
目录建议:
- 对于私有文件建议存储在storage/emulated/0/Android/data目录下。该目录下不存在权限等判断。
- 对于共享文件建议存储在storage/emulated/0/Android/media下面。
3.文件的访问
3.1.可以使用直接文件路径和原生库访问文件
为了帮助您的应用更顺畅地使用第三方媒体库,Android 11 允许您使用除 MediaStore API 之外的 API 访问共享存储空间中的媒体文件。不过,您也可以转而选择使用以下任一 API 直接访问媒体文件:
- File API
- 原生库,例如 fopen()
如果您的应用没有任何存储权限,您可以使用直接文件路径访问归因于您的应用的媒体文件。如果您的应用具有 READ_EXTERNAL_STORAGE 权限,则可以使用直接文件路径访问所有媒体文件,无论这些文件是否归因于您的应用。如果您直接访问媒体文件,建议您在应用的清单文件中将 requestLegacyExternalStorage 设置为 true 以停用分区存储。这样,您的应用就可以在搭载 Android 10 的设备上正常工作。
3.2.对于性能的影响
当您使用直接文件路径依序读取媒体文件时,其性能与 MediaStore API 相当。但是,当您使用直接文件路径随机读取和写入媒体文件时,进程的速度可能最多会慢一倍。在此类情况下,我们建议您改为使用 MediaStore API。根据目前情况来看,会慢很多,建议使用MediaStore API。
3.3.媒体库中的可用值
当您访问现有媒体文件时,您可以使用您的逻辑中 DATA 列的值。这是因为,此值包含有效的文件路径。但是,不要假设文件始终可用。请准备好处理可能发生的任何基于文件的 I/O 错误。另一方面,如需创建或更新媒体文件,请勿使用 DATA 列的值。请改用 DISPLAY_NAME 和 RELATIVE_PATH 列的值。详见:https://developer.android.google.cn/preview/privacy/storage#change-details。
4.MediaStore的使用
由于R版本上使用File写文件目前存在性能问题,因此google推荐使用MediaStore进行写文件。而MediaStore写文件又会存在fuse同步的问题,一旦出现此类同步问题,产生文件无法打开,文件长度不对等异常现象。具体主要一下几点:
- MediaStore写文件,在文件未真正close的情况,不要调用fd的close操作。
以下为录音的部分代码,使用MediaStore方式进行音频录制,该fd传递给MediaRecord后,在录制真正完成前该fd不能被close()。正确的示例代码:
ParcelFapp一键生成器ileDescriptor 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();
}
}
}
}
- MediaStore写文件app 生成和File不能混合使用,MediaStore写文件时,不能使用File获取文件大小、重命名等操作。同时,在fd close后,由于回调有延迟,如果紧接着调用file的rename操作,会导致本次rename执行的文件异常。因此需要fd close后,需要延迟1-2s进行file的相关操作。
详见googleAPI文档:https://developer.android.google.cn/training/data-storage/shared/media。
编辑:yimen,如若转载,请注明出处:https://www.yimenapp.com/kb-yimen/12746/
部分内容来自网络投稿,如有侵权联系立删