Android---动态权限申请
迪丽瓦拉
2025-05-30 10:46:37
0

目录

权限分类

动态权限核心函数

简易实现案例

完整代码

 

 

Google 在 Android 6.0 开始引入了权限申请机制,将所有权限分成了正常权限危险权限。App 每次在使用危险权限时需要动态的申请并得到用户的授权才能使用。

权限分类

系统权限分为两类:正常权限危险权限。

正常权限:不会直接给用户隐私带来危险。如果你在其清单中列出了正常权限,系统将自动授予该权限。

危险权限:授予应用访问用户机密数据的权限。如果你在清单文件中列出了危险权限,则用户必须明确批准你的应用使用这些权限。那么危险权限有那些?日历(CALENDAR)相机(CAMERA) 通讯录(CONTACTS)位置(LOCATION)拨号(PHONE)短信(SMS)存储(STORAGE)等。




















申请以上权限时,除了要在清单文件中添加权限,还需要通过代码动态申请。

动态权限核心函数

1. 检测权限

checkSelfPermission(@NonNull String permission)

2. 申请权限

requestPermissions(@NonNull String[] permissions, int requestCode)

3. 处理结果回调

onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)

4. 是否需要显示 UI 界面提示用户为什么需要这个权限

shouldShowRequestPermissionRationale(@NonNull String permission)

简易实现案例

步骤1:在 AndroidManifest.xml 添加要申请的权限。这里以存储权限为例


骤2:封装一个 requestPermission 方法来动态检测和申请权限

    @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);requestPermission();}

 requestPermission() 函数里会先检测存储权限,如果没开启则动态申请存储权限。

private void requestPermission() {// checkSelfPermission() 检测权限if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {//TODO 申请存储权限ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},PERMISSION_REQUEST_CODE);}}

注意:这个 demo 里只申请了一个权限,当我们需要申请多个权限时,可以往requestPermissions 里的第二个参数添加其它需要的权限,因为它本就是一个 String 数组,且也要在 AndroidManifest里添加。

new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA}

步骤3:处理用户选择的结果(“允许” / “拒绝”),重写 onRequestPermissionsResult()方法。

//TODO 处理权限结果回调@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == PERMISSION_REQUEST_CODE) {//用户点击了“确定” == grantResults[0] == PackageManager.PERMISSION_GRANTED)if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {Log.i("TAG", "onRequestPermissionsResult granted");} else {Log.i("TAG", "onRequestPermissionsResult denied");// TODO 用户拒绝权限申请,则弹出警示框showWaringDialog();}}}

步骤4:当用户拒绝权限,则弹出警示框,并在用户点击“确定”后直接退出页面。因为没有存储权限肯定不能使用该应用的。

/*** 用户拒绝权限的警示*/private void showWaringDialog() {new AlertDialog.Builder(this).setTitle("警告!").setMessage("请前往设置->应用->权限管理->打开存储权限,否则无法正常使用!").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//TODO 一般情况下如果用户不授权的话,功能时无法运行的,则直接退出finish();}}).show();}

完整代码

MainActivity.java

package com.example.dynamicauthority;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;public class MainActivity extends AppCompatActivity {private static final int PERMISSION_REQUEST_CODE = 999;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);requestPermission();}private void requestPermission() {// checkSelfPermission() 检测权限if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {//TODO 申请存储权限ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},PERMISSION_REQUEST_CODE);}}//TODO 处理权限结果回调@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == PERMISSION_REQUEST_CODE) {//用户点击了“确定” == grantResults[0] == PackageManager.PERMISSION_GRANTED)if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {Log.i("TAG", "onRequestPermissionsResult granted");} else {Log.i("TAG", "onRequestPermissionsResult denied");// TODO 用户拒绝权限申请,则弹出警示框showWaringDialog();}}}/*** 用户拒绝权限的警示*/private void showWaringDialog() {new AlertDialog.Builder(this).setTitle("警告!").setMessage("请前往设置->应用->权限管理->打开存储权限,否则无法正常使用!").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//TODO 一般情况下如果用户不授权的话,功能时无法运行的,则直接退出finish();}}).show();}
}

相关内容

热门资讯

处理大数据的最佳方式——con... css属性处理大数据 content-visibility——只需一行CSS代码,让长...
Vuex由浅入深详细讲解 目录前言一,理解Vuex1.1 Vuex是什么1.2 Vuex概述1.3 Vuex统一...
Vector - CAPL -... 摸鱼聊天、答疑解惑首选之地 --- 车载网络哪些事儿你是否还在为VT板卡系统昂贵而发愁?...
qt5.6(mingw) 编译... 具体版本和操纵参考官网win msvc版本编译,Qt5.6编译PCL环境 备注...
【论文速览】引入motion ... 文章目录研究背景解决思路实验效果思考参考资料 收录于 ECCV 2020,代码地址...
字符串 - 二进制和文本字符串... 1.应用场景 主要用于探究字符串中的二进制和文本字符串,以及它们的区别和应用场景。2....
windows下使用gitea... windows下使用gitea搭建git服务器 详细过程 1、简述 使用过好几个git服务器...
LCHub:一句话让 AI 替... LCHub 3 月 18 日消息,这几天,GPT-4 接入微软 Office 全家桶的消息传遍了互联...
STM32模拟SPI控制NRF... STM32模拟SPI控制NRF24L01发送和接收 NRF24L01是一款2.4Ghz ISM频段无...
Vue路由及状态管理 1,Vue引入路由配置 在Vue中,我们可以通过vue-router路...
Lua 开发过程中常见坑 Lua 开发过程中常见坑 Lua next return _G.next( tb ) =&#...
蓝桥c++数位排序(运用pai... 问题描述 小蓝对一个数的数位之和很感兴趣, 今天他要按照数位之和给数排序。当 两个数各个数位之和不同...
3Dmax开孔打洞圆孔洞的几种... 最常见的几种打洞方法及技巧和注意事项总结如下。除了布尔运算外其余几种都是在可编辑多边形模式下进行的&...
04 - 进程参数编程 ---- 整理自狄泰软件唐佐林老师课程 查看所有文章链接:(更新中&...
【Git使用学习】本地创建项目... 记录学习过程,一波三折。以【Vue+CesiumJS学习(1&#...
电子拣货标签1代系统简介 CK_Label_v1 ​一、产品参数 1. 电池供电版 产品型号 CK_Label_v1 尺...
为什么写分页器的时候要用当前页... 比方说总共有100条数据(编号从0起算就是0到99),每次...
古典密码学 主要划分方式及其分类按密钥方式划分:对称,非对称按明文处理方式分...
C# 项目名称为什么是xxx.... 在 C# 中,通常将项目命名为“xxx.xxx”的形式,其中第一个“xx...
【Java】UDP网络编程 文章目录前言DatagramSocketDatagramPacket注意事项与区别代码演示 前言 U...