Android SDK34中requestPermissions不弹权限弹窗,SDK29正常
问题分析与解决方案
核心原因
Android 14(API 34)对存储权限做了进一步限制:READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE已被系统废弃,当应用targetSdkVersion≥33时,请求这两个权限会被系统直接拒绝,不会弹出授权弹窗。而Android 10(API 29)虽然引入了分区存储,但仍兼容旧权限逻辑,所以你的新版本在API 29设备上能正常工作。
另外从API 30开始,保存图片到公共图库等场景已经不需要WRITE_EXTERNAL_STORAGE权限,使用MediaStore API即可完成操作。
解决方案
1. 适配权限声明(AndroidManifest.xml)
根据不同API等级声明对应权限,避免无效权限请求:
<!-- API 32及以下设备需要的旧存储权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- API 33及以上设备需要的媒体读取权限(仅针对图片场景) --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
2. 动态请求权限逻辑适配
根据设备API版本,动态选择要请求的权限:
private void requestStoragePermissions() { List<String> permissions = new ArrayList<>(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // Android 13+,请求图片读取权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) { permissions.add(Manifest.permission.READ_MEDIA_IMAGES); } } else { // Android 12及以下,请求旧存储权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE); } if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); } } if (!permissions.isEmpty()) { requestPermissions(permissions.toArray(new String[0]), READ_STORAGE_RESPONSE); } else { // 权限已就绪,执行图片编辑保存逻辑 handleImageOperations(); } }
3. 替换图片保存逻辑(无需WRITE权限)
使用MediaStore API保存图片到公共图库,无需申请WRITE_EXTERNAL_STORAGE:
private Uri saveEditedImage(Bitmap editedBitmap) { ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "edit_img_" + System.currentTimeMillis() + ".png"); contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/png"); // 指定保存到图库的子目录,方便用户查找 contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/YourAppFolder"); Uri imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); if (imageUri == null) return null; try (OutputStream outputStream = getContentResolver().openOutputStream(imageUri)) { editedBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); return imageUri; } catch (IOException e) { e.printStackTrace(); // 保存失败,删除空文件 getContentResolver().delete(imageUri, null, null); return null; } }
额外说明
- 如果你的应用仅需保存自己生成的图片,无需读取用户其他图库内容,那么API 33+甚至不需要申请
READ_MEDIA_IMAGES权限。 - 若需读取用户图库中的图片用于编辑,才需要在API 33+请求
READ_MEDIA_IMAGES。
内容的提问来源于stack exchange,提问作者kralvarado
相关产品推荐
相关产品推荐

