Android6.0权限适配
2016-10-04 23:04
423 查看
Android6.0引入了新的权限机制,早已有大神对此做过讲解,比如这篇文章:
http://blog.csdn.net/lmj623565791/article/details/50709663
本文对Android权限相关知识做一些其它补充。
2、检查权限
3、申请授权
4、处理权限申请回调
不过还有个API值得提一下:
你需要给用户一个解释,为什么要授权,则使用该方法。
那么将上述几个步骤结合到一起就是:
权限成功和失败的处理和具体业务逻辑绑定的,我们没法预先知道具体方法,这时候反射就排上用场了。在Activity或Fragment中定义我们自己的业务方法,然后在方法上使用定义好的注解来标识,这样我们就可以在申请权限后通过反射Activity或Fragment,拿到标识了权限注解的方法,进行调用。完整代码如下:
1、定义注解
权限申请成功后调用的方法
申请被用户拒绝后调用的方法
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
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
相关文章推荐
- Android6.0权限适配之WRITE_EXTERNAL_STORAGE(SD卡写入)
- Android6.0权限适配
- android6.0权限适配RxPermissions
- Android6.0运行时候权限适配
- Android6.0权限适配之WRITE_EXTERNAL_STORAGE(SD卡写入)
- Android6.0权限适配
- Android app实现自更新和安装,权限检测适配Android6.0以下和Android6.0和Android7.0和Android8.0总结篇
- Android6.0运行时权限适配
- Android6.0权限适配
- Android6.0权限适配
- 国内第三方Rom在Android6.0以下系统的权限适配
- Android6.0权限适配之WRITE_EXTERNAL_STORAGE(SD卡写入)
- Android6.0权限适配实践
- Android6.0后权限适配,参考地址
- 关于Android6.0权限适配的问题
- Android6.0权限适配之WRITE_EXTERNAL_STORAGE(SD卡写入)
- android6.0动态权限管理,小米bug适配
- [置顶] Android6.0权限适配的那些坑
- Android6.0权限适配
- Android6.0权限适配