android——运行时权限封装

前言

前一段时间看了郭霖前辈的一个关于运行时权限封装的视频,现在写一篇文章总结一下我在这个视频里学到的知识。
首先讲一下运行时权限的基本使用:

        if (ContextCompat.checkSelfPermission(MainActivity.this, "权限名") != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, "权限名", 1);
        }
    /**
     * @param requestCode 请求码,用于标识请求者
     * @param permissions 请求的权限列表
     * @param grantResults 请求的权限是否成功的列表
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //申请成功
                } else {
                    //申请失败或被拒绝
                }
                break;
        }
    }

首先用checkSelfPermission()方法(接收两个参数,活动的实例和权限名)判断你需要的权限有没有被授权过,如果没有授权就通过requestPermissions()方法(接收三个参数,活动的实例、权限名和请求码)申请权限。然后重写Activity里的onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 方法,这个方法有三个参数,第一个requestCode就是requestPermissions()方法里的第三个参数,第二个数组是你请求的权限列表,第三个参数是你请求的权限是否授权的列表,第二个和第三个参数是对应的,permissions[0]里的权限对应grantResults[0]

封装

现在进入正题,运行时权限的封装的难点在于回调的onRequestPermissionsResult()方法,这个方法是Activity和Fragment类里的方法,只能在继承这两个类的类中重新这两个方法。也就是说运行时权限只能封装在继承这两个类的类里面。
运行时权限的封装已知的方法有三种:

  1. 第一种方法是建立一个透明的Activity,将代码封装在这个Activity中,在这个Activity上申请权限,这样用户觉察不到这个Activity,但是却能实现我们的功能。
  2. 第二种方法是将运行时权限封装在fragment中,使用时将这个fragment添加到当前的Activity中,由于这个fragment是没有界面的,所以屏幕不会有任何变化,但是已经实现我们的功能了。
  3. 第三种方法是最简单的,建立一个BaseActivity继承AppCompatActivity,然后将运行时权限写在BaseActivity中,再让所有的活动都继承BaseActivity,这样就可以直接申请权限了。

第一种和第二种就不详细讲了,第二种有一个框架可以直接使用https://github.com/tbruyelle/RxPermissions
第三种着重讲一下:
首先新建一个ActivityCollector类:

public class ActivityCollector {
    private static List<Activity> activityList = new ArrayList<Activity>();

    public static void addActivity(Activity activity){
        activityList.add(activity);
    }

    public static void removeActivity(Activity activity){
        activityList.remove(activity);
    }

    public static Activity getTopActivity(){
        if (activityList.isEmpty()) {
            return null;
        } else {
            return activityList.get(activityList.size() - 1);
        }
    }
}

这是一个活动管理类,每个活动启动后都添加到这个管理类中,使用这个类的好处是可以在任何地方获取活动示例,从而在任何地方都可以请求权限。

然后新建一个PermissionListener接口:

public interface PermissionListener {
    void onGranted();

    void onDenied(List<String> deniedPermission);
}

这个接口定义了两个方法,分别是权限申请成功和失败的方法,用于回调;

最后在新建一个BaseActivity类:

public class BaseActivity extends AppCompatActivity {
    private static PermissionListener permissionListener;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }

    public static void requestRuntimePermissions(String[] permissions, PermissionListener listener) {
        permissionListener = listener;
        Activity topActivity = ActivityCollector.getTopActivity();
        if (topActivity == null) {
            return;
        }
        List<String> permissionList = new ArrayList<>();
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(topActivity, permission) != PackageManager.PERMISSION_GRANTED) {
                permissionList.add(permission);
            }
        }
        if (!permissionList.isEmpty()) {
            ActivityCompat.requestPermissions(topActivity, permissionList.toArray(new String[permissionList.size()]), 1);
        } else {
            listener.onGranted();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0) {
                    List<String> deniedPermission = new ArrayList<>();
                    for (int i = 0; i < grantResults.length; i++) {
                        int grantResult = grantResults[i];
                        String permission = permissions[i];
                        if (grantResult != PackageManager.PERMISSION_GRANTED) {
                            deniedPermission.add(permission);
                        }
                    }
                    if (deniedPermission.isEmpty()) {
                        permissionListener.onGranted();
                    } else {
                        permissionListener.onDenied(deniedPermission);
                    }
                }
                break;
        }
    }
}

在这个类中重写了onCreate、onDestroy和onRequestPermissionsResult三个方法,新建了一个requestRuntimePermissions静态方法;在onCreate和onDestroy中向ActivityCollector里添加和删除活动实例,在requestRuntimePermissions中添加请求权限的逻辑,定义成静态可以在任何地方调用,onRequestPermissionsResult是重写的请求的回调,还记得我们定义的那个接口吗,在申请成功或失败后回调这个接口。
最后我们只需使用下面的代码调用就可以了:

BaseActivity.requestRuntimePermissions(new String[]{"Permissions"}, new PermissionListener() {
            @Override
            public void onGranted() {
                //申请成功
            }

            @Override
            public void onDenied(List<String> deniedPermission) {
                //申请失败,以及失败的权限列表
            }
        });

到这里运行时权限的封装就完成了。
我专门写了一个开源框架,里面就是我说的第三种方法,大家不想打代码的可以直接去使用
https://github.com/mashanshui/MssPermission

发布了65 篇原创文章 · 获赞 24 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/shanshui911587154/article/details/77718577