成年人也是过期的小朋友!大家六一儿童节快乐呀,写过Android 6.0权限RxPermission的使用和源码解析,还没写过Android 原生方式实现Android 6.0权限申请,今天我们就用原生的代码用反射+注解的方式对权限进行封装,话不多说直接上代码。
public class Test1 extends AppCompatActivity {
TextView tv_call_phone;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.permissions_test1);
tv_call_phone = findViewById(R.id.tv_call_phone);
tv_call_phone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(Test1.this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(Test1.this,new String[]{"Manifest.permission.CALL_PHONE"},0);
}
else{
callPhone();
}
}
});
}
public void callPhone(){
Intent intent = new Intent(Intent.ACTION_CALL);
Uri parse = Uri.parse("tel:" + "130xxxxxxxx");
intent.setData(parse);
startActivity(intent);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==0){
if(grantResults!=null&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
callPhone();
}
else{
Toast.makeText(this,"权限被拒绝了",Toast.LENGTH_SHORT).show();
}
}
}
}
以上代码并没有做过任何处理,如果每次申请权限的地方都需要这么做,那就比较麻烦了,那么我们肯定要对点击事件中的代码和onRequestPermissionsResult()里面的代码进行处理,那么要处理成什么样子?接下来看洛
这里我们先定义两个注解一个请求权限成功的注解PermissionSucceed,一个请求权限失败的注解PermissionFail,关于注解的这里我不多解析,不了解的可以去网上看看
@Target({ElementType.METHOD}) //作用于方法上
@Retention(RetentionPolicy.RUNTIME)//表示运行时注解
public @interface PermissionSucceed {
int requestCode();
}
@Target(ElementType.METHOD)//作用于方法上
@Retention(RetentionPolicy.RUNTIME)////表示运行时注解
public @interface PermissionFail {
int requestCode();
}
定义完注解后,接下来我们来实现构建我们的链式调用,使用链式调用呢,可以让我们代码看起来更简洁,调用的时候一行代码搞定
public class PermissionHelper {
private Object object;
private int code;
private String []mRequestPermission;
private PermissionHelper(Object object){
this.object=object;
}
public static PermissionHelper with(Activity activity){
return new PermissionHelper(activity);
}
public static PermissionHelper with(Fragment fragment){
return new PermissionHelper(fragment);
}
public PermissionHelper requstCode(int requestCode){
this.code=requestCode;
return this;
}
public PermissionHelper requstPermission(String... mRequestPermission){
this.mRequestPermission=mRequestPermission;
return this;
}
public void requst(){
if(!PermissionUtils.isOverMarshmallow()){
PermissionUtils.executeSucceedMethod(object,code);
return;
}
List deniedPermissions = PermissionUtils.
getDeniedPermissions(object, mRequestPermission);
//直接授权通过
if(deniedPermissions.size()==0){
PermissionUtils.executeSucceedMethod(object,code);
}
//没授权通过
else{
ActivityCompat.requestPermissions(Utils.getActivity(object),mRequestPermission,code);
}
}
public static void requestPermissionsResult(Object object,int requestCode,String [] permission){
List deniedPermissions = PermissionUtils.getDeniedPermissions(object, permission);
if(deniedPermissions.size() == 0){
// 权限用户都同意授予了
PermissionUtils.executeSucceedMethod(object,requestCode);
}else{
// 你申请的权限中 有用户不同意的
PermissionUtils.executeFailMethod(object,requestCode);
}
}
}
上面代码所用到的PermissionUtils工具类
public class PermissionUtils {
/**
* 执行成功的方法
*/
public static void executeSucceedMethod(Object object,int requestCode){
Class> aClass = object.getClass();
// 获取class中多有的方法
Method[] declaredMethods = aClass.getDeclaredMethods();
// 遍历找到我们打了注解的方法
for(Method method:declaredMethods){
//判断方法上是否打了PermissionSucceed注解
if(method.isAnnotationPresent(PermissionSucceed.class)){
//获取该注解的一些类,并获取注解里面的值
PermissionSucceed annotation = method.getAnnotation(PermissionSucceed.class);
int i = annotation.requestCode();
if(i==requestCode){
//设置方法的一个访问权限
method.setAccessible(true);
try {
//反射执行该方法
method.invoke(object,null);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
//执行失败的方法
public static void executeFailMethod(Object object,int requestCode){
Class> aClass = object.getClass();
Method[] declaredMethods = aClass.getDeclaredMethods();
for(Method method:declaredMethods){
if(method.isAnnotationPresent(PermissionFail.class)){
PermissionFail annotation = method.getAnnotation(PermissionFail.class);
int i = annotation.requestCode();
if(i==requestCode){
method.setAccessible(true);
try {
method.invoke(object,null);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
// 获取没有授予过得权限
@SuppressLint("NewApi")
public static List getDeniedPermissions(Object object, String... permission){
List deniedPermission=new LinkedList<>();
for(String list:permission){
if(object instanceof Activity){
if(((Activity)object).checkSelfPermission(list)!= PackageManager.PERMISSION_GRANTED){
deniedPermission.add(list);
}
}
else{
if(((Fragment)object).getActivity().checkSelfPermission(list)!= PackageManager.PERMISSION_GRANTED){
deniedPermission.add(list);
}
}
}
return deniedPermission;
}
//Android 6.0的判断
public static boolean isOverMarshmallow() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
//将传过来的Object进行转换
public static Activity getActivity(Object object){
if(object instanceof Activity){
return (Activity) object;
}
else{
((Fragment)object).getActivity();
}
return null;
}
}
最后Activity如何使用
public class Test2 extends AppCompatActivity {
TextView tv_call_phone;
// 打电话权限申请的请求码
private static final int CALL_PHONE_REQUEST_CODE = 0x0011;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.permissions_test1);
tv_call_phone=findViewById(R.id.tv_call_phone);
tv_call_phone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PermissionHelper.with(Test2.this).requstCode(CALL_PHONE_REQUEST_CODE).requstPermission(Manifest.permission.CALL_PHONE).requst();
}
});
}
@PermissionSucceed(requestCode = CALL_PHONE_REQUEST_CODE)
public void callPhone(){
Intent intent = new Intent(Intent.ACTION_CALL);
Uri parse = Uri.parse("tel:" + "130xxxxxxxx");
intent.setData(parse);
startActivity(intent);
}
@PermissionFail(requestCode = CALL_PHONE_REQUEST_CODE)
public void callPhoneFaill(){
Toast.makeText(Test2.this,"拒绝了",1000).show();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionHelper.requestPermissionsResult(this,requestCode,permissions);
}
}
参考: Android 6.0(权限申请)基于Rxjava2的RxPermissions2的使用.
参考: Android 6.0(权限申请)RxPermission2源码解析.