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 小时前
Android 快捷方式实战指南:静态、动态与固定快捷方式详解
android
hqk3 小时前
鸿蒙项目实战:手把手带你实现 WanAndroid 布局与交互
android·前端·harmonyos
LING4 小时前
RN容器启动优化实践
android·react native
恋猫de小郭6 小时前
Flutter 发布官方 Skills ,Flutter 在 AI 领域再添一助力
android·前端·flutter
Kapaseker11 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴11 小时前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭21 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab1 天前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
BoomHe1 天前
Now in Android 架构模式全面分析
android·android jetpack
二流小码农1 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos