Android-适配记录API28~33:读写权限变更记录

Android-适配记录API28~33:读写权限变更记录

背景

因为Android应用市场要求是最低要求API 30以上,我准备就直接从API 28升到API 33了,其中遇到了一些读写存储空间的问题,这里做一些记录总结~

相关权限:

  1. permission.READ_EXTERNAL_STORAGE
  2. permission.WRITE_EXTERNAL_STORAGE
  3. permission.MANAGE_EXTERNAL_STORAGE
  4. permission.READ_MEDIA_VIDEO
  5. permission.READ_MEDIA_IMAGES
  6. permission.READ_MEDIA_AUDIO

相关知识点

低版本的,我这里就不说明了

  1. Android 10(API 级别 29)开始,android.permission.WRITE_EXTERNAL_STORAGE 权限的行为发生了变化,这个权限默认情况下被视为无效,可以通过permission.MANAGE_EXTERNAL_STORAGE 获取全部文件的权限,但是只有系统应用程序或具有特殊要求的应用程序才能申请此权限,Environment.isExternalStorageManager() 判断自己是否获取了全部的权限。Environment.getExternalStorageDirectory() 在没有权限时,是无法访问的。
  2. android:requestLegacyExternalStorage="true" 是一个用于在 Android 10(API 级别 29)及以上版本中启用传统外部存储权限模式的应用程序清单属性,Android 11(API 级别 30)中将不再生效。
  3. Android 11(API 级别 30) 后,默认获取权限可以通过 context.getExternalFilesDir 获取外部存储的,/storage/emulated/0/Android/data/包名/file ,不需要特殊的权限,因为这个目录是应用程序的私有目录,删除app后会同时删除。
  4. Android 11(API 级别 30) 中,读取媒体文件的权限受到了更严格的限制。即使你声明了 READ_EXTERNAL_STORAGE 权限,你的应用程序也只能访问自己的媒体文件或存储在媒体库中的公共文件。如果你需要访问其他应用程序的媒体文件,你需要使用 Storage Access Framework 或 MediaStore API 来进行访问。
  5. 要读取媒体文件(如图片、音频、视频等)需要permission.READ_EXTERNAL_STORAGE, 在Android 33后被细分出了permission.READ_MEDIA_VIDEO,permission.READ_MEDIA_IMAGES,permission.READ_MEDIA_AUDIO

总结

  1. Android 10(API 级别 29)以后:android.permission.WRITE_EXTERNAL_STORAGE 默认无效,但是可以使用android:requestLegacyExternalStorage="true" 过度。
  2. Android 11(API 级别 30)以后:android:requestLegacyExternalStorage="true" 开始无效了,但是可以通过permission.MANAGE_EXTERNAL_STORAGE 获取全部文件的读写权限,或者使用 context.getExternalFilesDir() 方法获取外部存储空间的应用程序目录/storage/emulated/0/Android/data/包名/file时,不需要特殊的权限。需要注意:在 Android 12 中,MANAGE_EXTERNAL_STORAGE 权限被修改为更高的保护级别,只有特定的系统应用程序才能获得这个权限,这是一个高危的权限。
  3. Android 13(API 级别 33)以后:READ_EXTERNAL_STORAGE 权限被细分,需要获取对应媒体权限permission.READ_MEDIA_VIDEO,permission.READ_MEDIA_IMAGES,permission.READ_MEDIA_AUDIO

遇到的问题

1. 第三方相册选择器访问限制

fun checkHasPermission(activity: FragmentActivity,isRequest:Boolean): Boolean {
        val hasPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
			//**Android 13(API 级别 33),检测并申请对应权限**
            activity.hasPermission(
                Manifest.permission.READ_MEDIA_VIDEO,
                Manifest.permission.READ_MEDIA_IMAGES,
                Manifest.permission.READ_MEDIA_AUDIO,
                Manifest.permission.READ_EXTERNAL_STORAGE,
                isRequest = isRequest
            )
        } else {
            activity.hasPermission(
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                isRequest = isRequest
            )
        }
        return hasPermission
    } 

2. 文件外部存储

方法1: Environment.getExternalStorageDirectory() 使用 context.getExternalFilesDir() 代替;
- 优点:不需要权限申请。
- 缺点:app删除的时候会一起删除,所以重要的媒体文件需要你使用新的媒体方法进行保存。

方法2:获取android.permission.WRITE_EXTERNAL_STORAGE
- 优点:这种方法可以继承老的数据,同时app删除的时候数据不会被删除,
- 缺点:权限太敏感,需要用户跳转对应设置界面手动打开

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />
if (!Environment.isExternalStorageManager()) {  
   //调到对应设置进行处理
    try {
        val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
        intent.addCategory("android.intent.category.DEFAULT")
        intent.data = Uri.parse(String.format("package:%s", context.packageName))
        context.startActivity(intent)
    } catch (e: Exception) {
        val intent = Intent()
        intent.action = Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
        context.startActivity(intent)
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TieJun~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值