1.第一种 (抽取基类+回调)
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<>();
//权限不能为空
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 {
//如果应用之前请求过此权限但用户拒绝了请求,ActivityCompat.shouldShowRequestPermissionRationale(this,permissions[i])方法将返回 true,
// 但实际使用过程中发现第一次出现权限对话框也会返回true,如果用户在过去拒绝了权限请求,并在权限请求系统对话框中选择了 Don’t ask again 选项,
// 此方法将返回 false
if (!(ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i]))) {
mListener.onPermissionDeniedDontAskAgain(permissions[i]);
} else {
mListener.onPermissionDenied(permissions[i]);
}
}
}
} else {
mListener.onPermissionFailure();
}
}
}
//判断权限是否申请
private boolean isHavePermissions(@NonNull String permissions) {
if (ContextCompat.checkSelfPermission(this, permissions) != PackageManager.PERMISSION_GRANTED) {
return false;
}
return true;
}
//申请权限
private void requestPermissions(List<String> permissionsList) {
ActivityCompat.requestPermissions(this, permissionsList.toArray(new String[permissionsList.size()]), mRequestCode);
}
public interface PermissionsResultListener {
//拒绝权限
void onPermissionDenied(String permissions);
//获取权限失败
void onPermissionFailure();
//成功获取权限
void onPermissionGranted(String permissions);
//拒绝了权限并且勾选了不再提示
void onPermissionDeniedDontAskAgain(String permissions);
}
}
在使用过程中需要将Activity继承自PermissionActivity ,并实现回调方法,如下所示
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, "拒绝了拨打电话的权限");
break;
case Manifest.permission.WRITE_EXTERNAL_STORAGE:
Log.e(TAG, "拒绝了写存储卡的权限");
break;
}
}
@Override
public void onPermissionFailure() {
Log.e(TAG, "申请权限失败");
}
@Override
public void onPermissionGranted(String permission) {
switch (permission) {
case Manifest.permission.CALL_PHONE:
Log.e(TAG, "同意了拨打电话的权限");
break;
case Manifest.permission.WRITE_EXTERNAL_STORAGE:
Log.e(TAG, "同意了写存储卡的权限");
break;
}
}
@Override
public void onPermissionDeniedDontAskAgain(String permission) {
switch (permission) {
case Manifest.permission.CALL_PHONE:
Log.e(TAG, "拒绝了拨打电话的权限并且不再询问");
break;
case Manifest.permission.WRITE_EXTERNAL_STORAGE:
Log.e(TAG, "拒绝了写存储卡的权限并且不再询问");
break;
}
}
}
上述方法看起来通俗易懂,但是在申请的权限较多时,需要进行多次的switch语句进行判断。代码稍显多。
第二种(注解+反射)
1.添加两个注解
//权限授予后执行的方法注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionGrantedMethod {
public int requestCode();
}
//权限拒绝后执行的方法注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionDeniedMethod {
public int requestCode();
}
2.增加权限的处理类PermissionHelper
public class PermissionHelper {
private Object mObject; //Fragment or Activity
private int mRequestCode; //请求码
private String[] mRequestPermissions; //请求的权限
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();
}
//链式调用
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;
}
//真正实现和发起权限请求
public void request() {
//判断当前版本是不是6.0及以上
if (!PermissionUtil.isOverMarshmallow()) {
//如果不是6.0以上则直接执行方法,通过反射获取方法执行
PermissionUtil.excuteGrantedMethod(mObject, mRequestCode);
return;
} else {
//如果是6.0以上,首先判断权限是否已经授予,获取还没有授予的权限
List<String> deniedPermissionsList = PermissionUtil.getDeniedPermissionsList(mObject, mRequestPermissions);
if (deniedPermissionsList.size() > 0) {
//列表中含有没有授予的权限,则需要去请求权限
PermissionUtil.requestPermissions(mObject, deniedPermissionsList, mRequestCode);
} else {
//如果权限已经授予则直接执行
PermissionUtil.excuteGrantedMethod(mObject, mRequestCode);
}
}
}
/**
* 判断原来没有申请到的权限是否由用户点击授予
*
* @param object
* @param requestCode
* @param permissions
*/
public static void requestPermissionResult(Object object, int requestCode, String[] permissions, @NonNull int[] grantResults) {
List<String> deniedPermissionsList = new ArrayList<>();
//表示第一次申请,或上次申请权限均拒绝
if (permissions.length == grantResults.length) {
deniedPermissionsList = Arrays.asList(permissions);
} else {
deniedPermissionsList = PermissionUtil.getDeniedPermissionsList(object, permissions);
}
if (deniedPermissionsList.size() == 0) {
//用户都同意授予权限,则执行方法
PermissionUtil.excuteGrantedMethod(object, requestCode);
} else {
//申请的权限中有用户不同意的,同意则执行同意的代码。需要对权限进行区分。
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.权限的辅助工具类
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();
//若注解中的请求码和传递的请求码一直,则执行这个方法
if (requestCode == mRequestCode && requestPermission == mRequestPermission) {
//反射执行该方法,第一个参数是这个方法属于哪个类,第二个参数是该方法的参数
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();
//若注解中的请求码和传递的请求码一直,则执行这个方法
if (requestCode == mRequestCode) {
//反射执行该方法,第一个参数是这个方法属于哪个类,第二个参数是该方法的参数
excuteMethod(mObject, method);
}
}
}
}
/**
* 用户拒绝了权限,则执行拒绝的方法
*
* @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();
//若注解中的请求码和传递的请求码一直,则执行这个方法
if (requestCode == mRequestCode && requestPermission == mRequestPermission) {
//反射执行该方法,第一个参数是这个方法属于哪个类,第二个参数是该方法的参数
excuteMethod(mObject, method);
}
}
}
}
//反射执行方法
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();
}
}
/**
* 获取没有授予的权限
*
* @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)) {
//没有申请到这个权限则将其添加到列表中
deniedPermissionsList.add(requestPermission);
} else {
grantPermissionsList.add(requestPermission);
}
}
return deniedPermissionsList;
}
public static List<String> getGrantPermissionsList() {
return grantPermissionsList;
}
//判断权限是否申请
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;
}
//申请权限
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, "拨打电话权限取消");
}
@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, "写存储卡权限取消");
}
}
目前框架还不够完善,如果我在申请权限中一个申请码对应两种以上权限,如果拒绝一种,则全部拒绝的问题。后序将修改。