API 29+ Android作用域存储:如何判断足够可用媒体存储空间?
Android API 29+ 作用域存储下判断公共存储磁盘空间的方案
在API 29及以上的作用域存储规则下,无法通过File API直接操作公共存储目录,要判断音乐目录所在的外部存储是否有足够空间存放媒体文件,可通过StorageManager API实现,具体步骤如下:
1. 定位目标存储卷
公共音乐目录对应的MediaStore URI为MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,先通过这个URI获取其所属的存储卷对象:val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager val audioPublicUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI val targetVolume = storageManager.getStorageVolume(context.contentResolver, audioPublicUri)2. 获取可用空间(准确值)
拿到存储卷后,使用getAllocatableBytes()方法获取应用实际可使用的空间(该方法会扣除系统预留的空间,比getFreeBytes()更可靠):targetVolume?.uuid?.let { volumeUuid -> val requiredSpace = 100 * 1024 * 1024L // 服务器告知的100MB文件大小 val availableSpace = storageManager.getAllocatableBytes(volumeUuid) // 建议预留少量额外空间,应对元数据或写入开销 val safeRequiredSpace = requiredSpace * 1.1.toLong() if (availableSpace >= safeRequiredSpace) { // 空间充足,可执行下载和写入MediaStore操作 } else { // 空间不足,提示用户清理存储 } } ?: run { // 外部存储不可用(如SD卡移除),提示用户 }3. 权限说明
- API 29-32:需声明
WRITE_EXTERNAL_STORAGE权限(无需动态申请,因为是写入公共媒体目录) - API 33+:无需额外写入权限,只需声明对应媒体类型的读取权限(如
READ_MEDIA_AUDIO),即可通过MediaStore写入公共音乐目录 getAllocatableBytes()方法在API 26及以上可用,无需特殊权限(只要应用有权限写入目标存储卷即可)
- API 29-32:需声明
关键注意点
- 禁止使用
Environment.getExternalStorageDirectory()等废弃API,这类方法在作用域存储下无法访问公共目录 - 务必用
getAllocatableBytes()而非getFreeBytes(),后者返回的总空闲空间包含系统预留的不可用部分,会导致误判 - 写入时直接通过MediaStore打开
OutputStream写入,无需先下载到内部存储再复制,节省额外空间占用
内容的提问来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

