在《Android6.0动态权限申请总结》一文中,我们详细分析了6.0之前与之后的权限管理变化。以及使用4个方法来适配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,
Bundle savedInstanceState
) {
View view = super.onCreateView(inflater,, 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,得到了解决方案。
学习之路很长,大家共勉吧!