Android M及以上系统授权申请

本文详细介绍了Android 6.0及以上版本中运行时权限的申请流程,包括不同权限组及其权限名称,以及如何通过代码实现权限的申请和授权状态检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

序言

在Android5.1及一下系统中,系统会自动为程序赋予权限,只要你在清单文件中标明;  

而6.0及以上系统中,若你的程序targetSdkVersion为23或以上,有些 运行时权限 还需要在运行时进行授权。

哪些权限需要申请?

权限组权限
CALENDARREAD_CALENDAR
WRITE_CALENDAR
CAMERACAMERA
CONTACTSREAD_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATIONACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONERECORD_AUDIO
PHONEREAD_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORSBODY_SENSORS
SMSSEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGEREAD_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

(详见官方说明,标注 Protection level: dangerous 需要运行时申请)

一般来说,一个组只要有一个权限被赋予,其它权限也就拥有了。所以,同组权限不需要重复申请。

申请代码

这里以 PROCESS_OUTGOING_CALLS 权限为例。

向用户申请权限

代码

private void requestPermission() {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
        if(ContextCompat.checkSelfPermission(this,android.Manifest.permission.PROCESS_OUTGOING_CALLS)!=PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.PROCESS_OUTGOING_CALLS}, 1);
        }
    }
}

分析

首先要判断系统版本,M一下就不用申请了。。。
判断权限是否已拥有,使用的是 ContextCompat.checkSelfPermission(Context context, String permission)
权限名为 android.Manifest.permission.PROCESS_OUTGOING_CALLS

(static int) checkSelfPermission (Context context, String permission)
Determine whether you have been granted a particular permission.
(返回是否拥有该权限)

Parameters :
context Context(上下文)
permission String: The name of the permission being checked.(要检查的权限)
Returns :
int PERMISSION_GRANTED if you have the permission(拥有该权限), or PERMISSION_DENIED if not(没有改权限).

有多个权限需要申请,可以直接使用&&连接判断。
申请用 ActivityCompat.requestPermissions(Activity activity, String[] permissions, int requestCode)

申请:

(static void) requestPermissions(Activity activity, String[] permissions, int requestCode)
Requests permissions to be granted to this application. (为本程序申请权限)

Parameters:
activity Activity : The target activity.(申请的Activity,可否理解成上下文?)
permissions String[] : The requested permissions.(需要申请的权限名, android.Manifest.permission.* 那个,可有多个)
requestCode int: Application specific request code to match with a result reported to onRequestPermissionsResult(int, String[], int[]).(请求码,多次请求处理请求结果时区分哪次请求的)

后面跟着说明一大串(原文),大概就这么几个意思:
1. 申请的权限必须是清单文件里有的,危险等级为 #PROTECTION_DANGEROUS
2. 没有申请,使用该权限就会被阻止。申请了,无论用户同意与否,都会接收到一个callback,可以实现 ActivityCompat.OnRequestPermissionsResultCallback 接口的 onRequestPermissionsResult(int, String[], int[]) 方法处理它。
3. 申请了不一定会被用户授予(意味着你还是得判断权限不被授予的情况,以免FC)
4. 申请时会弹出一个Activity,当前Activity会被 pausedresumed 。此外,一些权限需要重启程序,系统会在系统发送授权之前重新创建程序堆栈(英语水平有限,个人理解如此,有错请指正)。
5. 使用 checkSelfPermission(android.content.Context, String). 检查授权
6. 若程序已经拥有该权限,系统会询问用户是否仍然保持该应用拥有此权限(也就是说已经有该权限了,系统也得问一问咯)

向用户提出申请之后,还是有必要检查是否已经通过了的。使用 onRequestPermissionsResult 。Android Studio创建的Activity默认继承 AppCompatActivity ,而那些手动创建Activity直接继承 Activity 的可能需要实现 ActivityCompat.OnRequestPermissionsResultCallback 接口?我没试过

检查用户是否同意授权

重写 onRequestPermissionsResult 方法。

代码

在这里,用户如果眉头同意授予权限的话,会弹出一个AlertDialog提示用户,说明需要权限的原因。若用户还不同意,那就不再提示了,到需要该权限的地方再做判断,或提示重新授权,或提示该功能无法使用

boolean isFirst = true;   //这个是成员变量,用来判断是不是第一次申请权限

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //检查是否完成授权
        if(grantResults.length > 0 //此处为申请的权限个数-1,下面是判断申请的第n个是否通过
                && grantResults[0] == PackageManager.PERMISSION_GRANTED){
            Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
        } else {
            //失败--第一次,提示重新授权
            if(isFirst){
                isFirst = false;
                //构建提示授权的Dialog
                final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("授权申请");
                builder.setMessage("说明"); //为什么要这些权限??
                builder.setPositiveButton("授权", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        requestPermission();
                        builder.create().dismiss();
                    }
                });
                builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        builder.create().cancel(); //取消和返回一样,归到cancel内处理
                    }
                });
                builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialogInterface) {
                        //失败--第二次,提示失败
                        Toast.makeText(FindActivity.this, "提示:没有足够权限,XX功能将无法使用", Toast.LENGTH_SHORT).show();
                    }
                });
                builder.show();
            } else {
                //失败--第二次,提示失败
                Toast.makeText(this, "提示:没有足够权限,XX功能将无法使用", Toast.LENGTH_SHORT).show();
            }
        }
    }

分析

(abstract void) onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
Callback for the result from requesting permissions.

  1. 申请授权的返回结果。包括了在 requestPermissions(android.app.Activity, String[], int). 方法里面申请的所有权限
  2. 用户选取消,会收到一个空的权限和空的结果数组(这就是为什么要判断 grantResults.length 而不是直接判断 grantResults 数组内容)

Parameters
requestCode int: The request code passed in requestPermissions(android.app.Activity, String[], int)(申请码,requestPermissions 设置的)
permissions String[]: The requested permissions. Never null.(程序申请的权限,永不为空)
grantResults int: The grant results for the corresponding permissions which is either PERMISSION_GRANTED(成功) or PERMISSION_DENIED(失败). Never null.(与permissions一一对应,每个权限的授权结果。)

恩。。。以我这个英语四级没过的水平,勉强也就能理解到此了,出错难免,欢迎指正。。。百度机翻就是个坑,还不如我自己看。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值