Android Q中无法直接对内部存储的公共空间操作File对象来实现读文件、写文件、删除文件、重命名文件等操作。只能通过Uri的形式读写。如果直接拿File对象操作,在使用File对象创建OutputStream或者InputStream的时候,就会报错。
操作公共空间时,会用到MediaStore。它是外部存储空间的公共媒体集合,存放的都是多媒体文件,在API >= 29后加入了Download集合:
- 照片:存储在 MediaStore.Images 中。
- 视频:存储在 MediaStore.Video 中。
- 音乐文件:存储在 MediaStore.Audio 中。
- 下载文件:存储在 MediaStore.Downloads 中。
- 所有文件:存储在 MediaStore.Files 中。
为了以后的适配方便,在创建使用到文件的工具类的时候,最好不要再使用File对象传递了,而是替换成Uri对象。
创建Uri:
Uri fileUri = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { //设置保存参数到ContentValues中 ContentValues contentValues = new ContentValues(); //设置文件名 contentValues.put(MediaStore.Downloads.DISPLAY_NAME, fileName); contentValues.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS); //设置文件类型 contentValues.put(MediaStore.Downloads.MIME_TYPE, mime); //执行insert操作,向系统文件夹中添加文件 //EXTERNAL_CONTENT_URI代表外部存储器,该值不变 fileUri = getContentResolver().insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues); } else { File dir = new File(Environment.getExternalStorageDirectory().getPath() + File.separator + Environment.DIRECTORY_DOWNLOADS); if(!dir.exists()){ dir.mkdirs(); } File file = new File(dir, fileName); if (file.exists()) { file.delete(); } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { fileUri = Uri.fromFile(file); } else { fileUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".file_provider", file); } }
由Uri得到OutputStream或者InputStream:
OutputStream os = getContentResolver().openOutputStream(fileUri); InputStream is = getContentResolver().openInputStream(fileUri);
创建Uri时,可以的话尽量设置正确的MIME_TYPE。因为如果文件已存在,系统会自动重命名,MIME_TYPE正确的话,重命名的时候才会自动的正确递增,比如1.jpeg, 1(1).jpeg。如果MIME_TYPE错误,则会错误的递增,比如1.jpg, 1.jpg(1)。注意jpg文件的mime为image/jpeg,而不能是image/jpg。
对同一个目录通过getContentResolver().insert创建Uri对象后,如果对该目录使用该方法创建一个新的Uri,会报错:UNIQUE constraint failed。经尝试对另一个目录创建没有问题。比如分别对Download和Picture目录创建,没有问题。还不知道为什么。
参考文献:
https://developer.android.com/training/data-storage#scoped-storage
https://www.jianshu.com/p/15520bc3f5c6
https://blog.csdn.net/yehui928186846/article/details/101706238