Android 动态权限最全解析

本文目录

  • 动态权限概述
  • 动态权限分类
  • 动态权限申请方法
    • 方法1:官方API提供的方法
      • 步骤1:检查是否有权限
      • 步骤2:申请权限
      • 步骤3:回调函数的处理
      • 完整代码
    • 方法2:RxPermission
      • 引入依赖
      • 声明权限
      • 申请单个权限
      • 申请多个权限
    • 方法3:AndPermission
      • 引入依赖
      • 申请单个或多个权限

Android 动态权限最全解析_第1张图片
Android 动态权限最全解析_第2张图片

动态权限概述

Android6.0 开始,Google调整了应用的权限申请方案。调整之后将权限分级,分成了普通权限危险权限,普通权限的授权方式跟之前一样,只需要在Manifest文件中申明即可,危险权限不仅需要在Manifest文件中声明,还需要在程序中调用官方提供的Api主动申请。

动态权限分类

Android6.0 以后,一共将动态权限分成了9组,每组只要有一个权限申请成功了,就默认整组权限都可以使用了。这九组权限分别如下:

权限组名称 权限组 权限组权限成员
读写联系人 group:android.permission-group.CONTACTS permission:android.permission.WRITE_CONTACTS permission:android.permission.GET_ACCOUNTS permission:android.permission.READ_CONTACTS
电话 group:android.permission-group.PHONE permission:android.permission.READ_CALL_LOG permission:android.permission.READ_PHONE_STATE permission:android.permission.CALL_PHONE permission:android.permission.WRITE_CALL_LOG permission:android.permission.USE_SIP permission:android.permission.PROCESS_OUTGOING_CALLS permission:com.android.voicemail.permission.ADD_VOICEMAIL
日历信息 group:android.permission-group.CALENDAR permission:android.permission.READ_CALENDAR permission:android.permission.WRITE_CALENDAR
相机 group:android.permission-group.CAMERA permission:android.permission.CAMERA
传感器 group:android.permission-group.SENSORS permission:android.permission.BODY_SENSORS
地理位置 group:android.permission-group.LOCATION permission:android.permission.ACCESS_FINE_LOCATION permission:android.permission.ACCESS_COARSE_LOCATION
存储卡 group:android.permission-group.STORAGE permission:android.permission.READ_EXTERNAL_STORAGE permission:android.permission.WRITE_EXTERNAL_STORAGE
多媒体 group:android.permission-group.MICROPHONE permission:android.permission.RECORD_AUDIO
SMS group:android.permission-group.SMS permission:android.permission.READ_SMS permission:android.permission.RECEIVE_WAP_PUSH permission:android.permission.RECEIVE_MMS permission:android.permission.RECEIVE_SMS permission:android.permission.SEND_SMS permission:android.permission.READ_CELL_BROADCASTS

动态权限申请方法

方法1:官方API提供的方法

步骤1:检查是否有权限

由于低于API 23 是不需要使用动态权限申请的,我们需要先判断一下系统版本,代码如下是Android 6.0以上的系统还是Android 6.0以下的系统。用ContextCompat类中的checkSelfPermission方法进行是否有权限判断。

public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) {
    if (permission == null) {
        throw new IllegalArgumentException("permission is null");
    }

    return context.checkPermission(permission, android.os.Process.myPid(), Process.myUid());
}

具体使用方法如下:

if (Build.VERSION.SDK_INT >= 23) {
  if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
              != PackageManager.PERMISSION_GRANTED) {
              //无该权限,需要申请
      }
} else { //低于23 不需要处理

}

步骤2:申请权限

在步骤的的checkSelfPermission方法中如果判断没有权限,就需要用到ActivityCompat类中的requestPermissions方法进行动态权限申请,该方法需要传一个需要申请权限名称的权限permissions数组。

public static void requestPermissions(final @NonNull Activity activity,
         final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode) {
}

申请方法如下:先定一个需要申请权限的权限数组PERMISSIONS_STORAGE

private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {"android.permission.READ_EXTERNAL_STORAGE",
        "android.permission.WRITE_EXTERNAL_STORAGE"};
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);

步骤3:回调函数的处理

由于权限申请是异步的,用户完成了以后,需要回调函数处理,
Activity中提供了一个回调处理方法onRequestPermissionsResult,只需要重写该方法即可
case 中的参数REQUEST_EXTERNAL_STORAGE 即步骤2申请权限中定一个的参数

 @Override
 public void onRequestPermissionsResult(int requestCode,
                                        String permissions[], int[] grantResults) {
     switch (requestCode) {
         case REQUEST_EXTERNAL_STORAGE: {
             if (grantResults.length > 0
                     && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                 Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
             } else {
                 Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show();
             }
         }

     }
 }

完整代码

Android 动态权限最全解析_第3张图片

我们以申请SD卡读写权限为例,完整代码如下:

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {"android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (Build.VERSION.SDK_INT >= 23) {
            checkPermission();
        }
    }


    private void checkPermission() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission
                    .WRITE_EXTERNAL_STORAGE)) {
                Toast.makeText(this, "请开通相关权限,否则无法正常使用本应用!", Toast.LENGTH_SHORT).show();
            }
            //申请权限
            ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);

        } else {
            Toast.makeText(this, "已授权成功!", Toast.LENGTH_SHORT).show();
            dothings();
        }
    }


    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_EXTERNAL_STORAGE: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    dothings();
                    Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show();
                }
            }

        }
    }

    public void dothings() {

    }
}

AndroidManifest.xml声明权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

方法2:RxPermission

RxPermission 可以帮助开发者简化获取权限的相关处理操作,而且内部也自动帮我们判断了版本是否需要申请权限。同时结合RxJava可以方便的回调各种结果。
官网:https://github.com/tbruyelle/RxPermissions

引入依赖

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
 
dependencies {
    implementation 'com.github.tbruyelle:rxpermissions:0.10.2'
     implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
}

由于rxpermissions需要用到rxjava,所有rxjava的包也一起引入。

声明权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.CAMERA"/>

申请单个权限

RxPermissions permissions = new RxPermissions(this);
permissions.request(Manifest.permission.CAMERA)
       .subscribe(new Consumer<Boolean>() {
           @Override
           public void accept(Boolean aBoolean)  {
               if (aBoolean ) {
                   Toast.makeText(MainActivity.this, "授权成功!", Toast.LENGTH_SHORT).show();
               }else {
                   Toast.makeText(MainActivity.this, "授权失败!", Toast.LENGTH_SHORT).show();
               }
           }
       });

申请多个权限

RxPermissions permissions = new RxPermissions(this);  
permissions.request(Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE)
  .subscribe(new Consumer<Boolean>() {
            @Override
            public void accept(Boolean aBoolean)  {
                if (aBoolean ) {
                    Toast.makeText(MainActivity.this, "授权成功!", Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(MainActivity.this, "授权失败!", Toast.LENGTH_SHORT).show();
                }
            }
        });

方法3:AndPermission

AndPermission跟前面的RxPermission使用方法类似
官网:https://github.com/yanzhenjie/AndPermission

引入依赖

implementation 'com.yanzhenjie:permission:2.0.3'

申请单个或多个权限

 AndPermission.with(this)
            .runtime()
            .permission(Permission.WRITE_EXTERNAL_STORAGE,Permission.CAMERA)
            .onGranted(permissions -> {
                Toast.makeText(MainActivity.this, "授权成功!", Toast.LENGTH_SHORT).show();
            })
            .onDenied(permissions -> {
                Toast.makeText(MainActivity.this, "授权失败!", Toast.LENGTH_SHORT).show();
            })
            .start();

效果如下:Android 动态权限最全解析_第4张图片

你可能感兴趣的:(Android,#,Android,开源框架,#,Android基础)