本文目录

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


动态权限概述

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

完整代码

我们以申请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();

效果如下:

更多相关文章

  1. 事件处理机制之Gestures(手势)
  2. Android(安卓)—— 注解(Annotation)也被称为元数据(Metadata)
  3. Android权限申请的学习实践
  4. Android获取WIFI的BSSID遇到的坑(已解决)
  5. Android基础笔记(十一)- Service基础和注意事项以及Activity与Serv
  6. Android异步处理机制AsyncTask的理解
  7. Android(安卓)View源码解读:浅谈DecorView与ViewRootImpl
  8. Android(安卓)如何获取当前Activity实例对象?
  9. Android(安卓)AsyncTask 异步任务之源码解析

随机推荐

  1. Android(安卓)SDK开发包国内下载地址
  2. Android(安卓)UI更新
  3. AndroidManifest 中original-package标签
  4. Android动态壁纸的制作教程
  5. Android数字签名
  6. Android面试题集锦之Service
  7. 如何画Q版角色?绘画q版动漫人物
  8. Ubuntu系统-FFmpeg安装及环境配置
  9. iOS UITextView 实现类似微博的话题、提
  10. php生成WAP页面