从android6.0开始,访问危险权限需要用户明确授予。关于6.0的权限讲解可以查看官网的介绍,本文主要记录具体的使用步骤。
1、首先需要在manifest.xml文件中列出所需权限,如下所示:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<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"/>
<uses-permission android:name="android.permission.INTERNET"/><!-- 访问网络是正常权限,只需要在manifest文件中声明即可-->
2、在Activity中,首先检查权限,使用
ContextCompat.checkSelfPermission(context,permission)
该方法用于判断是否已授权,返回值为
PackageManager.PERMISSION_GRANTED(同意)或PackageManager.PERMISSION_DENIED(拒绝),若权限未授予,则申请权限。
3、申请授权,使用ActivityCompat.requestPermissions方法申请权限,如下所示:第一个参数为Context,第二个参数为所需的权限数组,第三个参数是请求码,用于回调时使用。ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},PERMISSION_REQUEST_CODE);
权限检查与申请完整代码如下:
private void checkPermissions(){ String[] permissionArray=new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION};//所需要的危险权限数组 List<String> needRequestPermission=new ArrayList<>();//需要申请的权限列表 List<String> noGrantedPermission=new ArrayList<>();//已拒绝权限列表 for(String permission:permissionArray){ int checkPermission=ContextCompat.checkSelfPermission(this,permission);//检查权限,返回值为PackageManager.PERMISSION_GRANTED(同意)或PackageManager.PERMISSION_DENIED(拒绝) if(checkPermission!= PackageManager.PERMISSION_GRANTED){//若未同意 if(ActivityCompat.shouldShowRequestPermissionRationale(this,permission)){//shouldShowRequestPermissionRationale用于用户已经拒绝过,再次申请时需要向用户解释为什么需要这些权限 noGrantedPermission.add(permission);//将用户拒绝的权限加入拒绝列表中 }else { needRequestPermission.add(permission);//将需要申请的权限加入申请列表中 } } } if(needRequestPermission.size()>0){ ActivityCompat.requestPermissions(this,needRequestPermission.toArray(new String[needRequestPermission.size()]),PERMISSION_REQUEST_CODE); } if(noGrantedPermission.size()>0){ final List<String> permissions=noGrantedPermission; showRationaleDialog("应用所必需权限未打开,请打开权限", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(MainActivity.this,permissions.toArray(new String[permissions.size()]),PERMISSION_REQUEST_CODE); } }); } }
4、申请权限的回调
具体实现如下:@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if(requestCode==PERMISSION_REQUEST_CODE){ //TODO }else{ //TODO } }
自定义dialog,用于用户拒绝之后,弹框提醒用户打开权限:@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { // super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode==PERMISSION_REQUEST_CODE){ if(allPermissionGranted(grantResults)){ Toast.makeText(MainActivity.this,"授权成功!",Toast.LENGTH_SHORT).show(); }else{ showRationaleDialog("请打开应用所需权限", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent=new Intent();//打开应用管理界面,修改权限 intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse("package:"+getPackageName())); startActivity(intent); } }); } } } private boolean allPermissionGranted(int[] grantResults){ for(int i=0;i<grantResults.length;i++){ if(grantResults[i]!=PackageManager.PERMISSION_GRANTED){ return false; } } return true; }
private void showRationaleDialog(String message,DialogInterface.OnClickListener onClickListener){ new AlertDialog.Builder(MainActivity.this) .setMessage(message) .setPositiveButton("OK", onClickListener) .setNegativeButton("Cancel",null) .create() .show(); }
以上是权限申请的整个流程,需要注意的是,targetSDK>=23时是必须动态申请权限的,若targetSDK<23,则只需要在manifest.xml文件中配置即可,不过对于targetSDK<23,使用checkSelfPermission可能会导致应用崩溃,可以在代码中判断Build.VERSION.SDK_INT是否小于23。