一.Android 的权限介绍

如果在Android系统中6.0以下的并不需要动态获取,

在Android的6.0系统上有的权限需要动态获取,有的权限不危险不需要动态获取,

但是都需要在AndroidManifest.xml文件中进行配置!

1.动态获取的权限(危险权限,需要在配置文件中配置)

(1)需要动态获取的权限组
// 摄像头权限
Manifest.permission_group.CAMERA;
// 传感器权限
Manifest.permission_group.SENSORS;
// 录制音频权限
Manifest.permission_group.MICROPHONE;
// 日历权限
Manifest.permission_group.CALENDAR;
// 定位权限
Manifest.permission_group.LOCATION;
// 存储权限
Manifest.permission_group.STORAGE;
// 通讯录权限
Manifest.permission_group.CONTACTS;
// 短信权限
Manifest.permission_group.SMS;
// 电话权限
Manifest.permission_group.PHONE;
(2)每个动态权限组中有哪些动态权限
2.常用权限(需要在配置文件中配置)
android:name="android.permission.SET_TIME_ZONE"
tools:ignore="ProtectedPermissions" />
3.权限流程
权限流程图
二.Android 权限
我这里面做的就是一个权限获取权限组的制作。
1.封装一个Permission实体类
import android.Manifest;
public class Permission {
//一共有九个权限
public static final int PERMISSION_LENGTH=9;
// 摄像头权限
public static final int CODE_CAMERA = 0;
// 传感器权限
public static final int CODE_SENSORS = 1;
// 录制音频权限
public static final int CODE_MICROPHONE = 2;
// 日历权限
public static final int CODE_CALENDAR = 3;
// 定位权限
public static final int CODE_LOCATION = 4;
// 存储权限
public static final int CODE_STORAGE = 5;
// 通讯录权限
public static final int CODE_CONTACTS = 6;
// 短信权限
public static final int CODE_SMS = 7;
// 电话权限
public static final int CODE_PHONE = 8;
// 摄像头权限
public static final String CAMERA = Manifest.permission.CAMERA;
// 传感器权限
public static final String BODY_SENSORS = Manifest.permission.BODY_SENSORS;
// 录制音频权限
public static final String RECORD_AUDIO = Manifest.permission.RECORD_AUDIO;
// 日历权限
public static final String READ_CALENDAR = Manifest.permission.READ_CALENDAR;
public static final String WRITE_CALENDAR = Manifest.permission.WRITE_CALENDAR;
// 定位权限
public static final String ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
public static final String ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
// 存储权限
public static final String READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;
public static final String WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
// 通讯录权限
public static final String READ_CONTACTS = Manifest.permission.READ_CONTACTS;
public static final String WRITE_CONTACTS = Manifest.permission.WRITE_CONTACTS;
public static final String GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS;
// 短信权限
public static final String SEND_SMS = Manifest.permission.SEND_SMS;
public static final String RECEIVE_SMS = Manifest.permission.RECEIVE_SMS;
public static final String READ_SMS = Manifest.permission.READ_SMS;
public static final String RECEIVE_WAP_PUSH = Manifest.permission.RECEIVE_WAP_PUSH;
public static final String RECEIVE_MMS = Manifest.permission.RECEIVE_MMS;
// 电话权限
public static final String READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE;
public static final String CALL_PHONE = Manifest.permission.CALL_PHONE;
public static final String READ_CALL_LOG = Manifest.permission.READ_CALL_LOG;
public static final String WRITE_CALL_LOG = Manifest.permission.WRITE_CALL_LOG;
public static final String ADD_VOICEMAIL = Manifest.permission.ADD_VOICEMAIL;
public static final String USE_SIP = Manifest.permission.USE_SIP;
public static final String PROCESS_OUTGOING_CALLS = Manifest.permission.PROCESS_OUTGOING_CALLS;
// 权限组
public static final class Group {
public static final String[] CAMERA = new String[]{Permission.CAMERA};
public static final String[] SENSORS = new String[]{Permission.BODY_SENSORS};
public static final String[] MICROPHONE = new String[]{Permission.RECORD_AUDIO};
public static final String[] CALENDAR = new String[]{
Permission.READ_CALENDAR,
Permission.WRITE_CALENDAR};
public static final String[] LOCATION = new String[]{
Permission.ACCESS_FINE_LOCATION,
Permission.ACCESS_COARSE_LOCATION};
public static final String[] STORAGE = new String[]{
Permission.READ_EXTERNAL_STORAGE,
Permission.WRITE_EXTERNAL_STORAGE};
public static final String[] CONTACTS = new String[]{
Permission.READ_CONTACTS,
Permission.WRITE_CONTACTS,
Permission.GET_ACCOUNTS};
public static final String[] SMS = new String[]{
Permission.SEND_SMS,
Permission.RECEIVE_SMS,
Permission.READ_SMS,
Permission.RECEIVE_WAP_PUSH,
Permission.RECEIVE_MMS};
public static final String[] PHONE = new String[]{
Permission.READ_PHONE_STATE,
Permission.CALL_PHONE,
Permission.READ_CALL_LOG,
Permission.WRITE_CALL_LOG,
Permission.ADD_VOICEMAIL,
Permission.USE_SIP,
Permission.PROCESS_OUTGOING_CALLS};
}
// 根据权限code返回相应的权限组
public static String[] getPermissions(int requestCode){
switch (requestCode){
case Permission.CODE_CAMERA:
return Permission.Group.CAMERA;
case Permission.CODE_SENSORS:
return Permission.Group.SENSORS;
case Permission.CODE_MICROPHONE:
return Permission.Group.MICROPHONE;
case Permission.CODE_CALENDAR:
return Permission.Group.CALENDAR;
case Permission.CODE_LOCATION:
return Permission.Group.LOCATION;
case Permission.CODE_STORAGE:
return Permission.Group.STORAGE;
case Permission.CODE_CONTACTS:
return Permission.Group.CONTACTS;
case Permission.CODE_SMS:
return Permission.Group.SMS;
case Permission.CODE_PHONE:
return Permission.Group.PHONE;
default:
return null;
}
}
}
2.制作一个权限帮助类PermissionHelper
(1)检查是否有权限
/**
* 检查权限是否授予
*
* @param context
* @param requestPermission 权限名称 eg:Permission.CAMERA
* @return
*/
public static int checkSelfPermission(Context context, String requestPermission) {
//如果是6.0以下的手机,ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED,
// 但是,如果用户关闭了你申请的权限,ActivityCompat.checkSelfPermission(),会导致程序崩溃
// (java.lang.RuntimeException: Unknown exception code: 1 msg null),
// 你可以使用try{}catch(){},处理异常,也可以在这个地方,低于23就什么都不做,
// 个人建议try{}catch(){}单独处理,提示用户开启权限。
try {
return ActivityCompat.checkSelfPermission(context, requestPermission);
} catch (RuntimeException e) {
Toast.makeText(context, "请开启权限,因为已经被拒绝过,无法动态获取权限!", Toast.LENGTH_SHORT)
.show();
SuperLog.e("请开启权限,因为已经被拒绝过,无法动态获取权限:" + e.getMessage());
}
return -1;
}
(2)循环获取权限组中的权限,查看没有获取的权限和拒绝的权限
/**
* 循环获取权限
*
* @param context
* @param isShouldRationale true:没获取的权限 , false: 已经拒绝权限
* @return
*/
public static ArrayList getNoGrantedPermission(Context context, int requestCode, boolean isShouldRationale) {
ArrayList permissions = new ArrayList<>();
String[] requestPermissions = Permission.getPermissions(requestCode);
for (int i = 0; i < requestPermissions.length; i++) {
SuperLog.e(i);
String requestPermission = requestPermissions[i];
//TODO checkSelfPermission
int checkSelfPermission = checkSelfPermission(context, requestPermission);
SuperLog.e("checkSelfPermission:" + checkSelfPermission);
if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
SuperLog.e("Android系统超过6.0需要动态申请权限" + requestPermission + "isShouldRationale:" + isShouldRationale);
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, requestPermission)) {
SuperLog.e("权限被拒绝过,并且不在提示");
if (isShouldRationale) {
permissions.add(requestPermission);
}
} else {
if (!isShouldRationale) {
permissions.add(requestPermission);
}
}
}
}
return permissions;
}
(3)需要制作一个权限的成功的回调接口
//回调返回结果
public interface PermissionGrant {
void onPermissionGranted(int requestCode);
}
(4)进行权限申请的方法
/**
* 申请权限组
*/
public static void requestGroupPermission(final Context context, int requestCode, PermissionGrant grant) {
//判断这个权限requestCode是否正确
if (requestCode < 0 || requestCode >= Permission.PERMISSION_LENGTH) {
SuperLog.e("权限code不存在动态获取的requestPermissions数组中:" + requestCode);
return;
}
//可以获取的权限
final List permissionsList = getNoGrantedPermission(context, requestCode, false);
//已经拒绝过的权限并且选择不再提示
final List shouldRationalePermissionsList = getNoGrantedPermission(context, requestCode, true);
//TODO checkSelfPermission
if (permissionsList == null || shouldRationalePermissionsList == null) {
return;
}
SuperLog.e("可以授予的权限列表" + permissionsList.size() + ",被拒绝的权限列表:" + shouldRationalePermissionsList.size());
if (permissionsList.size() > 0) {
ActivityCompat.requestPermissions((Activity) context, permissionsList.toArray(new String[permissionsList.size()]),
requestCode);
} else if (shouldRationalePermissionsList.size() > 0) {
shouldShowRationale(context, requestCode, shouldRationalePermissionsList.toArray(new String[permissionsList.size()]));
} else {
grant.onPermissionGranted(requestCode);
}
}
(5)在权限申请的时候,做一个拒绝权限之后再次点击的弹出框
/**
* 权限首次获取拒绝后再次弹出对话框提示为什么要获取这个权限
*
* @param context
* @param requestCode
* @param requestPermission
*/
private static void shouldShowRationale(final Context context, final int requestCode, final String[] requestPermission) {
String[] permissionsHint = context.getResources().getStringArray(R.array.permissions);
SuperLog.e("被拒绝过,需要弹出对话框来提示,动态获取权限" + requestPermission);
showMessageOKCancel(context, permissionsHint[requestCode], (dialog, which) -> {
ActivityCompat.requestPermissions((Activity) context, requestPermission,
requestCode);
SuperLog.e("动态获取拒绝过的多个权限");
});
}
/**
* 对话框弹出
*
* @param context
* @param message
* @param okListener
*/
private static void showMessageOKCancel(final Context context, String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(context)
.setTitle("权限获取")
.setMessage(message)
.setPositiveButton("好的", okListener)
.setNegativeButton("取消", null)
.create()
.show();
}
(5)在权限申请的时候,如果是拒绝并且选择不再提示,这样就没办法获取权限了,只能提示用户,您需要跳转设置去设置
/**
* 跳转Setting页面
*
* @param context
* @param message
*/
private static void openSettingActivity(final Context context, String message) {
showMessageOKCancel(context, message, (dialog, which) -> {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
SuperLog.e(context.getPackageName());
Uri uri = Uri.fromParts("package", context.getPackageName(), null);
intent.setData(uri);
context.startActivity(intent);
});
}
(6)需要制作一个权限的成功的回调接口
/**
* onRequestPermissionsResult的请求结果回调
*
* @param context
* @param requestCode
* @param permissions
* @param grantResults
* @param permissionGrant
*/
public static void requestGroupResult(@NonNull Context context, final int requestCode, String[] permissions, int[] grantResults, PermissionGrant permissionGrant) {
Map perms = new HashMap<>();
ArrayList notGranted = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
SuperLog.e("第" + i + "个权限, 权限名称:" + permissions[i] + ",权限授予结果:" + grantResults[i]);
perms.put(permissions[i], grantResults[i]);
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
notGranted.add(permissions[i]);
}
}
if (notGranted.size() == 0) {
Toast.makeText(context, "权限都授予成功", Toast.LENGTH_SHORT)
.show();
permissionGrant.onPermissionGranted(requestCode);
} else {
openSettingActivity(context, "因为已经拒绝了权限请求,如果想用这个功能,请去设置页面进行权限设置!");
}
}
(7)配置文件配置
在string.xml文件里面配置
没有此权限,无法开启这个功能,请开启权限。PERMISSION_GET_ACCOUNTS
没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_PHONE_STATE
没有电话权限,无法开启这个功能,请开启电话权限。
没有此权限,无法开启这个功能,请开启权限。PERMISSION_CAMERA
没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_FINE_LOCATION
没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_COARSE_LOCATION
没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_EXTERNAL_STORAGE
没有此权限,无法开启这个功能,请开启权限。PERMISSION_WRITE_EXTERNAL_STORAGE
没有此权限,无法开启这个功能,请开启权限。PERMISSION_RECORD_AUDIO
values文件夹下建一个array.xml文件
@string/permission_camera_hint
@string/permission_sensors_hint
@string/permission_microphone_hint
@string/permission_calendar_hint
@string/permission_location_hint
@string/permission_storage_hint
@string/permission_contacts_hint
@string/permission_sms_hint
@string/permission_phone_hint
三.工具类的使用
假设在一个MainActivity中的一个buttom的点击事件中
1.请求权限方法
Button button = findViewById(R.id.getPermisson);
button.setOnClickListener(v-> {
PermissionHelper.requestGroupPermission(MainActivity.this, Permission.CODE_PHONE,mPermissionGrant);
});
2.权限结果回调,进行之后的操作
private PermissionHelper.PermissionGrant mPermissionGrant = requestCode-> {
switch (requestCode) {
case Permission.CODE_CAMERA:
/* SuperLog.e("已经获取打开摄像头权限");
Toast.makeText(MainActivity.this, "已经获取打开摄像头权限", Toast.LENGTH_SHORT).show();*/
Intent intent = new Intent();
// 指定开启系统相机的Action
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivityForResult(intent, 1);
break;
case Permission.CODE_PHONE:
SuperLog.e("已经获取打开摄像头权限");
Toast.makeText(MainActivity.this, "已经获取打开摄像头权限", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
};
/**
* Callback received when a permissions request has been completed.
*/
@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
PermissionHelper.requestGroupResult(this, requestCode,permissions,grantResults, mPermissionGrant);
}