ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android权限申请

2021-05-01 17:32:23  阅读:360  来源: 互联网

标签:请求 申请 用户 注解 Android 权限 方法 permissions


一、基本介绍

1、正常权限(安装时权限):

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

例如,设置时区的权限就是正常权限。如果应用声明其需要正常权限,系统会自动向应用授予该权限。

2、危险权限(运行时权限):

会授予应用访问用户机密数据的权限。如果您列出了危险权限,则用户必须明确批准您的应用使用这些权限。

3、注意:

  1. 在 Android 5.1(API 22)或更低版本,并且应用的 targetSdkVersion 是 22 或更低版本,则系统会在安装时要求用户授予权限。(沿用之前的权限系统),也就是在程序安装的时候程序会将所有需要的权限全部列出来,其设计思路非常简单,就是用户如果认可你所申请的权限,那么就会安装你的程序,如果不认可你所申请的权限,则会拒绝安装。
  2. 从Android6.0版本开始才开始加入运行时权限,也就是说用户不需要在安装软件的时候一次性授权所有的权限,而是可以在软件的使用过程中再对某一项权限进行申请使用,这就是运行时权限。
  3. 在请求权限时,系统只告诉用户应用需要的权限组,而不告知具体权限。(如上图)

二、运行时权限(使用原生API)

1、步骤

  1. 首先要在清单文件中申请所需要的权限。

  2. 将硬件声明为可选(uses-feature)以及要确定硬件可用性


3. 按API级别申明权限

当目标sdk大于等于29的时候配置android.permission.WRITE_EXTERNAL_STORAGE会出现下面的警报:

WRITE_EXTERNAL_STORAGE no longer provides write access when targeting Android 10+

这时候需要设置根据Api级别申明权限android:maxSdkVersion,该属性表示设备搭载的系统版本高于 maxSdkVersion 时不需要特定权限。

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28"
        tools:ignore="ScopedStorage"/>
  1. 请求应用权限,其逻辑应该如下图所示

  2. 首先检查是否已经授予了某个权限,使用 ContextCompat.checkSelfPermission()此方法会返回 PERMISSION_GRANTEDPERMISSION_DENIED。如果 ContextCompat.checkSelfPermission() 方法返回 PERMISSION_DENIED,请调用 shouldShowRequestPermissionRationale()。如果此方法返回 true,请向用户显示指导界面,在此界面中说明用户希望启用的功能为何需要特定权限。(返回true说明应用之前请求过此权限但用户拒绝了请求,此方法将返回 true),之后再调用requestPermissions函数进行权限的请求,这个函数会引起onRequestPermissionsResult的回调。

        private void callPhone(){
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
                    != PackageManager.PERMISSION_GRANTED) {
                // 应用没有授予拨打电话权限,请求权限
                requestPhoneCallPermission();
            } else {
                // 应用被授予拨打电话权限 PackageManager.PERMISSION_GRANTED
                makeCall();
            }
        }
    
    private void requestPhoneCallPermission() {
            // 如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)){
                // 向用户详细解释申请该权限的原因
                new AlertDialog.Builder(this)
                        .setCancelable(false)
                        .setMessage("拨打电话需要使用电话权限,如果不授予权限会导致该功能无法正常使用")
                        .setPositiveButton("好的", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions(
                                        MainActivity.this,
                                        new String[]{Manifest.permission.CALL_PHONE},
                                        REQUEST_CALLPHONE//注意这个REQUEST_CALLPHONE会传给回调函数的requestCode
                                );
                            }
                        })
                        .setNegativeButton("拒绝", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        })
                        .show();
            } else {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALLPHONE);
            }
        }
    

    下面是回调函数:

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if (requestCode == REQUEST_CALLPHONE) {
                if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // 授予权限,拨打电话
                    makeCall();
                } else {
                    Toast.makeText(this, "请求权限被拒绝", Toast.LENGTH_SHORT).show();
                }
            } else {
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    

2、结果展示

当需要打电话的时候第一次请求:

当点击禁止之后:
当再一次点击打电话按钮时:
点击好的(又会看见请求权限的弹窗)
点击始终允许后,直接把电话打了过去

三、运行时权限(使用PermissionsDispatcher)

该工具直接使用注解来自动帮我们生成权限请求代码,使用时需要在项目中添加如下两个注解:

    implementation "com.github.permissions-dispatcher:permissionsdispatcher:4.8.0"
    annotationProcessor "com.github.permissions-dispatcher:permissionsdispatcher-processor:4.8.0"
注解 是否必须 作用
@RuntimePermissions 这是必须使用的注解,标记Activity/Fragment,则注解解释器会生成对应类的代码
@NeedsPermission 标记需要请求使用权限的方法,也就是说你获取了相应的权限之后就会执行这个方法,可以在括号里面加一个权限或者多个权限。
@OnShowRationale 对应之前的shouldShowRequestPermissionRationale(),当应用之前请求过此权限但用户拒绝了请求,再次请求时调用,告知用户为什么必须要授权这个权限,注解括号里面有参数,传入想要申请的权限,而且这个方法还要传入一个PermissionRequest对象,这个对象有两种方法:proceed()让权限请求继续,cancel()让请求中断。也就是说,这个方法会拦截你发出的请求,这个方法用于告诉用户你接下来申请的权限是干嘛的,说服用户给你权限。
@OnPermissionDenied 当请求权限遭拒绝时调用,可以告知用户已经拒绝该权限
@OnNeverAskAgain 当用户勾选不再提示,并拒绝权限时,再次请求时调用(如上图中禁止之后不再询问按钮)也就是说,我们可以在这个方法做申请权限失败并选择不再询问之后的处理。例如,可以告诉作者想开启权限的就从手机设置里面开启。

注意:上面这些注解的方法都不能是private,原因看下面
使用PermissionsDispatcher除了要实现注解之外,还要重写Activity的onRequestPermissionsResult()方法,在里面让一个PermissionsDispatcher执行回调。这个PermissionsDispatcher是什么来的呢?

原来只要我们实现了@RuntimePermissions和@NeedsPermission这两个必须的注解之后,再build一次project之后,编译器就会在在app\build\intermediates\classes\debug目录下与被注解的Activity同一个包下生成一个辅助类,名称为 “被注解的Activity的名称+PermissionsDispatcher” 的辅助类,用来调用被注解的Activity的方法(就是因为这个所以被注解的方法不能private,private方法的作用域不在其他的类)。所以,第一次用的话,要注解好之后,build一次,下面的方法里面的PermissionsDispatcherActivityPermissionsDispatcher才不会令AS报红。

 @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionsDispatcherActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
    }

注意代码中的onclick方法PermissionsDispatcherActivityPermissionsDispatchertakePhotoWithPermissionCheck方法在第一次编译完成之后会自动生成。

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               PermissionsDispatcherActivityPermissionsDispatcher.takePhotoWithPermissionCheck(PermissionsDispatcherActivity.this);
            }
        });

上面的具体代码链接:
https://github.com/Haoocker/Android_Learn/tree/master/RuntimePermissionDemo

参考阅读

  1. https://developer.android.com/guide/topics/permissions/overview?hl=zh-cn
  2. https://www.jianshu.com/p/d6b3e16cc1d9
  3. https://github.com/permissions-dispatcher/PermissionsDispatcher
  4. https://blog.csdn.net/s13383754499/article/details/79034758

标签:请求,申请,用户,注解,Android,权限,方法,permissions
来源: https://www.cnblogs.com/haoocker/p/14724449.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有