Android 13下PhotoPicker无法访问全部文件夹的问题求助
Android 13 无法访问全部图片文件夹的解决方案
问题原因
Android 13(API 33)开始,系统默认的MediaStore.ACTION_PICK_IMAGES选择器仅展示媒体库已索引的文件夹(比如收藏、相机、截图、下载),未被媒体库扫描到的文件夹不会显示。同时READ_MEDIA_IMAGES权限仅授予访问媒体库中的媒体文件权限,并非全存储访问权限——这是Android 13针对隐私权限的收紧,和旧版本的权限逻辑不同。
另外你代码里在API33+时还申请了READ_EXTERNAL_STORAGE,这个权限在Android 13已经被废弃,无需申请,不会起到任何作用。
解决方案
根据需求,有两种可行方案:
方案1:使用系统文档树选择器(访问任意文件夹)
通过ACTION_OPEN_DOCUMENT_TREE让用户主动选择要访问的文件夹,获取该文件夹的访问权限后,即可遍历其中所有文件。代码示例:
private fun openDocumentTree() { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) startActivityForResult(intent, REQUEST_CODE_DOCUMENT_TREE) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE_DOCUMENT_TREE && resultCode == RESULT_OK) { data?.data?.let { treeUri -> // 持久化权限,重启APP后仍有效 contentResolver.takePersistableUriPermission( treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION ) // 遍历文件夹内的文件,需要使用DocumentFile操作 val rootDocument = DocumentFile.fromTreeUri(this, treeUri) rootDocument?.listFiles()?.forEach { file -> // 处理文件,比如判断是否为图片 if (file.type?.startsWith("image/") == true) { // 执行你的逻辑 } } } } }
注意:这种方式需要用户手动选择文件夹,符合Android隐私规范。
方案2:自定义媒体选择器(遍历所有媒体文件)
如果你的需求是访问所有图片文件(不管所在文件夹),可以直接查询MediaStore获取所有图片的Uri,然后自己构建选择界面,绕过系统默认选择器的限制。代码示例:
private fun queryAllImages() { val projection = arrayOf( MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.BUCKET_DISPLAY_NAME // 获取文件夹名称 ) val cursor = contentResolver.query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, "${MediaStore.Images.Media.DATE_ADDED} DESC" ) cursor?.use { val idColumn = it.getColumnIndexOrThrow(MediaStore.Images.Media._ID) val folderColumn = it.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME) val folderMap = mutableMapOf<String, MutableList<Uri>>() while (it.moveToNext()) { val id = it.getLong(idColumn) val folderName = it.getString(folderColumn) val imageUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id) if (!folderMap.containsKey(folderName)) { folderMap[folderName] = mutableListOf() } folderMap[folderName]?.add(imageUri) } // folderMap中存储了所有文件夹及其对应的图片Uri,可用于构建自定义选择界面 } }
这种方式可以获取到媒体库中所有已索引的图片,按文件夹分类展示,不受系统选择器的限制。
权限调整
修改你的checkPermission方法,API33+时移除无用的READ_EXTERNAL_STORAGE:
private fun checkPermission() { val PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { arrayOf(Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.POST_NOTIFICATIONS) } else { arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA) } TedPermission(this) .setPermissionListener(permissionlistener) .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]") .setPermissions(*PERMISSIONS) .check() }
内容的提问来源于stack exchange,提问作者tej shah
相关产品推荐
相关产品推荐

