Android:无需权限访问MediaStore获取Cursor数据及图片选择器Uri问题
无需权限访问相册数据及图片选择器返回Uri的解决方案
一、无需权限获取相册媒体基本数据
直接查询MediaStore.Images.Media.EXTERNAL_CONTENT_URI通常需要READ_EXTERNAL_STORAGE权限,无权限时Cursor会为空。但从Android 10(API 29)开始,系统允许无需存储权限读取媒体的非隐私元数据(如ID、文件名、媒体类型等),只需在查询时指定必要的非隐私列,避免请求文件路径这类敏感字段:
// 仅请求非隐私的元数据列 String[] projection = { MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.MIME_TYPE }; Cursor cursor = context.getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null );
这种情况下,即使没有存储权限,Cursor也会返回有效数据,但无法获取MediaStore.Images.Media.DATA(文件路径)这类隐私字段。如果你的需求只是获取媒体基本信息,这个方法完全适用。
二、无需权限访问图片选择器返回的Uri
你使用Intent.ACTION_PICK打开的图片选择器,返回的Uri本身带有系统授予的临时访问权限,不需要额外申请存储权限就能直接访问。问题出在你后续重新构造picUri的逻辑——通过ID拼接的Uri会丢失原有临时权限,导致需要权限才能访问。
正确的做法是直接使用选择器返回的selectedImage Uri,无需重新构造:
ContentResolver contentResolver = activity.getContentResolver(); try { InputStream inStream = contentResolver.openInputStream(selectedImage); final byte[] file = PicUtils.readFileBytes(inStream); // 后续处理逻辑 } catch (IOException e) { e.printStackTrace(); }
如果需要获取该图片的元数据,同样可以直接查询返回的Uri,无需权限:
String[] projection = { MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.MIME_TYPE }; Cursor cursor = activity.getContentResolver().query( selectedImage, projection, null, null, null ); if (cursor != null && cursor.moveToFirst()) { String fileName = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)); String mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.MIME_TYPE)); cursor.close(); }
临时权限的有效期至你的Activity销毁为止,足够完成图片读取和处理操作。
内容的提问来源于stack exchange,提问作者hotpot
相关产品推荐
相关产品推荐

