Android运行时请求权限封装

news/2024/11/13 19:09:14/文章来源:https://www.cnblogs.com/shuijinglingsos/p/18544574

@

目录
  • 1 介绍
  • 2 测试用例设计
  • 3 实现
  • 4 用例测试
  • 5 总结

本文目的:“借助透明Activity封装一个易于调用的权限请求模块”

1 介绍

Android权限的校验和申请比较简单,但在实际项目中使用时还要进行系统版本的适配,最不友好的是权限的申请结果需要在 onRequestPermissionsResult 中进行判断,如果项目中有多个地方需要申请权限,或者申请权限的代码在自定义的组件中,而申请结果判断则在activity或fragment中,那代码就会显得很乱,对于后期维护也是很不方便,因此我们就来封装一个简单的权限申请模块。

2 测试用例设计

首页我们还是先设计一个权限申请的测试用例步骤:
1、首先判断所需要的权限是否已经过用户授权;
2、如果没有经过用户授权,则申请权限;
3、如果用户授权,则调用相关功能;
4、如果用户拒绝授权,则提示信息。
解析流程:
输入:需要的权限
输出:授权/拒绝

测试用例的代码实现:

String[] permisstions = new String[];  //申请所需要权限
PermissionHelper.request(context,permisstions,new Listener(){void granted(){//授权后执行}void denied(){//拒绝后执行}
});

测试用例实现了输入、输出,其他步骤就需要在模块中实现,对调用方透明。

3 实现

首先我们先实现PermissionHelper类,功能是判断权限是否被授权,如果没有被授权则申请权限。


/*** 权限帮助类* Created by lidong on 2019/10/25.*/
public class PermissionHelper {/*** 请求权限** @param context     context* @param permissions 权限* @param listener    监听*/public static void request(Context context, String[] permissions, PermissionListener listener) {//判断权限,如果所有权限全被授权,直接返回if (checkPermission(context, permissions)) {if (listener != null) {listener.granted();}return;}//申请权限if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {  //6.0以下没有申请权限,直接返回拒绝if (listener != null) {listener.denied();}} else {  //6.0及以上申请权限//为了统一回调需要借用一个activityPermissionActivity.open(context, permissions, listener);}}/*** 校验权限** @param context     context* @param permissions 权限* @return 所有权限已被授权返回true,否则返回false*/protected static boolean checkPermission(Context context, String[] permissions) {for (String per : permissions) {int result = PermissionChecker.checkSelfPermission(context, per);if (result != PermissionChecker.PERMISSION_GRANTED) {return false;}}return true;}/*** 权限监听*/public interface PermissionListener {/*** 所有权限已被授权*/void granted();/*** 一个或多个权限被拒绝*/void denied();}
}

这里为了方便接收申请权限的结果,我们打开一个新的activity,在新activity中进行权限申请,需要将申请的权限和回调监听传入activity中:

public static void open(Context context, String[] permissions, PermissionHelper.PermissionListener listener) {Intent intent = new Intent(context, PermissionActivity.class);intent.putExtra("data", permissions);context.startActivity(intent);mPermissionListener = listener;}

PermissionActivity类:


/*** 权限申请* Created by lidong on 2019/10/25.*/
public class PermissionActivity extends Activity {private static PermissionHelper.PermissionListener mPermissionListener;private String[] permissions;private AlertDialog mAlertDialog;private boolean first = true;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);permissions = getIntent().getStringArrayExtra("data");}private void requestPermissions(){ActivityCompat.requestPermissions(this, permissions, 1);}@Overrideprotected void onResume() {super.onResume();if (first) {first = false;requestPermissions();return;}//切换页面回来重新校验一下showMissingPermissionDefiniteDialog();}/*** 拒绝授权 显示提示对话框*/private void showMissingPermissionDefiniteDialog() {if (mAlertDialog != null && mAlertDialog.isShowing()) {mAlertDialog.dismiss();}List<String> deniedList = new ArrayList<>();for (String permission : permissions) {if (PermissionChecker.checkSelfPermission(this, permission)== PermissionChecker.PERMISSION_GRANTED) {continue;}deniedList.add(permission);}if (deniedList.size() == 0) {granted();return;}List<String> tipList = transformTip(deniedList);StringBuilder tip = new StringBuilder();int i = 0;for (String temp : tipList) {if (i > 0) {tip.append(",");}tip.append(temp);i++;}AlertDialog.Builder builder = new AlertDialog.Builder(PermissionActivity.this);builder.setMessage("应用程序需要以下权限:\n\r" + tip);builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {denied();}});builder.setPositiveButton("设置", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {gotoSetting();}});builder.setCancelable(false);mAlertDialog = builder.show();}private List<String> transformTip(List<String> list) {Map<String, String> permissionList = new HashMap<>();permissionList.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, "「存储空间」");permissionList.put(Manifest.permission.READ_PHONE_STATE, "「电话」");permissionList.put(Manifest.permission.CAMERA, "「相机」");permissionList.put(Manifest.permission.RECORD_AUDIO, "「录音」");permissionList.put(Manifest.permission.ACCESS_FINE_LOCATION, "「位置」");permissionList.put(Manifest.permission.ACCESS_COARSE_LOCATION, "「位置」");List<String> tipList = new ArrayList<>();for (String temp : list) {String tip = permissionList.get(temp);if (!tipList.contains(tip)) {tipList.add(tip);}}return tipList;}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);//判断所有权限是否被授权if (isGranted(grantResults) && PermissionHelper.checkPermission(this, permissions)) {granted();} else {showMissingPermissionDefiniteDialog();}}/*** 授权回调*/private void granted(){if (mPermissionListener != null) {mPermissionListener.granted();}finish();}/*** 拒绝回调*/private void denied(){if (mPermissionListener != null) {mPermissionListener.denied();}finish();}private boolean isGranted(int[] grantResult) {for (int result : grantResult) {if (result != PackageManager.PERMISSION_GRANTED) {return false;}}return true;}/*** 跳转到当前应用对应的设置页面*/private void gotoSetting() {Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);intent.setData(Uri.parse("package:" + getPackageName()));startActivity(intent);}@Overridepublic void finish() {super.finish();overridePendingTransition(0, 0);mPermissionListener = null;}public static void open(Context context, String[] permissions, PermissionHelper.PermissionListener listener) {Intent intent = new Intent(context, PermissionActivity.class);intent.putExtra("data", permissions);context.startActivity(intent);mPermissionListener = listener;}
}

在 activity 的 onRequestPermissionsResult 方法中,校验授权结果,如果一个或多个权限未被授权,则显示提示对话框,对话框有“设置”按钮跳转到应用程序详情页面,可以进入权限设置页面修改权限。

为了兼容在程序以外的地方手动修改权限,再切换回当前页面的情况,我们在 onResume 方法里增了页面切换回来后重新判断权限是否被授权。

到这里已经封装完成了。

4 用例测试

现在我们完善一下测试用例:

String[] permissions=new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA,Manifest.permission.READ_PHONE_STATE,};PermissionHelper.request(context, permissions, new PermissionHelper.PermissionListener() {@Overridepublic void granted() {showToast("已授权");}@Overridepublic void denied() {showToast("已拒绝");}});

运行测试用例,发现申请权限的activity是白色背景,我们可以在 AndroidManifest.xml 文件中将 activity 设置成全屏透明窗体,用户体验也会好点。

好了,以后无论在哪里需要申请权限,我们只需要这几行代码就够了!

5 总结

申请权限的封装,主要是利用一个透明的activity来完成需要在 activity 中接收结果的情况。其实微信的支付sdk也有用到透明的activity。使用透明activity可以用来将调用和回调代码组装一起,增加代码的可读性和维护性。

END


本文的技术设计和实现都是基于作者工作中的经验总结,如有错误,请留言指正,谢谢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/833086.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Paper Reading] Fusing Monocular Images and Sparse IMU Signals for Real-time Human Motion Capture

目录名称TL;DRMethodLocal Pose EstimationRNN-P1RNN-P2RNN-P3Global Translation EstimationRNN-T1RNN-T2RNN-T3Hidden State Feedback MechanismExperiment效果可视化总结与发散相关链接 名称 link 时间:23.09 作者与单位:主页: https://github.com/shaohua-pan/RobustCap…

HarmonyOS Next 入门实战 - 创建项目、主题适配

​开发一个简单的demo,其中涉及一些鸿蒙应用开发的知识点,其中涉及导航框架,常用组件,列表懒加载,动画,深色模式适配,关系型数据库等内容,在实践中学习和熟悉鸿蒙应用开发。 ​​ ​​ 首先下载并安装DevEco Studio开发环境,下载完成后按照提示安装即可,过程不在多说…

rust学习八、包和模块

总体上,也没有什么特别的地方,和其它语言比较起来。 我们可以看懂熟悉的字眼:包括、模块、use、公共等等 如果是英文,则需要知道crate、pub。 本章节对应相关书籍的第七章节. 一、一个rust可执行程序的大体结构 就本章节而言,尚未接触到一个非常复杂的工程结构,据说有什么…

starrycan的pwn学习记录1

一.Introducation 0x01 简介CTF 0x02 什么是pwn ”Pwn”是一个黑客语法的俚语词,是指攻破设备或者系统 。发音类似“砰”,对黑客而言这就是成功实施黑客攻击的声音--砰的一声,被“黑”的电脑或手机就被你操纵了。 CTF中的pwn CTF中的PWN主要是针对于二进制漏洞挖掘与利用,通…

计算机组成原理与操作系统 第二章 处理机组成与管理

目录1.CPU的功能和组成1.1CPU的四大功能1.2CPU的基本组成1.3 一条指令如何在CPU内运行2.指令系统2.1机器语言与指令2.1.1基本概念2.1.2一条指令一般应包含的信息2.1.3指令的类型与功能2.1.4寻址方式2.2指令格式的设计2.2.1基本概念2.2.2指令类型2.2.3操作码类型2.2.4指令设计2.…

UWB无线通信技术

UWB定位与通信技术标准第2章 UWB无线通信技术 UWB(超宽带)技术最早诞生于无线通信领域,该新兴技术一出现就备受关注UWB信号有着极大的带宽,其时间分辨率高、抗多径效应能力强,被认为是高速率短距离无线通信中具有很强竞争力的候选方案之一为此,本章寻根溯源,从UWB无线通…

极速启动,函数计算弹性降本能力再升级

本文将深入探讨函数计算如何通过技术革新实现提效降本,以及其在 AI 业务、数据处理和 Web 应用等多个领域的广泛应用。作者:墨飏 在数字化转型的大潮中,云计算成为推动创新和优化业务流程的关键力量。作为阿里巴巴集团的核心产品之一,函数计算(Function Compute)引领着 S…

用函数实现模块化程序设计四

数组作为函数参数数组作为函数参数 调用有参函数时,需要提供实参,实参可以是常量、变量或表达式 数组元素的作用与变量相当,一般来说,凡是变量可以出现的地方,都可以用数组元素代替,因此,数组元素也可以用作函数实参,其用法与变量相同,向形参船体数组元素的值。此外,…

Vulnhub W1R3S: 1.0.1

Vulnhub W1R3S: 1.0.1 0x01:端口扫描 主机发现,靶机ip:192.168.231.133 nmap -sn 192.168.231.0/24-sn 仅主机扫描 /24 扫描c段详细全端口扫描 nmap -sT -sC -sV -O -p21,22,80,3306 192.168.231.133 -oA /root/scan/1/-sT: 以TCP进行扫描; -sC:使用 nmap 的默认脚本集合进…

永宏BI 自定义绘图(环状图)

结果样式:绑定数据:自定义JS代码:点击查看代码 option = {tooltip: {trigger: item,formatter: {a} <br/>{b}: {c} ({d}%)},series: [{type: pie,radius: [50%, 70%],avoidLabelOverlap: false,label: {show: false,position: center},emphasis: {label: {show: false…