简单介绍

关于运行时权限的说法,早在Google发布android 6.0的时候,大家也听得蛮多的。从用户的角度来讲,用户是受益方,更好的保护用户的意思,而对于开发者来说,无疑增加了工作量。

对于6.0以下的权限在安装时,会根据权限声明产生一个权限列表,用户只有同意才能完成app的安装。而在6.0以后,不需要先对权限授权就可以安装app,对于权限的授权我们可以选择禁止。

在新的权限机制中,Google将权限分为两类:

Normal Permissions(普通权限):不涉及用户隐私,不需要用户进行授权,比如访问网络等;

Dangerous Permission(危险权限):涉及到用户隐私,需要用户进行授权,比如相机访问、读取SD卡等。

PS:运行时权限只适合APP运行在Android 6.x以上的机器,对于危险权限Google官方也对其进行了分组,只要一组中的某一权限被授权,同组的权限也同样会被授权。

操作步骤

简单的介绍了关于运行时权限的使用方法,操作步骤如下

  1. 在Androidmanifest.xml文件声明相关权限

  2. 通过ContextCompat.checkSelfPermission方法检查某项权限被授予情况

  3. 申请授权

  4. 权限回调处理

封装调用

权限的申请我们一般的做法都在Activity被创建的时候,才开始申请危险权限。而每次都得重复上述的操作,想想都觉得烦。为此,笔者将运行时权限的使用进行了进一步的归纳总结。将权限的检查统一封装在基类中,子类继承并实现抽象方法,传入权限数组等即可。

1)通过抽象方法getNeedPermissions( )获取需要进行检测的权限数组,检查相关权限是否授权,如果未授权则开始申请权限

 1 /**
 2      * 检查所有权限,无权限则开始申请相关权限
 3      */
 4     protected void checkAllNeedPermissions() {
 5         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
 6         List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
 7         if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
 8             ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(
 9                     new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);
10         }
11     }

2)权限授权情况回调处理,这里授权失败默认弹框是否前往设置页面授权

 

 1 /**
 2      * 权限授权结果回调
 3      *
 4      * @param requestCode
 5      * @param permissions
 6      * @param paramArrayOfInt
 7      */
 8     @Override
 9     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
10                                            @NonNull int[] paramArrayOfInt) {
11         if (requestCode == REQUEST_CODE_PERMISSON) {
12             if (!verifyPermissions(paramArrayOfInt)) {
13                 permissionGrantedFail();
14                 showTipsDialog();
15                 isNeedCheckPermission = false;
16             } else permissionGrantedSuccess();
17         }
18     }

 

PS:其中permissionGrantedSuccess()和permissionGrantedSuccess()为抽象方法,由子类实现。

 

3)简单调用,子类继承该基类,实现以下抽象方法即可

 1 @Override
 2     public String[] getNeedPermissions() {
 3         return new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
 4     }
 5 
 6     @Override
 7     protected void permissionGrantedSuccess() {
 8 
 9     }
10 
11     @Override
12     protected void permissionGrantedFail() {
13     }

有没有觉得酱紫操作清晰了很多,也方便了不少。依然如此,就赶紧mark吧。

封装类的完整代码如下:

  1 /**
  2  * Created by chenyk on 2016/9/28.
  3  * 检查相关权限基类,适用于android 6.0 运行时权限
  4  * 使用方法:需要运行时权限的activity继承此类
  5  */
  6 public abstract class BaseCheckPermissionActivity extends NeedBackActivity
  7         implements OnRequestPermissionsResultCallback {
  8     private static final int REQUEST_CODE_PERMISSON = 2020; //权限请求码
  9 
 10     private boolean isNeedCheckPermission = true; //判断是否需要检测,防止无限弹框申请权限
 11 
 12     @Override
 13     protected void onResume() {
 14         super.onResume();
 15         if (isNeedCheckPermission) {
 16             checkAllNeedPermissions();
 17         }
 18     }
 19 
 20     /**
 21      * 检查所有权限,无权限则开始申请相关权限
 22      */
 23     protected void checkAllNeedPermissions() {
 24         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
 25         List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
 26         if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
 27             ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(
 28                     new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);
 29         }
 30     }
 31 
 32     /**
 33      * 获取权限集中需要申请权限的列表
 34      *
 35      * @param permissions
 36      * @return
 37      */
 38     private List<String> getDeniedPermissions(String[] permissions) {
 39         List<String> needRequestPermissonList = new ArrayList<>();
 40         for (String permission : permissions) {
 41             if (ContextCompat.checkSelfPermission(this, permission) !=
 42                     PackageManager.PERMISSION_GRANTED ||
 43                     ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
 44                 needRequestPermissonList.add(permission);
 45             }
 46         }
 47         return needRequestPermissonList;
 48     }
 49 
 50     /**
 51      * 所有权限是否都已授权
 52      *
 53      * @return
 54      */
 55     protected boolean isGrantedAllPermission() {
 56         List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
 57         return needRequestPermissonList.size() == 0;
 58     }
 59 
 60     /**
 61      * 权限授权结果回调
 62      *
 63      * @param requestCode
 64      * @param permissions
 65      * @param paramArrayOfInt
 66      */
 67     @Override
 68     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
 69                                            @NonNull int[] paramArrayOfInt) {
 70         if (requestCode == REQUEST_CODE_PERMISSON) {
 71             if (!verifyPermissions(paramArrayOfInt)) {
 72                 permissionGrantedFail();
 73                 showTipsDialog();
 74                 isNeedCheckPermission = false;
 75             } else permissionGrantedSuccess();
 76         }
 77     }
 78 
 79     /**
 80      * 检测所有的权限是否都已授权
 81      *
 82      * @param grantResults
 83      * @return
 84      */
 85     private boolean verifyPermissions(int[] grantResults) {
 86         for (int grantResult : grantResults) {
 87             if (grantResult != PackageManager.PERMISSION_GRANTED) {
 88                 return false;
 89             }
 90         }
 91         return true;
 92     }
 93 
 94     /**
 95      * 显示提示对话框
 96      */
 97     protected void showTipsDialog() {
 98         new AlertDialog.Builder(this).setTitle("提示信息").setMessage("当前应用缺少" + getDialogTipsPart()
 99                 + "权限,该功能暂时无法使用。如若需要,请单击【确定】按钮前往设置中心进行权限授权。")
100                 .setNegativeButton("取消", new DialogInterface.OnClickListener() {
101                     @Override
102                     public void onClick(DialogInterface dialog, int which) {
103                         finish();
104                     }
105                 })
106                 .setPositiveButton("确定", new DialogInterface.OnClickListener() {
107                     @Override
108                     public void onClick(DialogInterface dialog, int which) {
109                         startAppSettings();
110                     }
111                 }).show();
112     }
113 
114 
115     /**
116      * 启动当前应用设置页面
117      */
118     private void startAppSettings() {
119         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
120         intent.setData(Uri.parse("package:" + getPackageName()));
121         startActivity(intent);
122     }
123 
124     /**
125      * 获取弹框提示部分内容
126      *
127      * @return
128      */
129     protected String getDialogTipsPart() {
130         return "必要";
131     }
132 
133     /**
134      * 获取需要进行检测的权限数组
135      */
136     protected abstract String[] getNeedPermissions();
137 
138     /**
139      * 权限授权成功
140      */
141     protected abstract void permissionGrantedSuccess();
142 
143     /**
144      * 权限授权失败
145      */
146     protected abstract void permissionGrantedFail();