谷歌在android6.0的权限管理方面做了不少的改动,android6.0以前的话需要什么权限只需要在AndroidManifest文件中进行申请就可以了,android6.0以后的话将权限分为两类;一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等;另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等;对于Normal Permissions的话还是跟之前一样的做法,Dangerous Permission的话不仅需要在AndroidManifest中注册,还需要动态申请;下面这些的就是Dangerous Permission:
group:permission-group.CONTACTS
permission:permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
对于这些权限在使用的时候就需要注意,要记得动态去申请添加权限;这里也讲下本人的一个大致思路:
1:判断当前的版本是否在android6.0及以上,如果不是就直接AndroidManifest中申请,
2:android6.0及以上的话,判断用户是否赋予该权限,如果赋予该权限,就运行进行相应的操作,
3:6.0及以上同时没有赋予该权限,就动态的申请并提示用户赋予该权限,,如果赋予该权限,就运行进行相应的操作,如果用户拒绝,就提示用户拒绝该权限的赋予,同时不允许用户进行相应操作,如果用户继续操作,还是提示用户要赋予该权限;
其实在http://blog.csdn.net/wangwo1991/article/details/54666737;
这篇博客中已经讲过6.0权限的处理,不过这是另外一种思路处理,这里要讲的是通过反射和注解的方式处理6.0的权限;反射和注解的话在IOC注解里面已经讲到过了;就直接写成功和失败的注解了;
成功的注解:
@Target(ElementType.METHOD)//ElementType.METHOD方法上面 Target代表放在什么位置
@Retention(RetentionPolicy.RUNTIME)//是编译时检测还是运行时检测 Retention代表什么时候去检测
public @interface PermissionSuccess {
public int requestCode();//请求码
}
失败的注解:
@Target(ElementType.METHOD)//ElementType.METHOD方法上面 Target代表放在什么位置
@Retention(RetentionPolicy.RUNTIME)//是编译时检测还是运行时检测 Retention代表什么时候去检测
public @interface PermissionFail {
public int requestCode();//请求码
}
首先判断当前系统的版本;
/**
* 判断其是不是6.0以上的版本
* @return
*/
public static boolean isOverMarshmallow(){
return Build.VERSION.SDK_INT>=Build.VERSION_CODES.M;
}
根据系统的版本去执行权限的申请或者相应的操作;
//首先判断当前的版本是不是6.0和6.0以上
if (!PermissionUtils.isOverMarshmallow()) {
//如果不是6.0以上, 反射获取执行方法
PermissionUtils.executeSuccess(mObject,mRequestCode);
return;
}
//如果是6.0以上那么首先需要判断是否授予权限
List<String> deniedPermission=PermissionUtils.getDeniedPermission(mObject,mPermisson);
//如果授予了 反射获取执行方法
if(deniedPermission.size()==0){
//全部都是授予过权限的
PermissionUtils.executeSuccess(mObject,mRequestCode);
}else{
//如果没有授予 那么我们就申请
ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
deniedPermission.toArray(new String[deniedPermission.size()]),
mRequestCode);
}
如果是6.0及以上并没有授予权限,就需要去动态申请,谷歌提供了
ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
deniedPermission.toArray(new String[deniedPermission.size()]),
mRequestCode);
方法可以去申请权限,当然了肯定还要去处理申请后的回调;
public static void requestPermissionsResult(Object mObject,int requestCode, String[] permissions, int[] grantResults) {
//再次获取是否授予的权限
List<String> deniedPermission=PermissionUtils.getDeniedPermission(mObject,permissions);
if(deniedPermission.size()==0){
//这些权限全部同一
PermissionUtils.executeSuccess(mObject,requestCode);
}else{
//申请中权限中有用户不同意的
PermissionUtils.executeFailMethod(mObject,requestCode);
}
}
申请的过程以及成功或者失败都是通过反射来执行和实现;如果是成功的话,通过invoke();方法去执行相应的操作;
public static void executeSuccess(Object mOhject, int requestCode) {
//获取class中所有的方法
Method[] methods = mOhject.getClass().getDeclaredMethods();
for(Method method:methods){
System.out.println("--------"+method);
//获取该方法上有没有打这个成功的标记
PermissionSuccess successMethod = method.getAnnotation(PermissionSuccess.class);
if(successMethod!=null){
//代表该方法打了标记
//遍历找到打了标记的方法并且我们的请求码要一致
int methodCode = successMethod.requestCode();
if(methodCode==requestCode){
//这个就是我们要找的成功的方法
//反射执行该方法
executeMethod(mOhject,method);
}
}
}
}
通过反射获取该类中所有的方法,根据传入的requestCode和方法注解中的methodCode对比,如果一致的话,就调用executeMethod();去执行;
private static void executeMethod(Object mOhject,Method method) {
//反射执行方法 第一个参数是该方法是属于哪个类 第二个参数是传参数
try {
method.setAccessible(true);//运行执行私有方法
method.invoke(mOhject,new Object[]{});//反射执行方法
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
获取失败的处理和执行也是一样的;
/**
* 执行失败的方法
* @param mObject
* @param requestCode
*/
public static void executeFailMethod(Object mObject, int requestCode) {
//获取class中所有的方法
Method[] methods = mObject.getClass().getDeclaredMethods();
for(Method method:methods){
System.out.println("--------"+method);
//获取该方法上有没有打这个失败的标记
PermissionFail failMethod = method.getAnnotation(PermissionFail.class);
if(failMethod!=null){
//代表该方法打了标记
//遍历找到打了标记的方法并且我们的请求码要一致
int methodCode = failMethod.requestCode();
if(methodCode==requestCode){
//这个就是我们要找的成功的方法
//反射执行该方法
executeMethod(mObject,method);
}
}
}
}
这里提供了Activity、Fragment以及FragmentActivity的使用,调用下面这些方法进行请求码和需要申请的权限;
//传请求码
public PermissionHelper requestCode(int requestCode) {
this.mRequestCode = requestCode;
return this;
}
//传请求权限
public PermissionHelper requestPermission(String... permisson) {
this.mPermisson = permisson;
return this;
}
使用的时候肯定是要先进行权限的申请;
PermissionHelper.with(MainActivity.this).
requestPermission(new String[]{Manifest.permission.CALL_PHONE}).
requestCode(CALL_PHONE_REQUEST_DODE).
request();
@PermissionSuccess(requestCode =CALL_PHONE_REQUEST_DODE)
private void callPhone(){
Intent intent=new Intent(Intent.ACTION_CALL);
Uri data=Uri.parse("tel:"+"15889548152");
intent.setData(data);
startActivity(intent);
}
这里是成功要执行的相应操作;如果需要对失败也进行相应提示的话,写一个失败的方法就可以了,也可以不处理;
@PermissionFail(requestCode =CALL_PHONE_REQUEST_DODE)
private void callPhoneFail(){
Toast.makeText(this, "你拒绝了拨打电话", Toast.LENGTH_SHORT).show();
}
下面这个的话是申请结果的一个回调;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionHelper.requestPermissionsResult(this,requestCode,permissions,grantResults);
}
这样就ok了,使用起来还是蛮简单的,效果如下: