2步搞定动态权限:一个优雅的Android6.0动态权限申请库

在《Android6.0动态权限申请总结》一文中,我们详细分析了6.0之前与之后的权限管理变化。以及使用4个方法来适配Android6.0的动态权限申请。

忘记或者想要看的朋友,在此奉上文章链接:Android6.0动态权限申请总结

在文章的最后我们说了,这样适配动态权限步骤繁琐、代码分散,对于一个项目维护来说,并不是很好的一件事情。

并且我们讨论了一种我们期望的动态权限申请方案。

本篇文章我们来讲一下对于动态权限申请的封装方案。先上github项目地址:一个优雅的Android6.0动态权限申请库

我们先来看一下具体使用起来是怎么样的:

(1)声明你需要申请的权限:

final String[] permissions = new String[]{
    Manifest.permission.WRITE_EXTERNAL_STORAGE,
    Manifest.permission.CAMERA,
    Manifest.permission.CALL_PHONE
};

(2)创建PermissionRequest类对象并调用request方法:

new PermissionRequest(
    getActivity()
).request(
    permissions,
    new PermissionRequestListener() {
        @Override
        public void onAllowAllPermissions() {
            //所有申请的权限均被允许
        }

        @Override
        public void onDenySomePermissions(Collection<String> denyPermissions) {
            //申请的权限中有权限被拒绝
        }

        @Override
        public void onDenyAndNeverAskAgainSomePermissions(
            Collection<String> denyAndNeverAskAgainPermissions
        ) {
            //申请的权限中有权限被拒绝并勾选了不再提示
        }
    }
);

两步结束,就是这么简单粗暴。仅仅通过两个步骤我们就解决了Android6.0的动态权限问题。对比一下上一篇的代码,这次我们没有被分散的回调,业务代码完全可以集中写在PermissionRequestListener中。而且动态权限申请不再被局限于Activity和Fragment中,只要可以获得到Activity对象,我们可以在任何地方调用该库,来请求动态权限。这样确实实现了我们在上一篇最后所期望达到的结果。

接下来,简单描述一下封装过程。

(1)首先我们定义一个PermissionRequestListener接口。为我们上一篇所讲的动态权限请求结果的3种情况,分别提供一个回调方法。并且在有权限被拒绝 和 有权限被拒绝并不再提示 2种情况下,将被拒绝和不再提示的权限回传给用户。供用户选择性处理。

public interface PermissionRequestListener {

    /**
     * 所有申请的权限均被允许的回调
     */
    void onAllowAllPermissions();

    /**
     * 申请的权限中有权限被拒绝的回调
     */
    void onDenySomePermissions(Collection<String> denyPermissions);

    /**
     * 申请的权限中有权限被拒绝并勾选了不再提示的回调
     */
    void onDenyAndNeverAskAgainSomePermissions(Collection<String> denyAndNeverAskAgainPermissions);

}

(2)接下来我们定义一个PermissionRequest类,该类用于接收用户的申请权限列表和PermissionRequestListener实现类。用于请求权限和回调权限结果的函数。

但是有一个问题出现了。就是Android系统的requestPermissions函数和权限申请的结果回调函数onRequestPermissionsResult是在Activity和Fragment中的。为了更好的将这两个函数也封装起来,我们采用一个没有UI界面的Fragment作为中转。该Fragment所做的事情只有一个,就是申请权限和得到结果。

public class PermissionRequest {

    private static final int REQUEST_CODE = 1990;
    private static final String FRAGMENT_TAG = "PermissionRequestFragment";

    private Activity mActivity;

    public PermissionRequest(
            @NonNull Activity activity
    ) {
        mActivity = activity;
    }

    public void request(
            @NonNull String[] permissions,
            @NonNull PermissionRequestListener permissionRequestListener
    ) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            permissionRequestListener.onAllowAllPermissions();
        } else {
            PermissionRequestListenerWrapper permissionRequestListenerWrapper
                    = new PermissionRequestListenerWrapper(permissionRequestListener);
            if (!EventBus.getDefault().isRegistered(permissionRequestListenerWrapper)) {
                EventBus.getDefault().register(permissionRequestListenerWrapper);
            }

            if (mActivity != null) {
                PermissionRequestFragment permissionRequestFragment;
                Fragment fragment = mActivity.getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
                if (fragment != null && fragment instanceof PermissionRequestFragment) {
                    permissionRequestFragment = (PermissionRequestFragment) fragment;
                } else {
                    permissionRequestFragment
                            = PermissionRequestFragment.makeFragment(REQUEST_CODE);
                    mActivity.getFragmentManager().beginTransaction().add(
                            permissionRequestFragment,
                            FRAGMENT_TAG
                    ).commitAllowingStateLoss();
                    mActivity.getFragmentManager().executePendingTransactions();
                }
                if (permissionRequestFragment.isAdded()) {
                    permissionRequestFragment.requestPermissions(
                            permissions,
                            REQUEST_CODE
                    );
                }
            }
        }
    }

}

(3)没有UI界面的Fragment

public class PermissionRequestFragment extends Fragment {

    public static final String REQUEST_CODE = "REQUEST_CODE";
    private int mRequestCode;

    public static PermissionRequestFragment makeFragment(
            int requestCode
    ) {
        PermissionRequestFragment permissionRequestFragment
                = new PermissionRequestFragment();
        Bundle arguments = new Bundle();
        arguments.putInt(REQUEST_CODE, requestCode);
        permissionRequestFragment.setArguments(arguments);
        return permissionRequestFragment;
    }

    @Nullable
    @Override
    public View onCreateView(
            LayoutInflater inflater,
            ViewGroup container,
            Bundle savedInstanceState
    ) {
        View view = super.onCreateView(inflater, container, savedInstanceState);
        Bundle arguments = getArguments();
        if (arguments != null) {
            mRequestCode = arguments.getInt(REQUEST_CODE);
        }
        return view;
    }

    @Override
    public void onRequestPermissionsResult(
            int requestCode,
            @NonNull String[] permissions,
            @NonNull int[] grantResults
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == mRequestCode) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                int length = grantResults.length;
                LinkedHashSet<String> denyAndNeverAskAgainPermissions = new LinkedHashSet<>();
                LinkedHashSet<String> denyPermissions = new LinkedHashSet<>();
                for (int i = 0; i < length; i++) {
                    if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                        boolean b = shouldShowRequestPermissionRationale(permissions[i]);
                        if (!b) {
                            //申请的权限中有权限被拒绝并勾选了不再提示
                            denyAndNeverAskAgainPermissions.add(permissions[i]);
                        } else {
                            //申请的权限仅仅是被用户拒绝
                            denyPermissions.add(permissions[i]);
                        }
                    }
                }
                if (denyAndNeverAskAgainPermissions.size() > 0) {
                    //申请的权限中有权限被拒绝并勾选了不再提示
                    EventBus.getDefault().post(
                            new OnDenyAndNeverAskAgainSomePermissionsEvent(
                                    denyAndNeverAskAgainPermissions
                            )
                    );
                } else if (denyPermissions.size() > 0) {
                    //申请的权限中有权限被拒绝
                    EventBus.getDefault().post(new OnDenySomePermissionsEvent(
                            denyPermissions
                    ));
                } else {
                    //所有申请的权限均被允许
                    EventBus.getDefault().post(new OnAllowAllPermissionsEvent());
                }
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().post(new OnPermissionRequestFragmentDestroyEvent());
    }

}

(4)这里我们采用EventBus根据不同的结果发出不同的Event。而对于用户传进来的PermissionRequestListener,我们对其做了一层包装,使他能够获得到Fragment发来的事件:

public class PermissionRequestListenerWrapper {

    private PermissionRequestListener mPermissionRequestListener;

    public PermissionRequestListenerWrapper(PermissionRequestListener permissionRequestListener) {
        mPermissionRequestListener = permissionRequestListener;
    }

    @Subscribe
    public void onReceivedOnAllowAllPermissionsEvent(
            OnAllowAllPermissionsEvent onAllowAllPermissionsEvent
    ) {
        if (mPermissionRequestListener != null) {
            mPermissionRequestListener.onAllowAllPermissions();
        }
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
    }

    @Subscribe
    public void onReceivedOnDenySomePermissionsEvent(
            OnDenySomePermissionsEvent onDenySomePermissionsEvent
    ) {
        if (mPermissionRequestListener != null) {
            mPermissionRequestListener.onDenySomePermissions(
                    onDenySomePermissionsEvent.getDenyPermissions()
            );
        }
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
    }

    @Subscribe
    public void onReceivedOnDenyAndNeverAskAgainSomePermissionsEvent(
            OnDenyAndNeverAskAgainSomePermissionsEvent onDenyAndNeverAskAgainSomePermissionsEvent
    ) {
        if (mPermissionRequestListener != null) {
            mPermissionRequestListener.onDenyAndNeverAskAgainSomePermissions(
                    onDenyAndNeverAskAgainSomePermissionsEvent.getDenyAndNeverAskAgainPermissions()
            );
        }
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
    }

    @Subscribe
    public void onReceivedOnPermissionRequestFragmentDestroyEvent(
            OnPermissionRequestFragmentDestroyEvent onPermissionRequestFragmentDestroyEvent
    ) {
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
    }

}

到此,这个动态权限封装库我们就做好了。期间,对于requestPermissions和onRequestPermissionsResult封装遇到了些问题。后来在Github上看到了这个库:RxPermissions,得到了解决方案。

学习之路很长,大家共勉吧!




猜你喜欢

转载自blog.csdn.net/ArimaKisho/article/details/79862348