Android权限动态申请(包括悬浮窗)

目录

效果图

一、环境配置

二、新建工具类

 三、开始使用

备注(一):用户手动设置权限

手动设置效果图

备注(二):在Fragment中如何调用动态权限申请

备注(三):悬浮窗权限处理

1、配置环境

 2、核心代码

 3、在需要使用的地方调用上面的函数

悬浮窗申请效果图


效果图

一、环境配置

AndroidManifest.xml中先配置需要的权限,这里以【读写通讯录】权限为例: 

<uses-permission android:name="android.permission.READ_CONTACTS" /> <!-- 联系人权限-读 -->
<uses-permission android:name="android.permission.WRITE_CONTACTS" /> <!-- 联系人权限-写 -->

二、新建工具类

新建一个工具类PermissionUtil.class,用于循环【验证权限】、【申请权限】及【申请权限后用户的选择结果】的操作处理。

/**
 * 权限工具类
 */
public class PermissionUtil {

    /**
     * 判断是否权限都已授权,存在未授权则进行申请授权
     * @param activity
     * @param permissions 权限列表
     * @param requestCode
     * @return
     */
    public static boolean checkPermission (Activity activity, String[] permissions, int requestCode ) {

        // 默认已经授权
        int check = PackageManager.PERMISSION_GRANTED;

        // 判断安卓版本是否是大于6.0(6.0及以上才需要申请权限)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            // 循环处理
            for (String permission : permissions) {
                // 验证单个权限是否授权-【核心】
                check = ContextCompat.checkSelfPermission(activity, permission);
                // 判断发现存在某一个未授权
                if (check != PackageManager.PERMISSION_GRANTED) {
                    break;
                }
            }
        }

        // 存在某一个未授权,重新进行申请权限
        if (check != PackageManager.PERMISSION_GRANTED) {

            // 执行权限列表的申请-【核心】
            ActivityCompat.requestPermissions(activity, permissions, requestCode);
            return false;
        }

        return true;
    }


    /**
     * 判断权限集合是否授权结果里是否存在未授权的情况,如果有返回false,否则反之
     * @param grantResults
     * @return
     */
    public static boolean checkGrant (int[] grantResults) {

        // 判断是否存在结果集合,没有直接返回false
        if (grantResults != null) {
            // 循环判断
            for (int grant : grantResults) {
                // 判断是否有未授权
                if (grant != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
}

 三、开始使用

在需要使用的activity中,添加以下代码,通过前面的工具类PermissionUtil中的checkPermission方法进行【验证权限】和【申请权限】,然后通过onRequestPermissionsResult监听【申请权限后用户的选择结果】:

    private static final int REQUEST_CODE = 1; // 申请权限状态标识

    private static final String[] PERMISSIONS_CONTACTS = new String[] {
        // 申请权限集合
        Manifest.permission.READ_CONTACTS,
        Manifest.permission.WRITE_CONTACTS
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        // 判断是否有获取对应权限,没有则进行申请
        PermissionUtil.checkPermission(getActivity(), PERMISSIONS_CONTACTS, REQUEST_CODE);
    }

    /**
     * 判断申请权限用户是否同意
     * @param requestCode The request code passed in
     * @param permissions The requested permissions. Never null.
     * @param grantResults The grant results for the corresponding permissions
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE) {
            if (PermissionUtil.checkGrant(grantResults)) {
                // 用户授予了权限,执行相应操作
                Log.d(TAG, "用户授予了权限");

            } else {
                // 用户拒绝了权限
                Log.e(TAG, "用户拒绝了权限");

            }
        }
    }

备注(一):用户手动设置权限

因为用户一旦拒绝2次权限申请,就不会再提示该权限的申请,就需要一个一个跳转该app的系统设置-权限页面,让用户手动设置的方法,如下所示:

    // 跳转设置-权限
    private void jumpToSetting () {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.fromParts("package", getPackageName(), null));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
手动设置效果图

备注(二):在Fragment中如何调用动态权限申请

 代码基本一致,只是要在父activity中加上这一段代码:

    // 在Activity中遍历所有的Fragment,并调用它们的onRequestPermissionsResult方法
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        for (Fragment fragment : getSupportFragmentManager().getFragments()) {
            if (fragment != null) {
                fragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    }

备注(三):悬浮窗权限处理

悬浮窗权限比较特殊,无法弹出给用户选择,需要跳转到系统设置,让用户自己手动开启

1、配置环境
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /><!-- 悬浮窗权限 -->
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" /><!-- 悬浮窗权限 -->
 2、核心代码

直接复制粘贴拿去用就好:

    // 判断是否有悬浮窗权限
    public boolean isOverlayPermission(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return Settings.canDrawOverlays(context);
        } else {
            try {
                Class clazz = Settings.class;
                Method method = clazz.getDeclaredMethod("canDrawOverlays", Context.class);
                return (Boolean) method.invoke(null, context);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    // 跳转系统设置-悬浮窗页面
    public void jumpToPermission() {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getContext().getPackageName()));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
 3、在需要使用的地方调用上面的函数
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        // 判断是否有获取悬浮窗,有的话才执行startService
        if (isOverlayPermission(getContext())) {
            // 悬浮窗权限已被授予,可以显示悬浮窗
            Log.d(TAG, "悬浮窗权限已被授予");
           
        } else {
            // 悬浮窗权限未被授予
            Log.e(TAG, "悬浮窗权限未被授予");

            // 跳转系统设置去手动开启
            jumpToPermission();
        }
    }
悬浮窗申请效果图

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件外包开发的需求表达方法

软件开发需求的有效表达对于项目的成功至关重要。无论选择哪种需求表达方法&#xff0c;清晰、详细、易于理解是关键。与开发团队建立良好的沟通渠道&#xff0c;确保他们对需求有充分的理解&#xff0c;并随着项目的推进及时调整和更新需求文档。以下是一些常用的需求表达方法…

CMT2300A超低功耗127-1020MHz Sub-1GHz全频段SUB-1G 射频收发芯片

CMT2300A超低功耗127-1020MHz Sub-1GHz全频段SUB-1G 射频收发芯片 Sub-1GHz&#xff0c;是指小于1GHz频率的统称。Sub-1GHz无线电频段应用的主要特点&#xff1a;&#xff08;1&#xff09;频率较低波长较长&#xff0c;传输距离远&#xff0c;穿透性强&#xff1b;&#xff0…

互联网Java工程师面试题·微服务篇·第一弹

目录 ​编辑 1、您对微服务有何了解&#xff1f; 2、微服务架构有哪些优势&#xff1f; 3、微服务有哪些特点&#xff1f; 4、设计微服务的最佳实践是什么&#xff1f; 5、微服务架构如何运作&#xff1f; 6、微服务架构的优缺点是什么&#xff1f; 7、单片&#xff0c…

本地PHP搭建简单Imagewheel私人云图床,在外远程访问——“cpolar内网穿透”

文章目录 1.前言2. Imagewheel网站搭建2.1. Imagewheel下载和安装2.2. Imagewheel网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…

ceph的体系结构

文章目录 CephCeph的体系结构对象存储RADOSOSDOSD的状态osd状态检测 数据寻址file--->Object映射Object--->pg映射pg--->osd思考&#xff1a;为什么要在Object和osd之间增加一层pg的映射呢&#xff1f; 存储池monitormonitor与客户端的通信Monitor与osd的通信 数据操作…

Jmeter添加变量的四种方法

一、在样本中添加同请求一起发送的参数。根据服务器设置的数据类型&#xff0c;来添加不同类型的参数 二、用户定义的变量 1、创建&#xff1a;添加->配置元件->用户定义的变量 2、作用&#xff1a;当前的线程组内所有Sampler都可以引用变量&#xff0c;方便脚本更新&a…

[PyTorch][chapter 62][强化学习-基本概念]

前言&#xff1a; 目录&#xff1a; 强化学习概念 马尔科夫决策 Bellman 方程 格子世界例子 一 强化学习 强化学习 必须在尝试之后&#xff0c;才能发现哪些行为会导致奖励的最大化。 当前的行为可能不仅仅会影响即时奖赏&#xff0c;还有影响下一步奖赏和所有奖赏 强…

BUUCTF刷题十一道【缺】(10)

文章目录 EasyBypass[SCTF2019]Flag Shop[BSidesCF 2019]SVGMagic[极客大挑战 2020]Greatphp[GYCTF2020]Easyphp【留坑-反序列化】[HarekazeCTF2019]Avatar Uploader 1[FireshellCTF2020]Caas[ISITDTU 2019]EasyPHP[N1CTF 2018]eating_cms[GYCTF2020]Ez_Express【留坑-nodejs原…

Power Automate-变量和excel表数据的应用

前提表格 Power Automate连接excel请参考&#xff1a;SharePoint-连接Excel-CSDN博客 需求1&#xff1a;计算表格中某列的和 添加操作&#xff0c;搜索变量&#xff0c;选择初始化变量 添加变量的名称、类型和初始值 再新增操作&#xff0c;搜索Excel&#xff0c;点击查看更多…

二叉树题目:二叉树最大宽度

文章目录 题目标题和出处难度题目描述要求示例数据范围 前言解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;二叉树最大宽度 出处&#xff1a;662. 二叉树最大宽度 难度 5 级 题目描述 要求 给定一个二叉树的根结点 …

【Python基础】一个简单的TCP通信程序

&#x1f308;欢迎来到Python专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mys…

事务JdbcTemplate

Spring框架对JDBC进行封装&#xff0c;使用JdbcTemplate方便对数据库操作。 1.搭建模块 2.引入依赖 <dependencies><!-- spring jdba Spring持久化层支持jar包--><dependency><groupId>org.springframework</groupId><artifactId>…

GB28181流媒体平台LiveGBS切换为国产信创环境下达梦数据库、高斯数据库、瀚高数据库的配置说明

LiveGBS流媒体平台GB/T28181功能-支持数据库切换为高斯数据库信创瀚高数据信创数据库 1、如何配置切换信创达梦数据库&#xff1f;2、如何配置切换高斯数据库&#xff1f;3、如何配置切换信创瀚高数据库&#xff1f;4、搭建GB28181视频直播平台 1、如何配置切换信创达梦数据库&…

Linkage Mapper 报错

1 . 错误提示&#xff1a;“No module named lm_config” 错误原因&#xff1a;**** 2.错误提示&#xff1a;“Cannot find an installation of Circuitscape in your Program Files directory.” 错误原因&#xff1a;***** 3. 错误提示&#xff1a;UnicodeEncodeError: ‘asc…

Element-Ui el-table 动态添加行

一、在项目需要使用 这个需求主要是在项目中需要用到 1.点击新增按钮&#xff0c;可以实现新增行。 2.在每个列里面可以进行输入。 3.可以删除新增的行&#xff0c;包括数据。 二、HTML代码 1.主要是循环每一个列&#xff0c;而且这些列都是动态&#xff0c;根据父组件传过来…

Facebook平台特征概述

Facebook是全球最大的社交媒体平台之一&#xff0c;拥有数十亿的用户。它的独特特征和功能使其成为人们分享、互动和连接的理想场所。下面小编将讲一下关于Facebook平台的特征的详细概述。 1、用户个人资料 每个Facebook用户都有一个个人资料页面&#xff0c;可以在上面分享个…

java算法学习索引之动态规划

一 斐波那契数列问题的递归和动态规划 【题目】给定整数N&#xff0c;返回斐波那契数列的第N项。 补充问题 1&#xff1a;给定整数 N&#xff0c;代表台阶数&#xff0c;一次可以跨 2个或者 1个台阶&#xff0c;返回有多少种走法。 【举例】N3&#xff0c;可以三次都跨1个台…

一文搞懂 Elasticsearch 之 Mapping

这篇文章主要介绍 Mapping、Dynamic Mapping 以及 ElasticSearch 是如何自动判断字段的类型&#xff0c;同时介绍 Mapping 的相关参数设置。 首先来看下什么是 Mapping&#xff1a; 1 什么是 Mapping&#xff1f; 在一篇文章带你搞定 ElasticSearch 术语中&#xff0c;我们讲…

DevicData-D-XXXXXXXX勒索病毒来袭:如何面对DevicData-D-XXXXXXXX勒索病毒的威胁

尊敬的读者&#xff1a; .DevicData-D-XXXXXXXX勒索病毒&#xff0c;犹如数字世界的黑暗幽灵&#xff0c;通过其复杂的加密算法&#xff0c;将用户数据变为数字谜团&#xff0c;要求赎金以唤回失去的信息。在这个数字时代&#xff0c;了解其特质和对抗方法至关重要。面对复杂的…