Android 13下如何彻底移除WRITE_EXTERNAL_STORAGE权限?
Android 13 存储权限适配方案
Android 13将原存储权限拆分为三个细分权限,不再需要WRITE_EXTERNAL_STORAGE,适配方式如下:
1. 替换Manifest权限声明
根据应用需求添加对应细分权限:
- 读取图片:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
- 读取视频:
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
- 读取音频:
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
针对Android 13以下版本,保留旧权限并限制最高适用版本:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
2. 动态申请权限
代码中区分Android版本,申请对应权限:
private const val REQUEST_CODE_MEDIA = 1001 private const val REQUEST_CODE_STORAGE = 1002 fun checkAndRequestStoragePermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // Android 13及以上,申请媒体细分权限 val neededPermissions = mutableListOf<String>() if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) { neededPermissions.add(Manifest.permission.READ_MEDIA_IMAGES) } if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_VIDEO) != PackageManager.PERMISSION_GRANTED) { neededPermissions.add(Manifest.permission.READ_MEDIA_VIDEO) } if (neededPermissions.isNotEmpty()) { requestPermissions(neededPermissions.toTypedArray(), REQUEST_CODE_MEDIA) } } else { // Android 13以下,申请READ_EXTERNAL_STORAGE if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), REQUEST_CODE_STORAGE) } } }
3. 适配文件读写逻辑
Android 13推荐使用MediaStore或SAF(存储访问框架)操作公共目录文件,避免直接读写外部存储路径。例如保存图片到公共图片目录:
fun saveImageToPublicGallery(bitmap: Bitmap) { val contentValues = ContentValues().apply { put(MediaStore.Images.Media.DISPLAY_NAME, "app_image_${System.currentTimeMillis()}.jpg") put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES) } } contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)?.let { uri -> contentResolver.openOutputStream(uri).use { outputStream -> bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream) } } }
内容的提问来源于stack exchange,提问作者rendjaya
相关产品推荐
相关产品推荐

