Android 6.0 运行时权限处理解析

1.概述

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

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


2.权限分类及区别

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

普通权限和危险权限的区别:

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

3.代码变化过程

3.1.6.0之前是这样写(已电话拨打为例):

    Intent intent = new Intent(Intent.ACTION_CALL);
    Uri data = Uri.parse("tel:" + mPhone);
    intent.setData(data);
    startActivity(intent);

3.2.6.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();
              }
          }
      }
  }

你可能感兴趣的:(Android 6.0 运行时权限处理解析)