Android 11及以上读取自定义文件夹非媒体文件的权限检查方法
Android 11+ 自定义非媒体文件夹的权限检查方案
Android 11及以上引入的范围存储机制主要针对媒体文件做了权限细分,但读取/storage/emulated/0/custom_folder这类公共目录下的自定义非媒体文件时,需要根据系统版本适配不同的权限逻辑,以下是具体实现方案:
权限适配逻辑
不同Android版本的权限要求差异较大,核心逻辑如下:
- Android 13(API 33)及以上:若自定义文件夹是当前APP创建的,无需额外权限;若访问其他APP创建的文件夹,需申请
MANAGE_EXTERNAL_STORAGE权限或使用存储访问框架(SAF) - Android 11-12(API 30-32):必须持有
MANAGE_EXTERNAL_STORAGE权限,或通过SAF让用户主动选择文件夹 - Android 6-10(API 23-29):申请
READ_EXTERNAL_STORAGE权限即可 - Android 5.1及以下:无运行时权限要求,默认允许访问
权限检查代码实现
fun hasCustomFolderAccessPermission(context: Context): Boolean { return when { // Android 13+:优先判断是否为APP自有文件夹,否则检查全存储权限 Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> { isAppOwnedCustomFolder() || Environment.isExternalStorageManager() } // Android 11-12:检查全存储管理权限 Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> { Environment.isExternalStorageManager() } // Android 6-10:检查外部存储读取权限 Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> { ContextCompat.checkSelfPermission( context, Manifest.permission.READ_EXTERNAL_STORAGE ) == PackageManager.PERMISSION_GRANTED } // 低版本无需权限 else -> true } } // 辅助判断:自定义文件夹是否为当前APP创建(示例逻辑,可根据实际业务调整) private fun isAppOwnedCustomFolder(): Boolean { val customFolder = File("/storage/emulated/0/custom_folder") // 可通过检查文件夹内的标记文件、创建者信息等方式强化判断 return customFolder.exists() && customFolder.canRead() && customFolder.canWrite() }
带权限检查的文件读取示例
结合权限检查优化文件读取逻辑,避免无权限时报错:
fun getFileString(context: Context): String? { if (!hasCustomFolderAccessPermission(context)) { // 此处可触发权限请求流程,比如引导用户开启权限或选择文件夹 return null } return try { File("/storage/emulated/0/custom_folder/file.txt").bufferedReader().use { it.readText() } } catch (e: IOException) { e.printStackTrace() null } }
关键注意事项
MANAGE_EXTERNAL_STORAGE权限:需引导用户到系统设置手动开启,Google Play对该权限的审核严格,仅允许文件管理器等刚需应用使用- 存储访问框架(SAF):若不想使用全存储权限,推荐通过
ACTION_OPEN_DOCUMENT_TREEIntent让用户选择目标文件夹,通过ContentResolver操作文件,更符合范围存储的设计规范
内容的提问来源于stack exchange,提问作者Bitwise DEVS
相关产品推荐
相关产品推荐

