Scoped Storage(Java):如何检测应用是否使用legacy旧版存储
Scoped Storage Legacy模式检测及自动切换方案
核心检测方法
你可以通过官方API加实际读写校验两层逻辑来判断legacy存储是否可用:
- 官方API判断
Android 10(API 29)及以上系统提供了Environment.isExternalStorageLegacy()方法,返回true代表当前应用正运行在legacy旧存储模式,返回false代表已启用分区存储。
注意事项:
preserveLegacyExternalStorage="true"仅对Android 10系统上从旧版本覆盖安装的应用生效,Android 11及以上系统该配置仅用于临时保留legacy权限,新安装的应用无论加什么配置都默认启用分区存储- Android 9及以下系统默认全程使用legacy存储,不需要额外判断
preserveLegacyExternalStorage属于过渡配置,Android 12及以上系统已完全废弃,所有应用最终都需要完成分区存储适配
- 兜底读写校验
为了避免部分厂商定制ROM对API的修改导致判断异常,建议加一层实际读写公共目录的校验逻辑,尝试对Download等公共目录写入临时文件,操作成功则代表legacy权限有效。
自动切换实现逻辑
你可以按照如下流程实现模式自动切换:
- 运行时先判断系统版本:
- API < 29:直接走原有legacy存储逻辑
- API >=29:先调用
Environment.isExternalStorageLegacy()获取初步结果
- 基于初步结果调用公共目录读写校验方法,确认legacy权限真实有效
- 如果确认legacy权限失效,自动切换到已经适配的Scoped Storage逻辑
代码示例
// 第一层API判断 fun isLegacyStorageEnabled(): Boolean { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { Environment.isExternalStorageLegacy() } else { true } } // 第二层兜底校验 fun isLegacyStorageActuallyAvailable(): Boolean { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return true return try { val testFile = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "legacy_test_${System.currentTimeMillis()}.tmp" ) // 尝试写入测试内容 testFile.outputStream().use { it.write("test".toByteArray()) } // 尝试读取验证 val content = testFile.inputStream().readBytes().toString(Charsets.UTF_8) // 删除测试临时文件 testFile.delete() content == "test" } catch (e: SecurityException) { false } catch (e: IOException) { false } }
内容的提问来源于stack exchange,提问作者Pink Jazz
相关产品推荐
相关产品推荐

