1.第一種 (抽取基類+回調(diào))
public class PermissionActivity extends AppCompatActivity {
private PermissionsResultListener mListener;
private int mRequestCode;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
protected void checkPermissions(@NonNull String[] permissions, int requestCode, PermissionsResultListener listener) {
List<String> permissionsList = new ArrayList<>();
//權(quán)限不能為空
if (permissions != null || permissions.length != 0) {
mListener = listener;
mRequestCode = requestCode;
for (int i = 0; i < permissions.length; i++) {
if (!isHavePermissions(permissions[i])) {
permissionsList.add(permissions[i]);
} else {
mListener.onPermissionGranted(permissions[i]);
}
}
//遍歷完后申請
requestPermissions(permissionsList);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == mRequestCode) {
if (grantResults.length > 0) {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
mListener.onPermissionGranted(permissions[i]);
} else {
//如果應用之前請求過此權(quán)限但用戶拒絕了請求掉分,ActivityCompat.shouldShowRequestPermissionRationale(this,permissions[i])方法將返回 true,
// 但實際使用過程中發(fā)現(xiàn)第一次出現(xiàn)權(quán)限對話框也會返回true百拓,如果用戶在過去拒絕了權(quán)限請求渠鸽,并在權(quán)限請求系統(tǒng)對話框中選擇了 Don’t ask again 選項嫂粟,
// 此方法將返回 false
if (!(ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i]))) {
mListener.onPermissionDeniedDontAskAgain(permissions[i]);
} else {
mListener.onPermissionDenied(permissions[i]);
}
}
}
} else {
mListener.onPermissionFailure();
}
}
}
//判斷權(quán)限是否申請
private boolean isHavePermissions(@NonNull String permissions) {
if (ContextCompat.checkSelfPermission(this, permissions) != PackageManager.PERMISSION_GRANTED) {
return false;
}
return true;
}
//申請權(quán)限
private void requestPermissions(List<String> permissionsList) {
ActivityCompat.requestPermissions(this, permissionsList.toArray(new String[permissionsList.size()]), mRequestCode);
}
public interface PermissionsResultListener {
//拒絕權(quán)限
void onPermissionDenied(String permissions);
//獲取權(quán)限失敗
void onPermissionFailure();
//成功獲取權(quán)限
void onPermissionGranted(String permissions);
//拒絕了權(quán)限并且勾選了不再提示
void onPermissionDeniedDontAskAgain(String permissions);
}
}
在使用過程中需要將Activity繼承自PermissionActivity 读虏,并實現(xiàn)回調(diào)方法责静,如下所示
public class MainActivity extends PermissionActivity implements PermissionActivity.PermissionsResultListener {
private String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkPermissions(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1, this);
}
@Override
public void onPermissionDenied(String permission) {
switch (permission) {
case Manifest.permission.CALL_PHONE:
Log.e(TAG, "拒絕了撥打電話的權(quán)限");
break;
case Manifest.permission.WRITE_EXTERNAL_STORAGE:
Log.e(TAG, "拒絕了寫存儲卡的權(quán)限");
break;
}
}
@Override
public void onPermissionFailure() {
Log.e(TAG, "申請權(quán)限失敗");
}
@Override
public void onPermissionGranted(String permission) {
switch (permission) {
case Manifest.permission.CALL_PHONE:
Log.e(TAG, "同意了撥打電話的權(quán)限");
break;
case Manifest.permission.WRITE_EXTERNAL_STORAGE:
Log.e(TAG, "同意了寫存儲卡的權(quán)限");
break;
}
}
@Override
public void onPermissionDeniedDontAskAgain(String permission) {
switch (permission) {
case Manifest.permission.CALL_PHONE:
Log.e(TAG, "拒絕了撥打電話的權(quán)限并且不再詢問");
break;
case Manifest.permission.WRITE_EXTERNAL_STORAGE:
Log.e(TAG, "拒絕了寫存儲卡的權(quán)限并且不再詢問");
break;
}
}
}
上述方法看起來通俗易懂,但是在申請的權(quán)限較多時盖桥,需要進行多次的switch語句進行判斷灾螃。代碼稍顯多。
第二種(注解+反射)
1.添加兩個注解
//權(quán)限授予后執(zhí)行的方法注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionGrantedMethod {
public int requestCode();
}
//權(quán)限拒絕后執(zhí)行的方法注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionDeniedMethod {
public int requestCode();
}
2.增加權(quán)限的處理類PermissionHelper
public class PermissionHelper {
private Object mObject; //Fragment or Activity
private int mRequestCode; //請求碼
private String[] mRequestPermissions; //請求的權(quán)限
public PermissionHelper(Object object) {
this.mObject = object;
}
public static void requestPermission(FragmentActivity activity, int requestCode, String[] permissions) {
PermissionHelper.with(activity).requestCode(requestCode).requestPermission(permissions).request();
}
//鏈式調(diào)用
public PermissionHelper with(Fragment fragment) {
return new PermissionHelper(fragment);
}
public static PermissionHelper with(FragmentActivity activity) {
return new PermissionHelper(activity);
}
public PermissionHelper requestCode(int requestCode) {
mRequestCode = requestCode;
return this;
}
public PermissionHelper requestPermission(String... permissions) {
mRequestPermissions = permissions;
return this;
}
//真正實現(xiàn)和發(fā)起權(quán)限請求
public void request() {
//判斷當前版本是不是6.0及以上
if (!PermissionUtil.isOverMarshmallow()) {
//如果不是6.0以上則直接執(zhí)行方法揩徊,通過反射獲取方法執(zhí)行
PermissionUtil.excuteGrantedMethod(mObject, mRequestCode);
return;
} else {
//如果是6.0以上腰鬼,首先判斷權(quán)限是否已經(jīng)授予,獲取還沒有授予的權(quán)限
List<String> deniedPermissionsList = PermissionUtil.getDeniedPermissionsList(mObject, mRequestPermissions);
if (deniedPermissionsList.size() > 0) {
//列表中含有沒有授予的權(quán)限塑荒,則需要去請求權(quán)限
PermissionUtil.requestPermissions(mObject, deniedPermissionsList, mRequestCode);
} else {
//如果權(quán)限已經(jīng)授予則直接執(zhí)行
PermissionUtil.excuteGrantedMethod(mObject, mRequestCode);
}
}
}
/**
* 判斷原來沒有申請到的權(quán)限是否由用戶點擊授予
*
* @param object
* @param requestCode
* @param permissions
*/
public static void requestPermissionResult(Object object, int requestCode, String[] permissions, @NonNull int[] grantResults) {
List<String> deniedPermissionsList = new ArrayList<>();
//表示第一次申請熄赡,或上次申請權(quán)限均拒絕
if (permissions.length == grantResults.length) {
deniedPermissionsList = Arrays.asList(permissions);
} else {
deniedPermissionsList = PermissionUtil.getDeniedPermissionsList(object, permissions);
}
if (deniedPermissionsList.size() == 0) {
//用戶都同意授予權(quán)限,則執(zhí)行方法
PermissionUtil.excuteGrantedMethod(object, requestCode);
} else {
//申請的權(quán)限中有用戶不同意的齿税,同意則執(zhí)行同意的代碼彼硫。需要對權(quán)限進行區(qū)分。
List<String> grantPermissionsList = PermissionUtil.getGrantPermissionsList();
for (int i = 0; i < grantPermissionsList.size(); i++) {
PermissionUtil.excuteGrantedMethod(object, requestCode, grantPermissionsList.get(i));
}
for (int i = 0; i < deniedPermissionsList.size(); i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
PermissionUtil.excuteGrantedMethod(object, requestCode, deniedPermissionsList.get(i));
} else {
PermissionUtil.excuteDeniedMethod(object, requestCode, deniedPermissionsList.get(i));
}
}
}
}
}
3.權(quán)限的輔助工具類
public class PermissionUtil {
private static List<String> grantPermissionsList = new ArrayList<>();
public PermissionUtil() {
throw new UnsupportedOperationException("Can not instantiated");
}
//判斷當前版本是否在6.0及以上
public static boolean isOverMarshmallow() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
public static void excuteGrantedMethod(Object mObject, int mRequestCode, String mRequestPermission) {
Class clazz = mObject.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
//反射獲取帶有PermissionGrantedMethod的方法
PermissionGrantedMethod permissionGrantedMethod = method.getAnnotation(PermissionGrantedMethod.class);
//找到了有該注解的方法
if (permissionGrantedMethod != null) {
//獲取注解中的請求碼
int requestCode = permissionGrantedMethod.requestCode();
String requestPermission = permissionGrantedMethod.requestPermission();
//若注解中的請求碼和傳遞的請求碼一直凌箕,則執(zhí)行這個方法
if (requestCode == mRequestCode && requestPermission == mRequestPermission) {
//反射執(zhí)行該方法拧篮,第一個參數(shù)是這個方法屬于哪個類羡洁,第二個參數(shù)是該方法的參數(shù)
excuteMethod(mObject, method);
}
}
}
}
public static void excuteGrantedMethod(Object mObject, int mRequestCode) {
Class clazz = mObject.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
//反射獲取帶有PermissionGrantedMethod的方法
PermissionGrantedMethod permissionGrantedMethod = method.getAnnotation(PermissionGrantedMethod.class);
//找到了有該注解的方法
if (permissionGrantedMethod != null) {
//獲取注解中的請求碼
int requestCode = permissionGrantedMethod.requestCode();
//若注解中的請求碼和傳遞的請求碼一直负蠕,則執(zhí)行這個方法
if (requestCode == mRequestCode) {
//反射執(zhí)行該方法,第一個參數(shù)是這個方法屬于哪個類枉圃,第二個參數(shù)是該方法的參數(shù)
excuteMethod(mObject, method);
}
}
}
}
/**
* 用戶拒絕了權(quán)限芜壁,則執(zhí)行拒絕的方法
*
* @param mObject
* @param mRequestCode
*/
public static void excuteDeniedMethod(Object mObject, int mRequestCode, String mRequestPermission) {
Class clazz = mObject.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
//反射獲取帶有PermissionDeniedMethod的方法
PermissionDeniedMethod permissionDeniedMethod = method.getAnnotation(PermissionDeniedMethod.class);
//找到了有該注解的方法
if (permissionDeniedMethod != null) {
//獲取注解中的請求碼
int requestCode = permissionDeniedMethod.requestCode();
String requestPermission = permissionDeniedMethod.requestPermission();
//若注解中的請求碼和傳遞的請求碼一直礁凡,則執(zhí)行這個方法
if (requestCode == mRequestCode && requestPermission == mRequestPermission) {
//反射執(zhí)行該方法,第一個參數(shù)是這個方法屬于哪個類沿盅,第二個參數(shù)是該方法的參數(shù)
excuteMethod(mObject, method);
}
}
}
}
//反射執(zhí)行方法
private static void excuteMethod(Object mObject, Method method) {
try {
method.setAccessible(true);
method.invoke(mObject, new Object[]{});
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 獲取沒有授予的權(quán)限
*
* @param object
* @param requestPermissions
* @return
*/
public static List<String> getDeniedPermissionsList(Object object, String[] requestPermissions) {
grantPermissionsList.clear();
List<String> deniedPermissionsList = new ArrayList<>();
for (String requestPermission : requestPermissions) {
if (!isHavePermissions(object, requestPermission)) {
//沒有申請到這個權(quán)限則將其添加到列表中
deniedPermissionsList.add(requestPermission);
} else {
grantPermissionsList.add(requestPermission);
}
}
return deniedPermissionsList;
}
public static List<String> getGrantPermissionsList() {
return grantPermissionsList;
}
//判斷權(quán)限是否申請
private static boolean isHavePermissions(Object object, @NonNull String permission) {
if (ContextCompat.checkSelfPermission(getActivity(object), permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
return true;
}
private static FragmentActivity getActivity(Object object) {
if (object instanceof Fragment) {
return ((Fragment) object).getActivity();
} else if (object instanceof FragmentActivity) {
return (FragmentActivity) object;
}
return null;
}
//申請權(quán)限
public static void requestPermissions(Object object, List<String> deniedPermissionsList, int requestCode) {
ActivityCompat.requestPermissions(getActivity(object), deniedPermissionsList.toArray(new String[deniedPermissionsList.size()]), requestCode);
}
}
4.使用框架實例
public class SecondActivity extends AppCompatActivity {
private String TAG = "MainActivity";
private static final int CALL_PHONE_REQUEST_CODE = 0x11;
private static final String CALL_PHONE_PERMISSION = Manifest.permission.CALL_PHONE;
private static final String WRITE_EXTERNAL_STORAGE_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//checkPermissions(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1, this);
PermissionHelper.requestPermission(this, CALL_PHONE_REQUEST_CODE, new String[]{CALL_PHONE_PERMISSION, WRITE_EXTERNAL_STORAGE_PERMISSION});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CALL_PHONE_REQUEST_CODE)
PermissionHelper.requestPermissionResult(this, CALL_PHONE_REQUEST_CODE, new String[]{CALL_PHONE_PERMISSION, WRITE_EXTERNAL_STORAGE_PERMISSION}, grantResults);
}
@PermissionGrantedMethod(requestCode = CALL_PHONE_REQUEST_CODE, requestPermission = CALL_PHONE_PERMISSION)
public void Call() {
Log.e(TAG, "撥打電話");
}
@PermissionDeniedMethod(requestCode = CALL_PHONE_REQUEST_CODE, requestPermission = CALL_PHONE_PERMISSION)
private void error() {
Log.e(TAG, "撥打電話權(quán)限取消");
}
@PermissionGrantedMethod(requestCode = CALL_PHONE_REQUEST_CODE, requestPermission = WRITE_EXTERNAL_STORAGE_PERMISSION)
private void write() {
Log.e(TAG, "寫存儲卡");
}
@PermissionDeniedMethod(requestCode = CALL_PHONE_REQUEST_CODE, requestPermission = WRITE_EXTERNAL_STORAGE_PERMISSION)
private void writeQuit() {
Log.e(TAG, "寫存儲卡權(quán)限取消");
}
}
目前框架還不夠完善把篓,如果我在申請權(quán)限中一個申請碼對應兩種以上權(quán)限纫溃,如果拒絕一種腰涧,則全部拒絕的問題。后序?qū)⑿薷摹?/p>