在Android 10(API 29)版本的手机中,系统提供了分区存储的功能。对于启用了分区存储的应用,可以通过MediaStore进行文件的操作。
对于部分应用未作MediaStore兼容时,存储文件会报错。这时候需要设置暂不启用分区存储能力,此时建议您在应用的清单文件中将 requestLegacyExternalStorage 设置为 true 以停用分区存储。
参考代码如下:
<application
android:allowBackup="true"
android:backupAgent=".database.DataBackupAgent"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:name=".application.TheApplication"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:theme="@style/AppTheme.NoActionBar">
...
</application>
但是上面方式只是临时方案,如果应用在搭载 Android 11 的设备上运行,以上配置会不生效。
此时就需要兼容MediaStore分区存储的方式了。
今天就以图片为例,实现图片的存储。官方文档:访问共享存储空间中的媒体文件。
首先我们找到清单文件,对权限进行配置,设定API 29及以上版本不再获取存储权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/>
然乎我们在全县申请时,判断当前系统,若是28或更低版本时才动态获取存储权限:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
addPermission(permissionsList, Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
权限申请取消后,我们可以使用MediaStore进行文件存储操作:
/**
* 保存图片,SDK > 28
*/
private void insertImage(Bitmap bitmap) {
// 拿到 MediaStore.Images 表的uri
Uri tableUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
// 创建图片索引
ContentValues value = new ContentValues();
value.put(MediaStore.Images.Media.DISPLAY_NAME,System.currentTimeMillis() + ".jpg");
value.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
value.put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/devdroid");
value.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());
// 将该索引信息插入数据表,获得图片的Uri
Uri imageUri = getContentResolver().insert(tableUri,value);
try {
// 通过图片uri获得输出流
OutputStream os = getContentResolver().openOutputStream(imageUri);
// 图片压缩保存
bitmap.compress(Bitmap.CompressFormat.JPEG,100,os);
} catch (Exception e) {
e.printStackTrace();
}
}
此时安装应用,发现在API29及以上系统上,打开应用不在获取存储权限,同时存储图片功能也正常了。
以上讲述了对图片类型的操作,事实上MediaStore除了Images类型,还支持:
- MediaStore.Files: 共享的文件,包括多媒体和非多媒体信息
- MediaStore.Audio: 音频信息
- MediaStore.Vedio: 视频信息
- MediaStore.Download: 下载信息
他们支持的路径分别以下路径及其子路径: - MediaStore.Images : 图片,存储在 DCIM/ 和 Pictures/ 目录中
- MediaStore.Video :视频,存储在 DCIM/、Movies/ 和 Pictures/ 目录中
- MediaStore.Audio :音频,存储在 Alarms/、Audiobooks/、Music/、Notifications/、Podcasts/ 和 Ringtones/ 目录中
- MediaStore.Download:下载,存储在 download/ 目录中
以上这些路径都是系统通过MIME类型进行访问和操作,包含视频、图像、文本、音频、应用程序等数据, 关于MIME类型后面有时间再研究。
以上所有代码可参考睡眠助理。