Android 6.0 运行时权限处理解析

本文深入解析Android6.0系统权限处理变化,包括普通权限与危险权限的分类,以及如何在代码中实现运行时权限申请和回调处理。

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

1.概述

  大家有没有遇到过这种情况,开发app的时候发现自己手机选择照片是正常的,测试的时候他那边的一台手机怎么搞都不行,然后查看版本之后才发现是6.0的手机。

  在Google发出Android 6.0版本以后,对权限这边做了很大的变动,其中之一就是权限处理。那么在6.0及以上版本我们的危险权限都需要在运行的时候去申请,之前都是在清单文件中配置即可,现在就不行了需要用代码动态申请。不然程序在执行时没有相应的权限就会无响应甚至导致APP崩溃。


2.权限的分类及区别

   2.1 Google对于Android 6.0 系统权限分为两类:

    1.Normal Permission(普通权限): 这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如访问网络,访问WIFI,访问蓝牙等权限;
    看一些普通权限:

    android.permission.ACCESS LOCATIONEXTRA_COMMANDS 
    android.permission.ACCESS NETWORKSTATE 
    android.permission.ACCESS NOTIFICATIONPOLICY 
    android.permission.ACCESS WIFISTATE 
    android.permission.ACCESS WIMAXSTATE 
    android.permission.BLUETOOTH 
    android.permission.BLUETOOTH_ADMIN 
    android.permission.BROADCAST_STICKY 
    android.permission.CHANGE NETWORKSTATE 
    android.permission.CHANGE WIFIMULTICAST_STATE 
    android.permission.CHANGE WIFISTATE 
    android.permission.CHANGE WIMAXSTATE 
    android.permission.DISABLE_KEYGUARD 
    android.permission.EXPAND STATUSBAR 
    android.permission.FLASHLIGHT 
    android.permission.GET_ACCOUNTS 
    android.permission.GET PACKAGESIZE 
    android.permission.INTERNET 
    android.permission.KILL BACKGROUNDPROCESSES 
    android.permission.MODIFY AUDIOSETTINGS 
    android.permission.NFC 
    android.permission.READ SYNCSETTINGS 
    android.permission.READ SYNCSTATS 
    android.permission.RECEIVE BOOTCOMPLETED 
    android.permission.REORDER_TASKS 
    android.permission.REQUEST INSTALLPACKAGES 
    android.permission.SET TIMEZONE 
    android.permission.SET_WALLPAPER 
    android.permission.SET WALLPAPERHINTS 
    android.permission.SUBSCRIBED FEEDSREAD 
    android.permission.TRANSMIT_IR 
    android.permission.USE_FINGERPRINT 
    android.permission.VIBRATE 
    android.permission.WAKE_LOCK 
    android.permission.WRITE SYNCSETTINGS 

    2.Dangerous Permission(危险权限): 这类权限一般是涉及到用户的安全和隐私问题,需要用户进行授权,比如读取SD卡,访问相册,拨打电话等权限。
    看几组危险权限:

      SMS(短信)
            SEND_SMS
            RECEIVE_SMS
            READ_SMS
            RECEIVE_WAP_PUSH
            RECEIVE_MMS
      STORAGE(存储卡)
            READ_EXTERNAL_STORAGE
            WRITE_EXTERNAL_STORAGE
      CONTACTS(联系人)
            READ_CONTACTS
            WRITE_CONTACTS
            GET_ACCOUNTS
      PHONE(手机)
            READ_PHONE_STATE
            READ_CALL_LOG
            WRITE_CALL_LOG
            CALL_PHONE
            ADD_VOICEMAIL
            USE_SIP
            PROCESS_OUTGOING_CALLS
      CALENDAR(日历)
            READ_CALENDAR
            WRITE_CALENDAR
      CAMERA(相机)
            CAMERA
      LOCATION(位置)
            ACCESS_FINE_LOCATION
            ACCESS_COARSE_LOCATION
      SENSORS(传感器)
            BODY_SENSORS
      MICROPHONE(麦克风)
            RECORD_AUDIO
   2.2 普通权限和危险权限的区别:

      1.普通权限:单条权限,可以直接在Manifests文件中进行注册从而获取权限,在程序初次安装启动时直接获取用户权限
      2.危险权限:成组授予,当授予一组中任何一个权限时,该组内其他的权限也会自动被授予。不仅需要在Manifests文件中进行注册还要在代码中进行动态申请。


3.代码变化过程

   3.1 Android6.0之前直接这样写(已电话拨打为例):
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:" + mPhone);
        intent.setData(data);
        startActivity(intent);
   3.2.Android6.0以后就不行啦,我们需要去检测该权限有没有被用户授予过,如果没有则需要申请打电话权限,如果有授予过可以直接拨打电话。

      ContextCompat.checkSelfPermission:检测权限
      ActivityCompat.requestPermissions:申请权限

       /**
         * 1.ContextCompat.checkSelfPermission 检查权限
         * 2.方法返回值有两种:
         *      PackageManager.PERMISSION_GRANTED   有该权限
         *      PackageManager.PERMISSION_DENIED    没有该权限
         */
        if(ContextCompat.checkSelfPermission(this,Manifest.permission.CALL_PHONE)
                != PackageManager.PERMISSION_GRANTED){
            /**
             * ActivityCompat.requestPermissions 申请权限
             *  参数1:Context , 
             *  参数2:用户需要申请的权限字符串数组,
             *  参数3:是请求码 主要用来处理用户选择后的返回结果 onRequestPermissionsResult返回会掉方法
             */
            ActivityCompat.requestPermissions(this,new String[]{"Manifest.permission.CALL_PHONE"},CALL_PHONE_REQUEST_CODE);
        }else {
            // 有该权限,直接打电话
            Intent intent = new Intent(Intent.ACTION_CALL);
            Uri data = Uri.parse("tel:" + mPhone);
            intent.setData(data);
            startActivity(intent);
        }
   3.3. 回调处理:如果用户同意或是拒绝那么会回调onRequestPermissionsResult(),注意:不是onActivityResult()
      @Override
      public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
          if(requestCode == CALL_PHONE_REQUEST_CODE){
            if (grantResults !=null&&grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 用户授予了权限
                Intent intent = new Intent(Intent.ACTION_CALL);
                Uri data = Uri.parse("tel:" + mPhone);
                intent.setData(data);
                startActivity(intent);
            } else {
                //用户拒绝了权限
                  Toast.makeText(this,"权限被您拒绝了",Toast.LENGTH_SHORT).show();
              }
          }
      }

4.简单事例:

    public class TextActivity extends AppCompatActivity {
          // 打电话权限申请的请求码
          private static final int CALL_PHONE_REQUEST_CODE = 0x0011;

          @Override
          protected void onCreate(Bundle savedInstanceState) {
               super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_text);
          }
         
         /**
          * 检察权限
          */    
          public void phoneClick(View view) {
               if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
                != PackageManager.PERMISSION_GRANTED) {
               Toast.makeText(this, "申请权限", Toast.LENGTH_SHORT).show();
               ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQUEST_CODE);
              } else {
                callPhone();
              }
          }

          /**
           * 拨打电话
           **/
          private void callPhone() {
              Intent intent = new Intent(Intent.ACTION_CALL);
              Uri data = Uri.parse("tel:130****7927");
              intent.setData(data);
              startActivity(intent);
          }

          @Override
          public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
              super.onRequestPermissionsResult(requestCode, permissions, grantResults);
              if(requestCode == CALL_PHONE_REQUEST_CODE){
                  if (grantResults !=null&&grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                      // 授予权限
                      callPhone();
                  } else {
                      // 拒绝权限
                      Toast.makeText(this,"权限被您拒绝了",Toast.LENGTH_SHORT).show();
                  }
              }
          }
      }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值