Android存储权限完美适配(Android11及以上适配)

一、Bug简述

一个很普通的需求,需要下载图片到本地,我的三个测试机(荣耀Android10,红米 11 和小米Android 13都没有问题)。

然后,主角登场了,测试的三星Android 13 死活拉不起存储权限弹窗。

想了下,三星的系统可能和小米的系统做了些区别。于是就是看了下存储权限的版本更迭,却是发现了些骚东西。

二、原因

很早以前,一直都是在manifest申明这两个权限就可以了,但是现在会有下面的警告!

这便是错误的原因:

可以得知,在Android 13(sdkversion为33)的系统中,已经被废弃了!!!

但是如果你给Write和Read权限加上maxSdkVersion=32,他在11,12上是没有问题的,但是最新的App要求 target sdkversion必须是33了。

所以,在此就必须做一个适配:

Android 11 里将引入一个特别的权限叫做 MANAGE_EXTERNAL_STORAGE,该权限将授权读写所有共享存储内容,这也将同时包含非媒体类型的文件。但是获得这个权限的应用还是无法访问其他应用的应用专属目录 (app-specific directory),无论是外部存储还是内部存储。

那么,为了兼容Android版本,我就必须在Android11之前和之后分开做申请才会有用。

三、步骤

1).申明权限

manifest文件里:

复制代码
<uses-permission
    android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
    tools:ignore="ScopedStorage" />

2).权限的判断

判断是否已经获得权限:

Kotlin 复制代码
 private fun checkPer(activity: PreViewActivity): Boolean {
        return if (Build.VERSION.SDK_INT >= 30) {
            EasyPermissions.hasPermissions(
                activity,
                android.Manifest.permission.MANAGE_EXTERNAL_STORAGE
            )
        } else {
            EasyPermissions.hasPermissions(
                activity,
                android.Manifest.permission.WRITE_EXTERNAL_STORAGE
            )
        }
    }

未获得权限,申请权限

Kotlin 复制代码
private fun aaa(activity: PreViewActivity, curImg: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            
                val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
                intent.data = Uri.parse("package:" + activity.packageName)
                activity.startActivityForResult(intent, 200)
           
        } else {
            val perm = android.Manifest.permission.WRITE_EXTERNAL_STORAGE
            PaperThreeVariable.isToRequestPer = true
            EasyPermissions.requestPermissions(
                PermissionRequest.Builder(
                    activity,
                    200,
                    perm
                )
                    .build()
            )
        }
    }

权限申请回调

Kotlin 复制代码
    override fun onRequestPermissionsResult(
        requestCode: Int, permissions: Array<String>, grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
    }

    override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
        AppInitUtils().saveFreshAppImageToGallery(this, curImg)
        PaperThreeVariable.isToRequestPer = false
    }

    override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {
        PaperThreeVariable.isToRequestPer = false
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            AppSettingsDialog.Builder(this)
                .setRationale("This function requires storage permission to be enabled")
                .setNegativeButton("No")
                .setPositiveButton("Yes")
                .build().show()
        }
    }

因为有时候用户会拒绝权限且永久弹窗,所以为了方便我就用了EasyPermission这个库,拒绝的情况下,弹窗跳转系统权限设置页面去让用户选择开启权限。

这样,就OK啦!(至于我的小米为啥Android 13也能正常拉起,我也不知道具体原因,但是在Android Studio的历史链接设备中,我发现它识别我的手机系统为Android 12,真是百思不得其解)

本文参考了郭霖大神的一篇文章,当时是想看下 Scoped Storage这个属性的内容,接过发现了Android 11的变更。

Android 11新特性,Scoped Storage又有了新花样

仅做个人工作总结,内容肯定不够全面,如有问题,欢迎大佬指正!

Android Permission 权限申请,EasyPermission和其他三方库_安卓权限申请_&岁月不待人&的博客-CSDN博客

相关推荐
玲小珑3 分钟前
Auto.js 入门指南(六)多线程与异步操作
android·前端
用户2018792831672 小时前
通俗易懂理解Java注解
android
用户2018792831672 小时前
通俗易懂理解泛型
android
linversion2 小时前
如何手动上传Android混淆映射文件Mapping.txt到Firebase
android
慕晨2 小时前
RecyclerView + SnapHelper 滚动差异问题
android
玲小珑2 小时前
Auto.js 入门指南(三)第一个 Auto.js 脚本
android·前端
aningxiaoxixi3 小时前
Android Studio 之基础代码解析
android·ide·android studio
A-花开堪折4 小时前
Android7 Input(十)View 处理Input事件pipeline
android·嵌入式硬件
Shujie_L5 小时前
Android基础回顾】六:安卓显示机制Surface 、 SurfaceFlinger、Choreographer
android
海棠一号5 小时前
Android Settings 数据库生成、监听与默认值配置
android·数据库