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]);
}
}
//遍歷完后申請(qǐng)
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 {
//如果應(yīng)用之前請(qǐng)求過此權(quán)限但用戶拒絕了請(qǐng)求,ActivityCompat.shouldShowRequestPermissionRationale(this,permissions[i])方法將返回 true,
// 但實(shí)際使用過程中發(fā)現(xiàn)第一次出現(xiàn)權(quán)限對(duì)話框也會(huì)返回true,如果用戶在過去拒絕了權(quán)限請(qǐng)求,并在權(quán)限請(qǐng)求系統(tǒng)對(duì)話框中選擇了 Don’t ask again 選項(xiàng),
// 此方法將返回 false
if (!(ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i]))) {
mListener.onPermissionDeniedDontAskAgain(permissions[i]);
} else {
mListener.onPermissionDenied(permissions[i]);
}
}
}
} else {
mListener.onPermissionFailure();
}
}
}
//判斷權(quán)限是否申請(qǐng)
private boolean isHavePermissions(@NonNull String permissions) {
if (ContextCompat.checkSelfPermission(this, permissions) != PackageManager.PERMISSION_GRANTED) {
return false;
}
return true;
}
//申請(qǐng)權(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 ,并實(shí)現(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, "拒絕了寫存儲(chǔ)卡的權(quán)限");
break;
}
}
@Override
public void onPermissionFailure() {
Log.e(TAG, "申請(qǐng)權(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, "同意了寫存儲(chǔ)卡的權(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, "拒絕了寫存儲(chǔ)卡的權(quán)限并且不再詢問");
break;
}
}
}
上述方法看起來通俗易懂,但是在申請(qǐng)的權(quán)限較多時(shí),需要進(jìn)行多次的switch語句進(jìn)行判斷。代碼稍顯多。
第二種(注解+反射)
1.添加兩個(gè)注解
//權(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; //請(qǐng)求碼
private String[] mRequestPermissions; //請(qǐng)求的權(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();
}
//鏈?zhǔn)秸{(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;
}
//真正實(shí)現(xiàn)和發(fā)起權(quán)限請(qǐng)求
public void request() {
//判斷當(dāng)前版本是不是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)限,則需要去請(qǐng)求權(quán)限
PermissionUtil.requestPermissions(mObject, deniedPermissionsList, mRequestCode);
} else {
//如果權(quán)限已經(jīng)授予則直接執(zhí)行
PermissionUtil.excuteGrantedMethod(mObject, mRequestCode);
}
}
}
/**
* 判斷原來沒有申請(qǐng)到的權(quán)限是否由用戶點(diǎ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<>();
//表示第一次申請(qǐng),或上次申請(qǐng)權(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 {
//申請(qǐng)的權(quán)限中有用戶不同意的,同意則執(zhí)行同意的代碼。需要對(duì)權(quán)限進(jì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");
}
//判斷當(dāng)前版本是否在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) {
//獲取注解中的請(qǐng)求碼
int requestCode = permissionGrantedMethod.requestCode();
String requestPermission = permissionGrantedMethod.requestPermission();
//若注解中的請(qǐng)求碼和傳遞的請(qǐng)求碼一直,則執(zhí)行這個(gè)方法
if (requestCode == mRequestCode && requestPermission == mRequestPermission) {
//反射執(zhí)行該方法,第一個(gè)參數(shù)是這個(gè)方法屬于哪個(gè)類,第二個(gè)參數(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) {
//獲取注解中的請(qǐng)求碼
int requestCode = permissionGrantedMethod.requestCode();
//若注解中的請(qǐng)求碼和傳遞的請(qǐng)求碼一直,則執(zhí)行這個(gè)方法
if (requestCode == mRequestCode) {
//反射執(zhí)行該方法,第一個(gè)參數(shù)是這個(gè)方法屬于哪個(gè)類,第二個(gè)參數(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) {
//獲取注解中的請(qǐng)求碼
int requestCode = permissionDeniedMethod.requestCode();
String requestPermission = permissionDeniedMethod.requestPermission();
//若注解中的請(qǐng)求碼和傳遞的請(qǐng)求碼一直,則執(zhí)行這個(gè)方法
if (requestCode == mRequestCode && requestPermission == mRequestPermission) {
//反射執(zhí)行該方法,第一個(gè)參數(shù)是這個(gè)方法屬于哪個(gè)類,第二個(gè)參數(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)) {
//沒有申請(qǐng)到這個(gè)權(quán)限則將其添加到列表中
deniedPermissionsList.add(requestPermission);
} else {
grantPermissionsList.add(requestPermission);
}
}
return deniedPermissionsList;
}
public static List<String> getGrantPermissionsList() {
return grantPermissionsList;
}
//判斷權(quán)限是否申請(qǐng)
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;
}
//申請(qǐng)權(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.使用框架實(shí)例
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, "寫存儲(chǔ)卡");
}
@PermissionDeniedMethod(requestCode = CALL_PHONE_REQUEST_CODE, requestPermission = WRITE_EXTERNAL_STORAGE_PERMISSION)
private void writeQuit() {
Log.e(TAG, "寫存儲(chǔ)卡權(quán)限取消");
}
}
目前框架還不夠完善,如果我在申請(qǐng)權(quán)限中一個(gè)申請(qǐng)碼對(duì)應(yīng)兩種以上權(quán)限,如果拒絕一種,則全部拒絕的問題。后序?qū)⑿薷摹?/p>