Android6.0权限处理不再复杂
前言
谷歌在2015年8月份时候,发布了Android 6.0版本,代号叫做“棉花糖”(Marshmallow ),其中的很大的一部分变化,是在用户权限授权上,或许是感觉之前默认授权的不合理,现在6.0出来,使得用户权限授权变得合理。
Android 6.0版本之前
在此版本之前,只要在清单文件(AndroidManifest)中申请需要用到的权限,安装之后,所申请的权限将会被允许。
Android 6.0版本之后
从Android6.0开始,APP可以直接安装,但所需的权限则需要动态申请。App在运行时询问用户授予权限,弹出Dialog窗口进行询问是否允许,【拒绝】之后,也可以引导用户前往设置界面。
权限分类
Google将权限分为两类:
一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等,所以开发者直接在清单文件中申请即可;
另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等;
但在Dangerous Permission中,其实还有比较特殊的两个权限存在,分别是SYSTEM_ALERT_WINDOW(允许一个程序打开窗口,显示在其他所有程序的顶层)和WRITE_SETTINGS(允许应用程序更改主屏幕中的设置和快捷方式)。
这两个权限也属于Dangerous Permission,但是在申请上却有点特殊。这两个权限是不能自动授权,也不能运行时请求授权,只能引导用户去应用的设置页手动开启。
PS:Dangerous Permission的权限9大类别
Dangerous Permission的权限9大类别只要授权某一个类别中的其中某一个权限,则该类别的权限默认全部授权,不需要针对该类别再次询问用户是否允许。
常用的权限申请
从Android6.0后,我们常用的权限申请,例如相机权限的申请,代码如下:
// 相机权限 2017/3/8 11:45
public static final int REQUEST_CAMERA = 4;
private static String[] PERMISSIONS_CAMERA = {
Manifest.permission.CAMERA};
/**
* 申请相机权限 2017/3/8 11:48
* @param activity
*/
public static void cameraPermissions(Activity activity) {
logger.debug("Camera permissions.");
int permission = ActivityCompat.checkSelfPermission(activity,
Manifest.permission.CAMERA);
if (permission != PackageManager.PERMISSION_GRANTED) {
logger.debug("Not have camera permissions.");
ActivityCompat.requestPermissions(activity, PERMISSIONS_CAMERA,
REQUEST_CAMERA);
}
}
上面是申请相机权限的代码,那么在调用的Activity类中,重写如下方法:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == RequestPermissions.REQUEST_CAMERA) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
Toast.makeText(this, "请授予相机权限", Toast.LENGTH_SHORT).show();
finish();
}
return;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
以上就是我们常用的权限申请。
PermissionsDispatcher
使用
在module.build.gradle中配置,如下:
compile 'com.github.hotchemi:permissionsdispatcher:2.3.2'
annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:2.3.2'
PS
旧版需要在top.build.gradle中配置如下信息:
buildscript {
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
在module.build.gradle中配置,如下:
apply plugin: 'android-apt'
我在最新的版本2.3.2已经不需要以上的配置了,不然会生成失败。等会在下面会讲。
Activity中的使用
package com.example.chenchubin.mypermission;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.OnNeverAskAgain;
import permissions.dispatcher.OnPermissionDenied;
import permissions.dispatcher.OnShowRationale;
import permissions.dispatcher.PermissionRequest;
import permissions.dispatcher.RuntimePermissions;
@RuntimePermissions
public class ScanQRActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
// 检查权限 2017/4/13 17:22
ScanQRActivityPermissionsDispatcher.getCameraWithCheck(this);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]
grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// 回调代理进行处理 2017/4/13 17:22
ScanQRActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}
/**
* 已授权时,进入Activity会调用该方法 2017/4/13 17:22
*/
@NeedsPermission(Manifest.permission.CAMERA)
public void getCamera() {
}
/**
* 授权申请提示,回调 2017/4/13 17:22
* @param request
*/
@OnShowRationale(Manifest.permission.CAMERA)
public void showRationaleForCamera(final PermissionRequest request) {
new AlertDialog.Builder(this)
.setCancelable(false)
.setTitle("权限申请")
.setMessage("应用需要使用相机权限,您是否确定要使用")
.setNegativeButton("拒绝", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
request.cancel();
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
request.proceed();
}
})
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
}
})
.show();
}
/**
* 拒绝时,回调 2017/4/13 17:22
*/
@OnPermissionDenied(Manifest.permission.CAMERA)
public void showDeniedForCamera() {
new AlertDialog.Builder(this)
.setCancelable(false)
.setTitle("权限申请")
.setMessage("在设置-应用-当前应用权限中开启相机权限,以正常使用拍照")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
})
.setPositiveButton("去设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//开启设置页
startActivity(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
dialog.dismiss();
}
})
.show();
}
/**
* 不再询问时,回调 2017/4/13 17:23
*/
@OnNeverAskAgain(Manifest.permission.CAMERA)
public void showNeverAskForCamera() {
new AlertDialog.Builder(this)
.setCancelable(false)
.setTitle("权限申请")
.setMessage("您已禁止不再询问,请前往设置-应用-当前应用权限中开启相机权限,以正常使用拍照")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
})
.setPositiveButton("去设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//开启设置页
startActivity(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
dialog.dismiss();
}
})
.show();
}
}
注解的意思
@RuntimePermissions
(必选)运行时,需要检查权限的类。
@NeedsPermission
(必选)当进入Activity类时,如果已授权,会直接调用该注解的方法。
@OnShowRationale
(可选)授权申请时,调用。
@OnPermissionDenied
(可选)授权申请被拒绝时,调用。
@OnNeverAskAgain
(可选)授权申请被勾选不再提示时,调用。
PS:
1,执行request.proceed()调用系统申请权限的弹窗;
如果在系统申请弹窗中勾选了不在提示并且拒绝,会调用@OnNeverAskAgain的方法;
2,执行request.cancel()会调用@OnPermissionDenied的方法。
Make Project
Make Project后,编译器会在app\build\intermediates\classes\debug目录下与被注解的Activity同一个包下生成一个辅助类,名称为被注解的Activity名称+PermissionsDispatcher.class,如图所示:
ScanQRActivityPermissionsDispatcherPS:
这里需要注意,因为我在这里遇到了一个大坑。
就是上面提到的,新版中已不需要在top.build.gradle中配置android-apt插件,要不上面的ScanQRActivityPermissionsDispatcher一直没有生成出来,找了我半个小时。。。
生成代理类后,检查调用,代码如下:
// 检查权限 2017/4/13 17:22
ScanQRActivityPermissionsDispatcher.getCameraWithCheck(this);
运行效果
进入检查提示 确定时,提示 拒绝时,提示这样使用后,Android权限请求这一块的逻辑就变得比较友好。
以上的所有内容就是今天要讲的关于Android6.0权限处理的内容。
我自己在写这文章时,也有所收获,同时希望能对大家有所帮助。
谢谢支持~~~