Android中canRead()函数始终返回false求助(已申请读取权限)
问题排查方案
1. 检查Android版本与分区存储限制
从Android 10(API 29)开始,系统默认启用分区存储(Scoped Storage),即使持有READ_EXTERNAL_STORAGE权限,也无法直接通过绝对路径访问外部存储的文件。
- 临时兼容方案(仅适用于Android 10):在
AndroidManifest.xml的<application>标签中添加android:requestLegacyExternalStorage="true" - 长期解决方案:使用
MediaStore查询Download目录下的文件,或者通过**存储访问框架(SAF)**让用户选择文件。示例代码:
// 用MediaStore查询指定文件的示例 val projection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.DISPLAY_NAME) val selection = "${MediaStore.Video.Media.DISPLAY_NAME} = ?" val selectionArgs = arrayOf("Ball - 113146.mp4") val query = contentResolver.query( MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null ) query?.use { cursor -> if (cursor.moveToFirst()) { val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID) val contentUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, cursor.getLong(idColumn)) // 通过contentUri打开输入流读取文件 val inputStream = contentResolver.openInputStream(contentUri) // 后续操作... } else { throw FileNotFoundException("文件不存在") } }
2. 确认文件实际存在
先调用inputFile.exists()验证文件是否真的在指定路径下:
if (!inputFile.exists()) { throw FileNotFoundException("文件不存在: ${inputFile.absolutePath}") }
如果返回false,检查路径拼写是否正确,或者文件是否被删除/移动。
3. 验证权限是否真正被授予
Android 6.0(API 23)及以上,除了在AndroidManifest.xml声明权限,还需要动态申请权限,并确保用户已授权:
// 检查权限是否已授予 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 未授权,发起权限请求 ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), REQUEST_CODE) } else { // 权限已授予,执行文件读取逻辑 }
注意:动态申请后要在onRequestPermissionsResult(或使用Activity Result API)中确认用户是否允许了权限。
4. 外置SD卡的特殊情况
如果文件位于外置SD卡,READ_EXTERNAL_STORAGE权限无法访问,Android 11及以上需要申请MANAGE_EXTERNAL_STORAGE权限(需在应用商店说明用途),或者通过SAF让用户选择SD卡上的文件。
内容的提问来源于stack exchange,提问作者Ashutosh
相关产品推荐
相关产品推荐

