权限管理的背景
Android6.0(API23)之前,用户在安装应用的时候会产生一个权限列表,只有允许这些权限之后才可以正常使用该应用。然而有些用户可能并不了解这些权限到底是干嘛用的,甚至会有利用这种“便利”从中牟利。
Android6.0(API23)之后,引入了动态权限这个概念。用户在安装应用的时候不用管这些权限,等到用户需要这些权限的时候,通过告知用户为何需要这些权限,询问用户是否可以得到该权限。这样在一定程度上保护了用户的隐私。
6.0之前权限默认全部允许,6.0之后默认全部禁止,需要用到的时候询问用户是否开启。
权限的分类
Android6.0把权限分为两种:正常权限和危险权限。这些权限都都必须在AndroidMainfest.xml中进行声明。
正常权限:不会对用户的隐私带来不安全,不需要动态申请。权限太多了请参照这个
Android所有权限
危险权限:涉及到用户隐私的数据或资料,对于这些危险权限,在需要用到的时候系统会动态申请。谷歌引入了一个权限组来呈现:
Android6.0之后权限的处理方法(附代码)
举个例子,拍照权限
1.正常在AndroidMainfest.xml中进行声明;
2.在需要用到权限的时候进行检测,在成功回调中进行拍照操作;
/**
* 检查并请求照相权限
*/
private void checkPermission() {
PermissionHelper.getInstance().checkPermission(this, new PermissionCallback() {
@Override
public void onFail() {
}
@Override
public void onSuccess() {
//成功回调中进行操作
}
@Override
public void onDenyItem(String permission, int position) {
}
@Override
public void onGuaranteeItem(String permission, int position) {
}
}, PermissionConfig.CAMERA);
}
3.判断是否缺少权限
/**
* 判断权限集合
* @param permissions
* @return
*/
public boolean lacksPermissions(String... permissions) {
for (String permission : permissions) {
if (lacksPermission(permission)) {
return true;
}
}
return false;
}
/**
* 判断是否缺少权限
* @param permission
* @return
*/
private boolean lacksPermission(String permission) {
if (permission == null){
return false;
}
return ContextCompat.checkSelfPermission(mContext, permission) ==
PackageManager.PERMISSION_DENIED;
}
4.保存所需要但未获得的权限情况,跳转到权限界面进行显示列表;
/**
* 检查权限
* @param context
* @param callback
* @param permissions
*/
public void checkPermission(Context context,PermissionCallback callback,String... permissions) {
mContext = context;
checker = new PermissionsChecker(mContext);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (!checker.lacksPermissions(permissions) && callback != null)
callback.onSuccess();
return;
}
mCheckPermissions = new ArrayList<>();
mAdapterPermissions = new ArrayList<>();
List<String> permissionNames = new ArrayList<>();
PermissionItem item;
for (String permission : permissions) {
if (!checker.lacksPermissions(permission)){
continue;
}
item = new PermissionItem();
//一顿判断
switch (permission){
case android.Manifest.permission.ACCESS_COARSE_LOCATION:
case android.Manifest.permission.ACCESS_FINE_LOCATION:
item.setPermission(permission);
item.setPermissionName(PermissionConfig.Names.LOCATION);
item.setPermissionIconRes(R.drawable.permission_ic_location);
if (!permissionNames.contains(PermissionConfig.Names.LOCATION)){
permissionNames.add(PermissionConfig.Names.LOCATION);
mAdapterPermissions.add(item);
}
break;
case android.Manifest.permission.WRITE_EXTERNAL_STORAGE:
case android.Manifest.permission.READ_EXTERNAL_STORAGE:
item.setPermission(permission);
item.setPermissionName(PermissionConfig.Names.STORAGE);
item.setPermissionIconRes(R.drawable.permission_ic_storage);
if (!permissionNames.contains(PermissionConfig.Names.STORAGE)){
permissionNames.add(PermissionConfig.Names.STORAGE);
mAdapterPermissions.add(item);
}
break;
case android.Manifest.permission.READ_PHONE_STATE:
case android.Manifest.permission.CALL_PHONE:
item.setPermission(permission);
item.setPermissionName(PermissionConfig.Names.PHONE);
item.setPermissionIconRes(R.drawable.permission_ic_phone);
if (!permissionNames.contains(PermissionConfig.Names.PHONE)){
permissionNames.add(PermissionConfig.Names.PHONE);
mAdapterPermissions.add(item);
}
break;
case android.Manifest.permission.RECORD_AUDIO:
item.setPermission(permission);
item.setPermissionName(PermissionConfig.Names.MICRO_PHONE);
item.setPermissionIconRes(R.drawable.permission_ic_micro_phone);
if (!permissionNames.contains(PermissionConfig.Names.MICRO_PHONE)){
permissionNames.add(PermissionConfig.Names.MICRO_PHONE);
mAdapterPermissions.add(item);
}
break;
case android.Manifest.permission.BODY_SENSORS:
item.setPermission(permission);
item.setPermissionName(PermissionConfig.Names.SENSORS);
item.setPermissionIconRes(R.drawable.permission_ic_sensors);
if (!permissionNames.contains(PermissionConfig.Names.SENSORS)){
permissionNames.add(PermissionConfig.Names.SENSORS);
mAdapterPermissions.add(item);
}
break;
case android.Manifest.permission.SEND_SMS:
case android.Manifest.permission.RECEIVE_SMS:
case android.Manifest.permission.READ_SMS:
case android.Manifest.permission.RECEIVE_WAP_PUSH:
case android.Manifest.permission.RECEIVE_MMS:
item.setPermission(permission);
item.setPermissionName(PermissionConfig.Names.SMS);
item.setPermissionIconRes(R.drawable.permission_ic_sms);
if (!permissionNames.contains(PermissionConfig.Names.SMS)){
permissionNames.add(PermissionConfig.Names.SMS);
mAdapterPermissions.add(item);
}
break;
case android.Manifest.permission.READ_CONTACTS:
case android.Manifest.permission.WRITE_CONTACTS:
case android.Manifest.permission.GET_ACCOUNTS:
item.setPermission(permission);
item.setPermissionName(PermissionConfig.Names.CONTACT);
item.setPermissionIconRes(R.drawable.permission_ic_contacts);
if (!permissionNames.contains(PermissionConfig.Names.CONTACT)){
permissionNames.add(PermissionConfig.Names.CONTACT);
mAdapterPermissions.add(item);
}
break;
case android.Manifest.permission.READ_CALENDAR:
case android.Manifest.permission.WRITE_CALENDAR:
item.setPermission(permission);
item.setPermissionName(PermissionConfig.Names.CALENDAR);
item.setPermissionIconRes(R.drawable.permission_ic_calendar);
if (!permissionNames.contains(PermissionConfig.Names.CALENDAR)){
permissionNames.add(PermissionConfig.Names.CALENDAR);
mAdapterPermissions.add(item);
}
break;
case android.Manifest.permission.CAMERA:
item.setPermission(permission);
item.setPermissionName(PermissionConfig.Names.CAMERA);
item.setPermissionIconRes(R.drawable.permission_ic_camera);
if (!permissionNames.contains(PermissionConfig.Names.CAMERA)){
permissionNames.add(PermissionConfig.Names.CAMERA);
mAdapterPermissions.add(item);
}
break;
default:
item = null;
break;
}
if (item != null){
mCheckPermissions.add(item);
}
}
mCallback = callback;
if (mCheckPermissions.size() > 0) {
startActivity();
} else {
if (callback != null)
callback.onSuccess();
}
}
startActivity()跳转到权限界面;
private void startActivity() {
PermissionActivity.setCallBack(mCallback);
Intent intent = new Intent(mContext,PermissionActivity.class);
intent.putExtra("items", (Serializable) mCheckPermissions);
intent.putExtra("adapter_items", (Serializable) mAdapterPermissions);
mContext.startActivity(intent);
}
列出所缺失的权限
权限界面.png
5.显示权限弹窗,请求并修改权限
权限弹窗.png
手动设置操作
// 启动应用的设置
private void startAppSettings() {
Uri packageURI = Uri.parse("package:" + getPackageName());
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
startActivityForResult(intent, REQUEST_SETTING);
}
立即开启操作
ActivityCompat.requestPermissions(PermissionActivity.this, getPermissionStrArray(), REQUEST_CODE);
6.修改权限的回调
public interface PermissionCallback {
void onFail();//申请失败
void onSuccess();//申请成功
void onDenyItem(String permission, int position);//某条权限被拒绝了
void onGuaranteeItem(String permission, int position);//某条权限同意了
}
Android6.0权限相关知识点
- 将targetSdkVersion设置为23,注意,如果你将targetSdkVersion设置为>=23,则必须按照Android谷歌的要求,动态的申请权限,如果你暂时不打算支持动态权限申请,则targetSdkVersion最大只能设置为22.
- 6.0之前权限默认全部允许,6.0之后默认全部禁止,需要用到的时候询问用户是否开启。
网友评论