Android6.0引入了新的权限机制,早已有大神对此做过讲解,比如这篇文章:
http://blog.csdn.net/lmj623565791/article/details/50709663
本文对Android权限相关知识做一些其它补充。
一、 获取某个应用的权限清单(Manifest.xml中申请的权限)
private List<String> getAppRegistPermissions(){
List<String> permissionList = new ArrayList<>();
try {
PackageManager pm = getPackageManager();
PackageInfo pack = pm.getPackageInfo(getPackageName(),PackageManager.GET_PERMISSIONS);
String[] permissionStrings = pack.requestedPermissions;
permissionList = Arrays.asList(permissionStrings);
return permissionList;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return permissionList;
}
二、检查APP是否申请了某项权限
int granted = 0;
//1、android6.0及以上
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
granted = checkSelfPermission(permission);
}
//2、使用support包中的ContextCompat
granted = ContextCompat.checkSelfPermission(this, permission);
//3、通过PackageManager判断
PackageManager pm = getPackageManager();
granted=pm.checkPermission(permission, getPackageName());
三、适配Android6.0以上
1、在AndroidManifest文件中添加需要的权限。
2、检查权限
private boolean hasPermission(String... permissions) {
for (String permission : permissions) {
int granted = ContextCompat.checkSelfPermission(this, permission);
if(granted == PackageManager.PERMISSION_DENIED){
return false;
}
}
return true;
}
3、申请授权
private void requestPermissions(int reqCode, String... permissions) {
ActivityCompat.requestPermissions(this, permissions, reqCode);
}
4、处理权限申请回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
List<String> deniedPermissions = new ArrayList<>();
for(int i=0; i<grantResults.length; i++){
if(grantResults[i] != PackageManager.PERMISSION_GRANTED){
deniedPermissions.add(permissions[i]);
}
}
if(deniedPermissions.size() > 0){
//权限被拒绝
} else {
//权限申请成功
}
}
不过还有个API值得提一下:
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS))
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
}
这个API主要用于给用户一个申请权限的解释,该方法只有在用户在上一次已经拒绝过你的这个权限申请。也就是说,用户已经拒绝一次了,你又弹个授权框,
你需要给用户一个解释,为什么要授权,则使用该方法。
那么将上述几个步骤结合到一起就是:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
四、权限封装
从android6.0后可以看出,权限检查、权限申请完全一致,就权限回调处理不太一样,也就是说,如果我们要做封装,难点就在于完成权限申请成功和失败的处理。然而
权限成功和失败的处理和具体业务逻辑绑定的,我们没法预先知道具体方法,这时候反射就排上用场了。在Activity或Fragment中定义我们自己的业务方法,然后在方法上使用定义好的注解来标识,这样我们就可以在申请权限后通过反射Activity或Fragment,拿到标识了权限注解的方法,进行调用。完整代码如下:
1、定义注解
权限申请成功后调用的方法
/**
* 标识权限获取成功
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PermissionSuccess {
int requestCode();
}
/**
* 标识权限获取失败
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionFail {
int requestCode();
}
2、权限工具类
public class PermissionUtil {
public static void needPermission(Fragment context, int reqCode, String... permissions) {
checkPermission(context, reqCode, permissions);
}
public static void needPermission(Activity context, int reqCode, String... permissions) {
checkPermission(context, reqCode, permissions);
}
@TargetApi(Build.VERSION_CODES.M)
private static void checkPermission(Object context, int reqCode, String... permissions) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
//6.0以下
executeSuccessResult(context, reqCode);
return;
}
boolean granted = hasPermission(context, permissions);//检查权限
if (granted) {
executeSuccessResult(context, reqCode);
} else {
if (context instanceof Fragment) {
((Fragment) context).requestPermissions(permissions, reqCode);
} else {
((Activity) context).requestPermissions(permissions, reqCode);
}
}
}
private static void executeSuccessResult(Object context, int reqCode) {
Method successMethod = getTargetMethod(context, reqCode, PermissionSuccess.class);
try {
successMethod.invoke(context);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void executeFailResult(Object context, int reqCode) {
Method successMethod = getTargetMethod(context, reqCode, PermissionFail.class);
try {
successMethod.invoke(context);
} catch (Exception e) {
e.printStackTrace();
}
}
private static Method getTargetMethod(Object context, int reqCode, Class annotation) {
Method[] declaredMethods = context.getClass().getDeclaredMethods();
for (Method method : declaredMethods) {
if (!method.isAccessible()) {
method.setAccessible(true); //私有的方法必须强制
}
//判断方法上是否使用了目标注解
boolean annotationPresent = method.isAnnotationPresent(annotation);
if (annotationPresent) {
if (isTargetMethod(method, reqCode, annotation)) { //比较requestCode是否相等
return method;
}
}
}
return null;
}
private static boolean isTargetMethod(Method method, int reqCode, Class cls) {
if (cls.equals(PermissionSuccess.class)) {
return reqCode == method.getAnnotation(PermissionSuccess.class).requestCode();
} else if (cls.equals(PermissionFail.class)) {
return reqCode == method.getAnnotation(PermissionFail.class).requestCode();
}
return false;
}
private static boolean hasPermission(Object context, String... permissions) {
Activity activity = null;
if (context instanceof Fragment) {
activity = ((Fragment) context).getActivity();
} else {
activity = (Activity) context;
}
for (String permission : permissions) {
int granted = ContextCompat.checkSelfPermission(activity, permission);
if (granted == PackageManager.PERMISSION_DENIED) {
return false;
}
}
return true;
}
public static void onRequestPermissionsResult(Fragment context, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
handlePermissionsResult(context, requestCode, permissions, grantResults);
}
public static void onRequestPermissionsResult(Activity context, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
handlePermissionsResult(context, requestCode, permissions, grantResults);
}
private static void handlePermissionsResult(Object context, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
boolean permissionGranted = true;
for (int grant : grantResults) {
if (grant == PackageManager.PERMISSION_DENIED) {
permissionGranted = false;
break;
}
}
if (permissionGranted) {
//获得权限
executeSuccessResult(context, requestCode);
} else {
//权限被用户拒绝
executeFailResult(context, requestCode);
}
}
}
下载完整Demo