Android动态权限申请封装总结
2019-02-19 本文已影响0人
d41f12d62517
最近在做公司的项目的时候,在动态权限申请这部分没有使用市面上流行的第三方库。但是在使用的时候发现每次都需要进行onRequestPermissionsResult 的回调,感觉比较的烦躁。想到RxPermission 这些第三方库没有在Activity中回调,就尝试的用一个透明的Fragment来做中转代理。
最终实现的目的就是要方便维护并且与Activty解耦,所实现的效果是:
PermissionHelper.getInstance().init(this)
.setmRequestCallback(new ICallbackManager.IRequestCallback() {
@Override
public void onAllPermissonGranted(boolean flag) {
hasPermission = true;
checkLicense();
}
})
.setmDenyPermissionCallback(new ICallbackManager.IDenyPermissionCallback() {
@Override
public void onDenyPermissions(List<String> permissions) {
PermissionHelper.getInstance().requestPermissions(permissions.toArray(new String[permissions.size()]));
}
})
.checkPermission(Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
创建代理Fragment
创建一个没有布局的 Fragment ,用于接收回调函数 onRequestPermissionsResult
。
public class PermissionFragment extends Fragment {
private static final int MAX_TRY_COUNT = 10; //requesCode 刷新次数
private FragmentActivity mActivity;
private SparseArray<ICallbackManager.IPermissionListCallback> mListCallbacks = new SparseArray<>();
private Random mCodeGenerator = new Random();
public PermissionFragment() {
}
public static PermissionFragment getInstance() {
return new PermissionFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
mActivity = getActivity();
}
private int createRequestCode() {
int requestCode;
int tryCount = 0;
do {
requestCode = mCodeGenerator.nextInt(0x0000FFFF);
tryCount++;
} while (mListCallbacks.indexOfKey(requestCode) >= 0 && tryCount < MAX_TRY_COUNT);
return requestCode;
}
/**
* 查询权限是否申请
*
* @param permissions
*/
public void checkPermission(ICallbackManager.IPermissionListCallback listCallback, String... permissions) {
ArrayList<String> requestPermissionList = new ArrayList<>();
ArrayList<String> denyPermissionList = new ArrayList<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int grs = 0;
for (String permission : permissions) {
int permissionStatus = (int) ContextCompat.checkSelfPermission(mActivity, permission);
grs += permissionStatus;
if (permissionStatus != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permission)) {
//之前用户禁止过该权限,提示用户权限用处,以及是否重新去开启
denyPermissionList.add(permission);
} else {
requestPermissionList.add(permission);
}
}
}
if (grs == 0) { //全部已经授权过,不必再申请
listCallback.onResultCallback(null);
}
if (!requestPermissionList.isEmpty()) {
requestPermissions(requestPermissionList.toArray(new String[requestPermissionList.size()]), listCallback);
}
if (!denyPermissionList.isEmpty()) {
listCallback.onCheckResultCallback(denyPermissionList);
}
} else { //不需要申请权限
listCallback.onResultCallback(null);
}
}
public void requestPermissions(@NonNull String[] permissions, ICallbackManager.IPermissionListCallback listCallback) {
int requestCode = createRequestCode();
mListCallbacks.put(requestCode, listCallback);
requestPermissions(permissions, requestCode);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
handlePermissionCallback(requestCode, permissions, grantResults);
}
private void handlePermissionCallback(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
ICallbackManager.IPermissionListCallback callback = mListCallbacks.get(requestCode);
if (null == callback) {
return;
}
mListCallbacks.remove(requestCode);
int length = grantResults.length;
ArrayList<Permission> needSetPermissions = new ArrayList<>();
for (int i = 0; i < length; i++) {
String permission = permissions[i];
int grantResult = grantResults[i];
needSetPermissions.add(new Permission(
permission,
grantResult == PackageManager.PERMISSION_GRANTED,
ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permission)
));
}
callback.onResultCallback(needSetPermissions);
}
}
创建调用的辅助类
public class PermissionHelper {
private static final String REQUEST_PERMISSION = "request_permission";
private static FragmentActivity mActivity;
private ICallbackManager.IDenyPermissionCallback mDenyPermissionCallback;
private ICallbackManager.IRequestCallback mRequestCallback;
private static class Holder{
private static PermissionHelper INSTANCE = new PermissionHelper();
}
public PermissionHelper() {
}
public static PermissionHelper getInstance(){
return Holder.INSTANCE;
}
public PermissionHelper init(FragmentActivity activity) {
mActivity = activity;
return Holder.INSTANCE;
}
private PermissionFragment getFragment() {
FragmentManager manager = mActivity.getSupportFragmentManager();
PermissionFragment fragment = (PermissionFragment) manager.findFragmentByTag(REQUEST_PERMISSION);
if (null == fragment) {
fragment = PermissionFragment.getInstance();
manager.beginTransaction()
.add(fragment, REQUEST_PERMISSION)
.commitAllowingStateLoss();
manager.executePendingTransactions(); //立即执行 commit 的事务
}
return fragment;
}
public PermissionHelper setmDenyPermissionCallback(ICallbackManager.IDenyPermissionCallback mDenyPermissionCallback) {
this.mDenyPermissionCallback = mDenyPermissionCallback;
return Holder.INSTANCE;
}
public PermissionHelper setmRequestCallback(ICallbackManager.IRequestCallback mRequestCallback) {
this.mRequestCallback = mRequestCallback;
return Holder.INSTANCE;
}
/**
* 打开设置页面打开权限
*
* @param context
*/
public void startSettingActivity(@NonNull Activity context) {
try {
Intent intent =
new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" +
context.getPackageName()));
intent.addCategory(Intent.CATEGORY_DEFAULT);
context.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 查询权限是否开启,如果有提醒禁止再次提醒,则跳转到设置页面
*
* @param permissions
*/
public void checkPermission(String... permissions) {
getFragment().checkPermission(new ICallbackManager.IPermissionListCallback() {
@Override
public void onResultCallback(List<Permission> permissions) {
boolean granted = true;
if(null != permissions){
for (Permission permission : permissions) {
if (!permission.granted) {
granted = permission.granted;
break;
}
}
}
if (null != mRequestCallback) {
mRequestCallback.onAllPermissonGranted(granted);
}
}
@Override
public void onCheckResultCallback(List<String> permissions) {
if (null != mDenyPermissionCallback) {
mDenyPermissionCallback.onDenyPermissions(permissions);
}
}
}, permissions);
}
/**
* 请求权限
* @param permissions
*/
public void requestPermissions(String...permissions){
getFragment().requestPermissions(permissions, new ICallbackManager.IPermissionListCallback() {
@Override
public void onResultCallback(List<Permission> permissions) {
boolean granted = true;
if(null != permissions){
for (Permission permission : permissions) {
if (!permission.granted) {
granted = permission.granted;
break;
}
}
}
if (null != mRequestCallback) {
mRequestCallback.onAllPermissonGranted(granted);
}
}
@Override
public void onCheckResultCallback(List<String> permissions) {
if (null != mDenyPermissionCallback) {
mDenyPermissionCallback.onDenyPermissions(permissions);
}
}
});
}
}
在这一步的时候出现了调用 Fragment的一些错误,都显示 Fragment 没有attach Activity。最后网上资料搜索一波,最后在 getFragment 方法中加入 manager.executePendingTransactions(); //立即执行 commit 的事务
。这个地方暂时还没有理解得很透彻,有知道详细原因的大神指点一下。
最后
因为项目的权限请求场景并不复杂,所以通过简单的封装可以达到目的,第三方的库总感觉很沉重复杂,在本项目中用就有点大材小用了。
demo下载地址:</br>
https://github.com/qinhaihang/permission
</br>项目新增 gradle引入方式:
- 在项目的root build.gradle 中添加:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
- 在引入的 module 中添加依赖
dependencies {
implementation 'com.github.qinhaihang:permission:Tag'
}