谷歌在android6.0的權(quán)限管理方面做了不少的改動,android6.0以前的話需要什么權(quán)限只需要在AndroidManifest文件中進(jìn)行申請就可以了效扫,android6.0以后的話將權(quán)限分為兩類;一類是Normal Permissions昏兆,這類權(quán)限一般不涉及用戶隱私有梆,是不需要用戶進(jìn)行授權(quán)的,比如手機(jī)震動瞒御、訪問網(wǎng)絡(luò)等;另一類是Dangerous Permission神郊,一般是涉及到用戶隱私的肴裙,需要用戶進(jìn)行授權(quán)趾唱,比如讀取sdcard、訪問通訊錄等蜻懦;對于Normal Permissions的話還是跟之前一樣的做法甜癞,Dangerous Permission的話不僅需要在AndroidManifest中注冊,還需要動態(tài)申請宛乃;下面這些的就是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
對于這些權(quán)限在使用的時(shí)候就需要注意悠咱,要記得動態(tài)去申請?zhí)砑訖?quán)限;這里也講下本人的一個大致思路:
1:判斷當(dāng)前的版本是否在android6.0及以上征炼,如果不是就直接AndroidManifest中申請乔煞,
2:android6.0及以上的話,判斷用戶是否賦予該權(quán)限柒室,如果賦予該權(quán)限渡贾,就運(yùn)行進(jìn)行相應(yīng)的操作,
3:6.0及以上同時(shí)沒有賦予該權(quán)限雄右,就動態(tài)的申請并提示用戶賦予該權(quán)限空骚,,如果賦予該權(quán)限擂仍,就運(yùn)行進(jìn)行相應(yīng)的操作囤屹,如果用戶拒絕,就提示用戶拒絕該權(quán)限的賦予逢渔,同時(shí)不允許用戶進(jìn)行相應(yīng)操作肋坚,如果用戶繼續(xù)操作,還是提示用戶要賦予該權(quán)限肃廓;
其實(shí)在http://blog.csdn.net/wangwo1991/article/details/54666737;
這篇博客中已經(jīng)講過6.0權(quán)限的處理智厌,不過這是另外一種思路處理,這里要講的是通過反射和注解的方式處理6.0的權(quán)限盲赊;反射和注解的話在IOC注解里面已經(jīng)講到過了铣鹏;就直接寫成功和失敗的注解了;
成功的注解:
@Target(ElementType.METHOD)//ElementType.METHOD方法上面 Target代表放在什么位置
@Retention(RetentionPolicy.RUNTIME)//是編譯時(shí)檢測還是運(yùn)行時(shí)檢測 Retention代表什么時(shí)候去檢測
public @interface PermissionSuccess {
public int requestCode();//請求碼
}
失敗的注解:
@Target(ElementType.METHOD)//ElementType.METHOD方法上面 Target代表放在什么位置
@Retention(RetentionPolicy.RUNTIME)//是編譯時(shí)檢測還是運(yùn)行時(shí)檢測 Retention代表什么時(shí)候去檢測
public @interface PermissionFail {
public int requestCode();//請求碼
}
首先判斷當(dāng)前系統(tǒng)的版本哀蘑;
/**
* 判斷其是不是6.0以上的版本
* @return
*/
public static boolean isOverMarshmallow(){
return Build.VERSION.SDK_INT>=Build.VERSION_CODES.M;
}
根據(jù)系統(tǒng)的版本去執(zhí)行權(quán)限的申請或者相應(yīng)的操作诚卸;
//首先判斷當(dāng)前的版本是不是6.0和6.0以上
if (!PermissionUtils.isOverMarshmallow()) {
//如果不是6.0以上, 反射獲取執(zhí)行方法
PermissionUtils.executeSuccess(mObject,mRequestCode);
return;
}
//如果是6.0以上那么首先需要判斷是否授予權(quán)限
List<String> deniedPermission=PermissionUtils.getDeniedPermission(mObject,mPermisson);
//如果授予了 反射獲取執(zhí)行方法
if(deniedPermission.size()==0){
//全部都是授予過權(quán)限的
PermissionUtils.executeSuccess(mObject,mRequestCode);
}else{
//如果沒有授予 那么我們就申請
ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
deniedPermission.toArray(new String[deniedPermission.size()]),
mRequestCode);
}
如果是6.0及以上并沒有授予權(quán)限绘迁,就需要去動態(tài)申請合溺,谷歌提供了
ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
deniedPermission.toArray(new String[deniedPermission.size()]),
mRequestCode);
方法可以去申請權(quán)限,當(dāng)然了肯定還要去處理申請后的回調(diào)缀台;
public static void requestPermissionsResult(Object mObject,int requestCode, String[] permissions, int[] grantResults) {
//再次獲取是否授予的權(quán)限
List<String> deniedPermission=PermissionUtils.getDeniedPermission(mObject,permissions);
if(deniedPermission.size()==0){
//這些權(quán)限全部同一
PermissionUtils.executeSuccess(mObject,requestCode);
}else{
//申請中權(quán)限中有用戶不同意的
PermissionUtils.executeFailMethod(mObject,requestCode);
}
}
申請的過程以及成功或者失敗都是通過反射來執(zhí)行和實(shí)現(xiàn)棠赛;如果是成功的話,通過invoke();方法去執(zhí)行相應(yīng)的操作;
public static void executeSuccess(Object mOhject, int requestCode) {
//獲取class中所有的方法
Method[] methods = mOhject.getClass().getDeclaredMethods();
for(Method method:methods){
System.out.println("--------"+method);
//獲取該方法上有沒有打這個成功的標(biāo)記
PermissionSuccess successMethod = method.getAnnotation(PermissionSuccess.class);
if(successMethod!=null){
//代表該方法打了標(biāo)記
//遍歷找到打了標(biāo)記的方法并且我們的請求碼要一致
int methodCode = successMethod.requestCode();
if(methodCode==requestCode){
//這個就是我們要找的成功的方法
//反射執(zhí)行該方法
executeMethod(mOhject,method);
}
}
}
}
通過反射獲取該類中所有的方法恭朗,根據(jù)傳入的requestCode和方法注解中的methodCode對比,如果一致的話依疼,就調(diào)用executeMethod();去執(zhí)行痰腮;
private static void executeMethod(Object mOhject,Method method) {
//反射執(zhí)行方法 第一個參數(shù)是該方法是屬于哪個類 第二個參數(shù)是傳參數(shù)
try {
method.setAccessible(true);//運(yùn)行執(zhí)行私有方法
method.invoke(mOhject,new Object[]{});//反射執(zhí)行方法
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
獲取失敗的處理和執(zhí)行也是一樣的;
/**
* 執(zhí)行失敗的方法
* @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);
//獲取該方法上有沒有打這個失敗的標(biāo)記
PermissionFail failMethod = method.getAnnotation(PermissionFail.class);
if(failMethod!=null){
//代表該方法打了標(biāo)記
//遍歷找到打了標(biāo)記的方法并且我們的請求碼要一致
int methodCode = failMethod.requestCode();
if(methodCode==requestCode){
//這個就是我們要找的成功的方法
//反射執(zhí)行該方法
executeMethod(mObject,method);
}
}
}
}
這里提供了Activity律罢、Fragment以及FragmentActivity的使用膀值,調(diào)用下面這些方法進(jìn)行請求碼和需要申請的權(quán)限;
//傳請求碼
public PermissionHelper requestCode(int requestCode) {
this.mRequestCode = requestCode;
return this;
}
//傳請求權(quán)限
public PermissionHelper requestPermission(String... permisson) {
this.mPermisson = permisson;
return this;
}
使用的時(shí)候肯定是要先進(jìn)行權(quán)限的申請误辑;
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);
}
這里是成功要執(zhí)行的相應(yīng)操作沧踏;如果需要對失敗也進(jìn)行相應(yīng)提示的話,寫一個失敗的方法就可以了巾钉,也可以不處理翘狱;
@PermissionFail(requestCode =CALL_PHONE_REQUEST_DODE)
private void callPhoneFail(){
Toast.makeText(this, "你拒絕了撥打電話", Toast.LENGTH_SHORT).show();
}
下面這個的話是申請結(jié)果的一個回調(diào);
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionHelper.requestPermissionsResult(this,requestCode,permissions,grantResults);
}
這樣就ok了砰苍,使用起來還是蠻簡單的潦匈,效果如下: