随着Android 6.0发布以及普及,
大家都知道,
对于6.0以下的权限及在安装的时候,根据权限声明产生一个权限列表,用户只有在同意之后才能完成app的安装,造成了我们想要使用某个app,就要默默忍受其一些不必要的权限(比如是个app都要访问通讯录、短信等)。而在6.0以后,我们可以直接安装,当app需要我们授予不恰当的权限的时候,我们可以予以拒绝(比如:单机的象棋对战,请求访问任何权限,我都是不同意的)。当然你也可以在设置界面对每个app的权限进行查看,以及对单个权限进行授权或者解除授权。
新的权限机制更好的保护了用户的隐私。但是对于我们开发者来说可就带来不便了,在Android 6.0 以上的手机上并且 targetSdkVersion>=23,当用户执行某个隐私权限操作(例如打电话)而你的程序中如果没有获得某项权限,用户直接使用相关功能,则会导致自己程序crash。为了解决这方面的问题,我们每次请求某一个权限要写好多代码解决这个问题,非常的麻烦。
下面是我写的一个轻量级的权限判断,支持请求单个和多个权限,并且根据权限请求情况做对应操作,可以减少很多重复的工作。废话不多说,直接上效果图
1、请求多个权限
1.1 请求打电话权限(调用手机系统默认界面)
1.2 请求拍照权限
2、请求单个权限
3、用户拒绝后再次请求权限时
3.1 拒绝权限后会进入权限管理授于权限时的界面
下面贴出代码
private final String tag = "MPermissions"; private int REQUEST_CODE_PERMISSION = 0x00099; /** * 请求权限 * * @param permissions 请求的权限 * @param requestCode 请求权限的请求码 */ public void requestPermission(String[] permissions, int requestCode) { this.REQUEST_CODE_PERMISSION = requestCode; if (checkPermissions(permissions)) { permissionSuccess(permissions,REQUEST_CODE_PERMISSION); } else { List<String> needPermissions = getDeniedPermissions(permissions); BaseFragment.this.requestPermissions(needPermissions.toArray(new String[needPermissions.size()]), REQUEST_CODE_PERMISSION); 注意这里因为是在fragment中,所以写成了 BaseFragment.this.requestPermissions。如果在activity应该是 ActivityCompat.requestPermissions 如果fragment中也写的是ActivityCompat.requestPermissions,那么第一次不会走回调,不要写错了 } } /** * 检测所有的权限是否都已授权 * * @param permissions * @return */ private boolean checkPermissions(String[] permissions) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } for (String permission : permissions) { if (ContextCompat.checkSelfPermission(mActivity, permission) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } /** * 获取权限集中需要申请权限的列表 * * @param permissions * @return */ private List<String> getDeniedPermissions(String[] permissions) { List<String> needRequestPermissionList = new ArrayList<>(); for (String permission : permissions) { if (ContextCompat.checkSelfPermission(mActivity, permission) != PackageManager.PERMISSION_GRANTED || ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permission)) { needRequestPermissionList.add(permission); } } return needRequestPermissionList; } /** * 系统请求权限回调 * * @param requestCode * @param permissions * @param grantResults */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CODE_PERMISSION) { if (verifyPermissions(grantResults)) { permissionSuccess(permissions,REQUEST_CODE_PERMISSION); } else { permissionFail(permissions,REQUEST_CODE_PERMISSION); showTipsDialog(); } } } /** * 确认所有的权限是否都已授权 * * @param grantResults * @return */ private boolean verifyPermissions(int[] grantResults) { for (int grantResult : grantResults) { if (grantResult != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } /** * 显示提示对话框 */ private void showTipsDialog() { new AlertDialog.Builder(mActivity) .setTitle("提示信息") .setMessage("当前应用缺少必要权限,该功能暂时无法使用。如若需要,请单击【确定】按钮前往设置中心进行权限授权。") .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startAppSettings(); } }).show(); } /** * 启动当前应用设置页面 */ private void startAppSettings() { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse("package:" + mActivity.getPackageName())); startActivity(intent); } /** * 获取权限成功 * * @param requestCode */ public void permissionSuccess(String []permissions,int requestCode) { Log.d(tag, "获取权限成功=" + requestCode); } /** * 权限获取失败 * @param requestCode */ public void permissionFail(String []permissions,int requestCode) { Log.d(tag, "获取权限失败=" + requestCode); }
关于如何使用
使用方法(多个权限为例)
Manifest.permission.CALL_PHONE:电话权限
Manifest.permission.CAMERA:拍照权限
0x0001:请求码(后面判断请求权限结果会用到)
requestPermission(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.CAMERA}, 0x0001);
请求权限结果回调(多个权限为例)
可根据请求码来区分
/** * 权限成功回调函数 * * @param requestCode */ @SuppressLint("MissingPermission") @Override public void permissionSuccess(String[] permissions, int requestCode) { switch (requestCode) { case 0x0001: for (String permission : permissions) { if (permission.equals(Manifest.permission.CAMERA)) {//获得拍照权限 ToastUtil.show("用户允许拍照权限"); } else if (permission.equals(Manifest.permission.CALL_PHONE)) {//获得打电话权限 ToastUtil.show("用户允许打电话权限"); } } ; break; } super.permissionSuccess(permissions, requestCode); } /** * 权限失败回调函数 * * @param requestCode */ @Override public void permissionFail(String[] permissions, int requestCode) { switch (requestCode) { case 0x0001: for (String permission : permissions) { if (permission.equals(Manifest.permission.CAMERA)) {//未获得拍照权限 ToastUtil.show("用户不允许拍照权限"); } else if (permission.equals(Manifest.permission.CALL_PHONE)) {//未获得打电话权限 ToastUtil.show("用户不允许打电话权限"); } } break; } super.permissionFail(permissions, requestCode); }
这里特别需要注意到的是在fragment和activity中这里的上下文对象是不一样的,如果fragment中使用ActivityCompat为对象,会出现第一次不走权限问题,切记、切记(如下图)
Activity中:
ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[needPermissions.size()]), REQUEST_CODE_PERMISSION);
Fragment中:
BaseFragment.this.requestPermissions(needPermissions.toArray(new String[needPermissions.size()]), REQUEST_CODE_PERMISSION);
好啦,到这里权限请求就完成了,内容不多,我就不贴出源码了,需要的可以底部留言!!!