1.概述
上篇文章文章介绍了Android 6.0 运行时权限处理解析,只是写了运行时申请权限处理,但是并未对其做代码封装,这一次我们做一个彻底的封装处理,供以后项目中使用。
2.框架封装
2.1.简单事例:
public class TextActivity extends AppCompatActivity {
// 打电话权限申请的请求码
private static final int CALL_PHONE_REQUEST_CODE = 0x0011;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text);
}
/**
* 检察权限
*/
public void phoneClick(View view) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "申请权限", Toast.LENGTH_SHORT).show();
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQUEST_CODE);
} else {
callPhone();
}
}
/**
* 拨打电话
**/
private void callPhone() {
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:130****7927");
intent.setData(data);
startActivity(intent);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == CALL_PHONE_REQUEST_CODE){
if (grantResults !=null&&grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 授予权限
callPhone();
} else {
// 拒绝权限
Toast.makeText(this,"权限被您拒绝了",Toast.LENGTH_SHORT).show();
}
}
}
}
这是从上一篇中复制过来的,没有任何地方改变,如果我们每次申请权限的地方都需要这么写,那就比较麻烦了,那么我们肯定要对 callPhone() 和 onRequestPermissionsResult() 里面的代码进行处理,那么要怎么处理呢?
2.2.什么方式进行封装
到底采用什么方式去封装,这个github上面也有很多,这里我才用反射+注解的方式去实现。这里就不在详细介绍了,这里我采用 反射 + 注解 的方式去实现。
反射 + 注解刚开始不是太了解,看了 辉哥 Darren,的视频文章懂了很多,非常感谢。大家也可以去看看,每篇文章下边都会附带视频,讲解很详细。
2.3.都需要什么
1.反射我们需要当前的类,第一个参数反射的类this
2.我们的请求码,第二个参数请求码用于监听反馈处理
3.要申请的权限数组,第三个参数传请求权限的数组
2.4 利用什么方式传递参数
可以在工具类里面写一个静态的方法一把塞过去。但是在这里我们可以使用链式调用这种方式我们也经常使用,例如:Retrofit,Okhttp,Gilde,甚至是Android自带的的AlertDialog都是使用的这个方式,也采用这种方式,装装B
3 开始封装
3.1 创建注解文件
//成功注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionSuccess {
public int requestCode(); //请求码
}
//失败的注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionFail {
public int requestCode(); //请求码
}
注解作用:在类,方法,属性上做一个标记,一般配合类反射使用
Target:表示作用在谁身上,方法METHOD,属性FIELD,类TYPE等等
@Target(ElementType.METHOD)
Retention:代表什么时候检测,编译时检测 运行时检测
@Retention(RetentionPolicy.RUNTIME)
3.2 创建PermissionHelper辅助类
public class PermissionHelper {
//1.需要传什么参数
//1.1 Object 可以是Fragment 或 Activity
private Object mObject;
//1.2 int 请求码
private int mRequestCode;
//1.3 String[] 需要申请权限数组
private String[] mRequestPermission;
public PermissionHelper(Object object) {
this.mObject = object;
}
//1.可以直接方法传递
public void requestPermission(Activity activity, int requestCode, String[] permissions) {
PermissionHelper.with(activity).requestCode(requestCode).requestPermission(permissions).request();
}
public void requestPermission(Fragment fragment, int requestCode, String[] permissions) {
PermissionHelper.with(fragment).requestCode(requestCode).requestPermission(permissions).request();
}
//2.可以使用链式调用,链式调用返回的都是this,才可以继续调用
//传Activity
public static PermissionHelper with(Activity activity) {
return new PermissionHelper(activity);
}
//传Fragment
public static PermissionHelper with(Fragment fragment) {
return new PermissionHelper(fragment);
}
//传请求码
public PermissionHelper requestCode(int requestCode) {
this.mRequestCode = requestCode;
return this;
}
//添加请求权限数组 String[] 想同于 String...
public PermissionHelper requestPermission(String... permissions) {
this.mRequestPermission = permissions;
return this;
}
//3.执行链式调用
public void request() {
//3.1 首先判断是否是6.0以上版本
if (!PermissionUtils.isOverMarshmallow()) {
//如果不是就不需要申请权限,直接执行方法,通过反射获取方法
//问题:执行哪个方法不确定,需要通过注解方式来声明,通过反射 + 注解执行
PermissionUtils.executeSuccessMethod(mObject, mRequestCode);
return;
}
//3.2 如果是6.0以上首先判断是否已经给予权限
//判断需要申请的权限中,用户没有授予过的权限,添加到集合中
List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(mObject, mRequestPermission);
//3.2.1 如果授权了,直接执行方法 反射获取执行方法
//如果没有授予的权限为0,表示都已经授予了,就直接执行
if (deniedPermissions.size() == 0) {
PermissionUtils.executeSuccessMethod(mObject, mRequestCode);
}else {
//3.2.2 如果没有授权,就申请授权
ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
deniedPermissions.toArray(new String[deniedPermissions.size()]),
mRequestCode);
}
}
/**
* 获取权限的回掉
* @param object
* @param requestCode
* @param permissions
*/
public static void requestPermissionsResult(Object object, int requestCode, String[] permissions) {
//再次获取数组中没有授予的权限
List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(object,permissions);
if (deniedPermissions.size() == 0){
//都已经授予了,直接执行方法
PermissionUtils.executeSuccessMethod(object, requestCode);
}else {
//申请的权限中,有用户不同意的
PermissionUtils.executeFailMethod(object,requestCode);
}
}
}
3.3 创建PermissionHelper辅助类
public class PermissionUtils {
private List<String> deniedPermissions;
//不允许使用者来new对象,也可以写
public PermissionUtils() {
throw new UnsupportedOperationException("Cannot be instantiated");
}
/**
* 判断是否是6.0以上
* Marshmallow 棉花糖
*/
public static boolean isOverMarshmallow(){
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
/**
* 执行我们成功方法
* @param reflectObject 类对象
* @param requestCode 请求码
*/
public static void executeSuccessMethod(Object reflectObject, int requestCode) {
//1.获取类中的所以有方法
Method[] methods = reflectObject.getClass().getDeclaredMethods();
//2.遍历找到我们方法上打了标记的方法
for (Method method : methods) {
//3.获取方法上是否打了标记
PermissionSuccess permissionSuccess = method.getAnnotation(PermissionSuccess.class);
if (permissionSuccess!=null){
//4.不为空证明该方法打了标记,并判断方法上请求码和申请的是否一样
int methodCode = permissionSuccess.requestCode();
if (methodCode == requestCode){
//相同就是我们要找的方法,反射执行方法
executeMethod(reflectObject,method);
}
}
}
}
/**
* 用户拒绝的权限,执行失败的方法
* @param reflectObject
* @param requestCode
*/
public static void executeFailMethod(Object reflectObject, int requestCode) {
//1.获取所有的方法
Method[] methods = reflectObject.getClass().getDeclaredMethods();
//2.遍历所有的方法,找到失败注解
for (Method method : methods) {
PermissionFail permissionFail = method.getAnnotation(PermissionFail.class);
int methodCode = permissionFail.requestCode();
if (methodCode == requestCode){
//相同是我们要找的方法,反射执行方法
executeMethod(reflectObject,method);
}
}
}
/**
* 执行方法
* @param reflectObject
* @param method
*/
public static void executeMethod(Object reflectObject, Method method) {
/**
* 参数1:该方法属于哪个类
* 参数2:该方法的参数,这里没有
*/
try {
method.setAccessible(true); //强制执行私有方法
method.invoke(reflectObject,new Object[]{});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取没有授予过的权限
* @param object Fragment 或者 Activity
* @param requestPermissions
* @return
*/
public static List<String> getDeniedPermissions(Object object, String[] requestPermissions) {
//创建数组,将用户未授予的权限添加到一个集合中
deniedPermissions = new ArrayList<>();
for (String requestPermission : requestPermissions) {
//将没有授予过的权限添加到集合
if (ContextCompat.checkSelfPermission(getActivity(object),requestPermission) == PackageManager.PERMISSION_DENIED){
deniedPermissions.add(requestPermission);
}
}
return deniedPermissions;
}
/**
* 获取Context上下文
* @param object
* @return
*/
public static Activity getActivity(Object object) {
if (object instanceof Activity){
return (Activity) object;
}
if (object instanceof Fragment){
return ((Fragment) object).getActivity();
}
return null;
}
}
4.最后使用
public class TextActivity extends AppCompatActivity {
// 打电话权限申请的请求码
private static final int CALL_PHONE_REQUEST_CODE = 0x0011;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text);
}
/**
* 调用打电话,只需一行代码
* @param view
*/
public void phoneClick(View view) {
PermissionHelper.with(this).requestCode(CALL_PHONE_REQUEST_CODE).requestPermission(Manifest.permission.CALL_PHONE).request();
}
/**
* 用户允许成功方法
**/
@PermissionSuccess(requestCode = CALL_PHONE_REQUEST_CODE)
private void callPhone() {
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:130****7927");
intent.setData(data);
startActivity(intent);
}
/**
* 用户拒绝失败方法
*/
@PermissionFail(requestCode = CALL_PHONE_REQUEST_CODE)
private void callPhoneFail() {
Toast.makeText(this,"您拒绝了拨打电话",Toast.LENGTH_SHORT).show();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//处理用户的回掉
PermissionHelper.requestPermissionsResult(this,requestCode,permissions);
}
}
这样封装后,是不是清晰很多,一行代码解决问题,我们还可以把onRequestPermissionsResult()的处理写到我们的基类BaseActivity中