API级别低于30时是否应采用Scoped Storage而非旧方法?
Android 媒体读写方案选择:API<30时用Scoped Storage还是旧方法?
问题背景
我已经在API级别低于30的环境(应用最低API为23)中测试了Scoped Storage,它在所有Android版本中都能正常工作,包括照片/视频的读写操作。
我的疑问:在API级别低于30的情况下,我应该使用Scoped Storage还是旧方法来处理媒体读写?
测试用代码
保存图片代码
private boolean saveImageToExternalStorage(String imgName, Bitmap bmp){ Uri ImageCollection = null; ContentResolver resolver = getContentResolver(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ ImageCollection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY); }else { ImageCollection = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, imgName + ".jpg"); contentValues.put(MediaStore.Images.Media.MIME_TYPE,"image/jpeg"); Uri imageUri = resolver.insert(ImageCollection, contentValues); try { OutputStream outputStream = resolver.openOutputStream(Objects.requireNonNull(imageUri)); bmp.compress(Bitmap.CompressFormat.JPEG,100,outputStream); Objects.requireNonNull(outputStream); return true; } catch (Exception e){ Toast.makeText(this,"Image not saved: \n" + e,Toast.LENGTH_SHORT).show(); e.printStackTrace(); } return false; }
读取图片代码
private ActivityResultLauncher<String> mTakePhoto; mTakePhoto = registerForActivityResult(new ActivityResultContracts.GetContent(), result -> binding.imageView.setImageURI(result) ); mTakePhoto.launch("image/*");
推荐方案:优先使用Scoped Storage
从你的测试结果和代码实现来看,推荐你统一采用Scoped Storage相关写法,原因如下:
- 兼容性已验证:你已经确认API23到API29之间该方案能正常运行,且代码已做版本适配,不会出现兼容问题。
- 降低未来适配成本:Android 11(API30)起强制要求Scoped Storage,现在统一用这套逻辑,后续无需为适配高版本大规模修改代码。
- 权限更简洁:API29及以上无需申请
READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE权限;API23-28虽仍需申请,但后续升级后可直接移除权限申请流程,减少对用户的打扰。 - 代码维护更简单:统一一套读写逻辑,避免维护两套不同的代码,降低后续出错概率。
另外你的代码实现已经符合规范:
- 保存图片通过
MediaStore插入Uri再写入,完全符合Scoped Storage的设计要求; - 读取图片使用官方推荐的
ActivityResultContracts.GetContent(),无需自行处理文件路径,规避了路径权限问题。
内容的提问来源于stack exchange,提问作者coderror
相关产品推荐
相关产品推荐

