Android 11 「外部存储」权限适配方案——权限申请框架推荐

2023-11-01


1.权限种类

1.1权限种类区分-普通权限、危险权限、特殊权限

首先 Android 的权限大致分为三种:
普通权限:只需要在清单文件中注册即可
危险权限:需要在代码中动态申请,以弹系统 Dialog 的形式进行请求
特殊权限:需要在代码中动态申请,以跳系统 Activity 的形式进行请求

1.2存储权限-变化

存储权限:
在 Android 6.0 之后就变成了危险权限;
在 Android 11 上面变成了特殊权限;
申请方式的发生了不同


2.外部存储和内部存储对比

2.1外部存储在手机哪个位置?

Android4.4之前:
内部存储在手机ROM上的一块存储区域;
外部存储在SD卡上;

Android4.4之后:
内部存储在手机ROM上的一块存储区域;
外部存储也在手机ROM上的一块存储区域;

在这里插入图片描述

2.2外部存储和内部存储的访问权限区别

在这里插入图片描述


3.外部存储适配方案

3.1 Android 10.0 以下外部存储权限适配

  • 升级 targetSdkVersion
android 
    defaultConfig {
        targetSdkVersion 23
    }
}
  • 添加清单权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • 如果 targetSdkVersion >= 29 上,还需要在清单文件中加上
<application
    android:requestLegacyExternalStorage="true">
  • 代码动态申请
public final class PermissionActivity extends AppCompatActivity {

    private static final int REQUEST_CODE = 1024;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestPermission();
    }

    private void requestPermission() {
    	//判断版本大于等于android 6.0
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 先判断有没有权限
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                writeFile();
            } else {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
            }
        } else {
            writeFile();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                writeFile();
            } else {
                ToastUtils.show("存储权限获取失败");
            }
        }
    }

    /**
     * 模拟文件写入
     */
    private void writeFile() {
        ToastUtils.show("写入文件成功");
    }
}

3.2 Android 11 及以上申请外部存储权限

  • 升级 targetSdkVersion
android 
    defaultConfig {
        targetSdkVersion 30
    }
}
  • 添加清单权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
  • 代码动态申请
public final class PermissionActivity extends AppCompatActivity {

    private static final int REQUEST_CODE = 1024;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestPermission();
    }

    private void requestPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // 先判断有没有权限
            if (Environment.isExternalStorageManager()) {
                writeFile();
            } else {
                Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
                intent.setData(Uri.parse("package:" + context.getPackageName()));
                startActivityForResult(intent, REQUEST_CODE);
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 先判断有没有权限
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                writeFile();
            } else {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
            }
        } else {
            writeFile();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                writeFile();
            } else {
                ToastUtils.show("存储权限获取失败");
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            if (Environment.isExternalStorageManager()) {
                writeFile();
            } else {
                ToastUtils.show("存储权限获取失败");
            }
        }
    }

    /**
     * 模拟文件写入
     */
    private void writeFile() {
        ToastUtils.show("写入文件成功");
    }
}

4.权限申请框架推荐

4.1 XXPermissions

4.1 AndPermission

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 11 「外部存储」权限适配方案——权限申请框架推荐 的相关文章

  • Android 中多个蓝牙连接的自定义 UUID

    我有一个 Android 设备作为服务器连接到多个蓝牙 Android 客户端 我了解 UUID 的概念以及它的独特之处 我的问题是 我可以为连接到我的服务器的所有客户端使用相同的 UUID 吗 如果没有 我如何以编程方式为我的客户端生成
  • gradle更新后无法找到方法(无法编译项目)

    我尝试将项目中的 gradle 版本更新为 4 1 milestone 1 以下这些说明 https developer android com studio build gradle plugin 3 0 0 migration html
  • 如何在 Linux 内核中定义并触发我自己的新软中断?

    我想在 Linux 内核中创建自己的软中断 这是正确的方法吗 In the init我想触发该模块的softirq我将添加一个调用 394 void open softirq int nr void action struct softir
  • 自定义首选项中的android首选项水平分隔线?

    我创建了自己的自定义首选项对象来扩展首选项 我创建它们只是因为这些自定义数据类型没有首选项 一切正常 但我的自定义首选项没有相同的外观 因为它们缺少系统首选项对象具有的水平分隔线 我已经查找了创建水平分隔线的代码 但我找不到它是在哪里完成的
  • 在 Cordova 应用程序中获取额外功能

    我们有两个 Android 应用程序 一个使用本机 Java 实现 另一个使用 Ionic 编写 Ionic 应用程序启动我的应用程序 这是使用灯插件 https github com lampaa com lampa startapp 我
  • Android Eclipse 上的 Web 服务

    我是 android eclipse java 的新手 事实上这个论坛也是如此 有人遇到过这种情况吗 从用户那里获取输入并通过使用 android eclipse 中的 Web 服务来显示适当的结果 有可用的示例吗 非常感谢 我正在发布教程
  • Android 手机作为 GSM 调制解调器在 PC 上发送/接收短信?

    是否可以将 Android 移动设备用作 PC 上的 GSM 调制解调器 我正在 net下开发应用程序来发送 接收短信等 现在我想通过 USB 将我的 Android 设备连接到我的 PC 并将其用作 GSM 调制解调器来与其通信 这里是参
  • 当 OnFocusChangeListener 应用于包装的 EditText 时,TextInputLayout 没有动画

    不能比标题说得更清楚了 我有一个由文本输入布局包裹的 EditText 我试图在 EditText 失去焦点时触发一个事件 但是 一旦应用了事件侦听器 TextInputLayout 就不再对文本进行动画处理 它只是位于 editText
  • 图像作为电子邮件附件

    我想构建一个应用程序 我可以在电子邮件中附加图像 打开图像并将其设置为我的壁纸 我想让它跨平台 所以你能告诉我是否可以使用phonegap 或者我是否必须为iphone和android构建一个本机应用程序 您好 如果您只想通过电子邮件附加图
  • 从 BroadcastReceiver 类调用活动方法

    我知道我可以做一个内部接收器类来调用接收器中的任何方法 但我的主要活动太大了 要做的事情也很多 因此 我需要一个扩展广播接收器的类 但它不是内部类 并且可以从我的主要活动中调用一种方法 我不知道是否可能 但我的活动是家庭活动和 single
  • 对于一个单元格,RecyclerView onBindViewHolder 调用次数过多

    我正在将 RecyclerView 与 GridLayoutManager 一起使用 对于网格中的每个项目 我需要调用 REST api 来检索数据 然后 从远程异步获取数据后 我使用 UIL 加载 显示图像 一切似乎都很好 但我发现 on
  • okhttp 获取失败响应

    我已经在我的 android 客户端中实现了 okhttp 来进行网络调用 当我收到失败响应时 我会收到失败代码以及与该代码相关的文本作为消息 但我没有收到服务器发送给我的自定义失败响应 在我实施的代码中的失败响应中 我收到的消息只是 错误
  • 如何在 Android 中从 WorkManager 取消工作?

    我已经保存了 WorkManagerUUID转换成String在领域数据库中 这是代码 Constraints constraints new Constraints Builder setRequiredNetworkType Netwo
  • Dagger 2 没有生成我的组件类

    我正在使用 Dagger 2 创建我的依赖注入 几个小时前它还在工作 但现在不再生成组件 这是我创建组件的地方 public class App extends Application CacheComponent mCacheCompon
  • 找不到符号 NOTIFICATION_SERVICE?

    package com test app import android app Notification import android app NotificationManager import android app PendingIn
  • 在 Android 应用程序资源中使用 JSON 文件

    假设我的应用程序的原始资源文件夹中有一个包含 JSON 内容的文件 我如何将其读入应用程序 以便我可以解析 JSON See 开放原始资源 http developer android com reference android conte
  • Android:如何从网络异步获取搜索建议?

    我创建了一个可搜索的活动 现在 我想添加从网络服务获取的搜索建议 我想异步获取这些建议 根据添加自定义建议 http developer android com guide topics search adding custom sugge
  • 我的应用程序中的后退按钮出现问题[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想在手机关闭时清除共享首选项值 你
  • Dagger 2 中“HasFragmentInjector”的实际用法是什么

    我之前已经实现了 dagger2 v2 2 但现在他们也添加了 dagger android 部分 所以我正在用它创建示例项目 我知道旧的方法论 Provide and Modules and 成分等注释 但从 Dagger 2 8 开始
  • 有没有任何代码可以在android中设置壁纸而无需裁剪和缩放?

    我正在创建一个画廊应用程序 我的第一个应用程序 这是我的代码 Bitmap bmd BitmapFactory decodeStream is try getApplicationContext setWallpaper bmd catch

随机推荐

  • 淤地坝安全自动监测预警系统解决方案

    一 方案背景 淤地坝是在水土流失地区各级沟道中 以拦泥淤地为目的而修建的坝工建筑物 其主要作用为 滞洪 拦泥 淤地 蓄水 减轻黄河泥沙 保持水土不流失 建设农田 发展农业生产等 我国黄土高原地区现有淤地坝58776座 存在量多面广 建设标准
  • PowerShell脚本文件无法加载运行

    显示Restricted 不允许执行任何脚本 Get ExecutionPolicy RemoteSigned 可执行任何脚本 需要管理员权限 才能设置成功 Set ExecutionPolicy RemoteSigned
  • Centos 7 配置IP地址时network 和networkmanager冲突

    一 区别 1 network service的制御网络接口配置信息改动后 网络服务必须从新启动 来激活网络新配置的使得配置生效 这部分操作和从新启动系统时时一样的作用 制御 控制 是 etc init d network这个文件 可以用这个
  • 2.4.1 用NPOI操作EXCEL--画线

    之所有说NPOI强大 是因为常用的Excel操作她都可以通过编程的方式完成 这节开始 我们开始学习NPOI的画图功能 先从最简单的开始 画一条直线 对应的代码为 HSSFSheet sheet1 hssfworkbook CreateShe
  • android中完全退出当前应用程序的四种方法

    Android程序有很多Activity 比如说主窗口A 调用了子窗口B 如果在B中直接finish 接下里显示的是A 在B中如何关闭整个Android应用程序呢 本人总结了几种比较简单的实现方法 1 Dalvik VM的本地方法 andr
  • toFixed精度丢失问题

    bug说明 10 3950 3935 00 用toFixed 2 得到的是40904 32 实际应该是40904 33 解决的方法 第一种 在main js中直接复制下面代码即可 Number prototype toFixed funct
  • 【9秒原创】cocos2d-x横版rts手游《口袋仙侠》alpha1.0正式开源

    9秒原创 Firefly cocos2d x的横版rts手机网游 口袋仙侠 alpha V1 0 商用版本 完整源码下载 特别声明 1 口袋仙侠 项目基于MIT协议 9秒社团团队允许任何厂商及个人对其进行修改和商用 并将会在本板块内进行技术
  • Linux NetworkManager网络服务详解

    一 网络配置文件 Linux 为 配 置 网 络 提 供 了 许 多 工 具 其 中 有 图 形 界 面 的 如 NetworkManager 也有伪图形界面 如 system config network 的 虽然使用这些工具来配置网络会
  • iSH使用与优化全网整合教程【持续更新】【精华】

    最后一次更新 2023 4 22 请勿利用文章内的相关技术从事非法测试 由于传播 利用此文所提供的信息而造成的任何直接或者间接的后果及损失 均由使用者本人负责 作者不为此承担任何责任 iSH介绍与换源 已安装并已完成换源的用户可直接跳过 介
  • Deep Java Library(六)DJLServing自定义模型,自定义Translator注意事项

    DJLServing自定义模型中自定义Translator注意事项需要仔细读一下DJLServing源码中的ServingTranslatorFactory类 一开始不了解以为DJLServing选择Translator像玄学 后来看了像迷
  • C语言常见笔试题——strcpy函数的实现

    转载地址 http blog csdn net gpengtao article details 7464061 大家一般认为名不见经传strcpy函数实现不是很难 流行的strcpy函数写法是 cpp view plain copy ch
  • Java电子招投标采购系统源码-适合于招标代理、政府采购、企业采购、等业务的企业

    功能描述 1 门户管理 所有用户可在门户页面查看所有的公告信息及相关的通知信息 主要板块包含 招标公告 非招标公告 系统通知 政策法规 2 立项管理 企业用户可对需要采购的项目进行立项申请 并提交审批 查看所有的立项信息 主要功能包含 招标
  • 用java做一个登录界面

    这篇文章教大家做一个简单的登录界面 方法如下 1 界面由三个部分组成 可视化部分 窗体 按钮 输入框 标签 元素规则部分 尺寸 颜色 字体 布局管理器 内容部分 字符串 图片 2 界面开发包 1 java awt Abstract Wind
  • C++基础之注释

    文章目录 前言 一 注释的语法 二 注意 三 优美的注释 四 总结 前言 注释在程序编写中很重要 一个良好的注释在编写注释时更重要 一 注释的语法 注释有两种风格的语法 c风格或者说 多行 注释 只是一个c风格的注释 或者说是多行注释 c
  • pytest 之skip 跳过某条测试用例执行

    前言 相信大家对于pytest 框架官方介绍的那几种跳过用例执行的方法都熟悉并且能够运用在自己的项目中了 但是设想有下面一种场景 使用pytest 框架编写了一个接口的自动化测试 请求体使用了 pytest mark parametrize
  • idea社区版已经足够强大了

    idea使用企业版还是社区版 社区版不支持的功能 Profiling tools JVM性能分析工具 类似的工具有很多 Spring 微服务开发时没有Servers标签 yaml配置文件不能提前校验 除此以外没啥感觉 JavaEE Micr
  • stm32初学笔记(一)真·入门笔记

    最近在学习stm32 看的是野火的 b站就有视频 此博客记录我在学习中的重点与困惑 笔者不是第一次学习嵌入式 之前学过51 知道嵌入式的门槛 此文章旨在解决真正零基础的人的疑问 所以写的很详细 每一个视频我都看了两遍以上 尽可能的列举了我在
  • 外观检验人员一致性(Kappa)分析

    系列文章目录 文章目录 系列文章目录 前言 一 目的 二 分析方法 三 判定方法 四 评价流程 1 实验设计及实施 五 结果分析 分析一 检验员自身一致性 重复性 分析二 每个检验员与标准之间一致性 分析三 检验员之间 再现性 分析四 所有
  • 航班订票功能的简要实现

    实现航班订票功能与WebService实现身份证验证 一 系统模块分析 a 普通用户 b 管理员 二 UML建模示例 1 航班管理系统UML类图表示 2 航班管理系统UML用例图表示 3 航班管理系统UML时序图表示 三 设计模式分析 1
  • Android 11 「外部存储」权限适配方案——权限申请框架推荐

    文章目录 1 权限种类 1 1权限种类区分 普通权限 危险权限 特殊权限 1 2存储权限 变化 2 外部存储和内部存储对比 2 1外部存储在手机哪个位置 2 2外部存储和内部存储的访问权限区别 3 外部存储适配方案 3 1 Android