1.动态权限发射器
/**
* Description : 动态权限发射器
*/
public final class DynamicPermissionEmitter {
private static final String TAG = "DynamicPermissionEmitter";
/**
* 申请权限的回调
*/
public interface ApplyPermissionsCallback {
/**
* 权限以map形式返回
*
* @param permissionEntityMap key value 形式 存储权限实体类,key 为权限名称
*/
void applyPermissionResult(Map<String, DynamicPermissionEntity> permissionEntityMap);
}
/**
* 动态权限申请的 fragment TAG
*/
private static final String DYNAMIC_PERMISSION_FRAGMENT_TAG = "DynamicPermissionFragment";
/**
* 动态权限Fragment
*/
private DynamicPermissionFragment dynamicPermissionFragment;
/**
* fragment manager
*/
private FragmentManager fragmentManager;
/**
* 构造方法
*
* @param activity fragmentActivity
*/
public DynamicPermissionEmitter(@NonNull FragmentActivity activity) {
try {
generateApplyPermissionFragment(activity.getSupportFragmentManager());
} catch (Exception e) {
handleFragmentException(activity, e);
}
}
/**
* 构造方法
*
* @param fragment v4 包下的 fragment
*/
@SuppressLint("LongLogTag")
public DynamicPermissionEmitter(@NonNull Fragment fragment) {
try {
generateApplyPermissionFragment(fragment.getChildFragmentManager());
} catch (Exception e) {
Log.e(TAG, "DynamicPermissionEmitter fragment", e);
}
}
/**
* 用户可能不知道当前是activity还是context 直接通过context转化成FragmentActivity
*
* @param activity fragment
* @param e exception
*/
@SuppressLint("LongLogTag")
private void handleFragmentException(@NonNull FragmentActivity activity, Exception e) {
FragmentManager supportFragmentManager = activity.getSupportFragmentManager();
if (supportFragmentManager != null) {
List<Fragment> fragments = supportFragmentManager.getFragments();
if (fragments != null) {
for (int i = 0; i < fragments.size(); i++) {
Fragment fragment = fragments.get(i);
if (TAG.equals(fragment.getTag())) {
continue;
}
try {
generateApplyPermissionFragment(fragment.getChildFragmentManager());
} catch (Exception e1) {
Log.e(TAG, "DynamicPermissionEmitter activity", e);
}
break;
}
}
}
}
/**
* 生成申请权限的fragment
*
* @param fragmentManager fragmentManager
*/
private void generateApplyPermissionFragment(@NonNull FragmentManager fragmentManager) throws Exception {
this.fragmentManager = fragmentManager;
Fragment mFragment = fragmentManager.findFragmentByTag(DYNAMIC_PERMISSION_FRAGMENT_TAG);
// 保证一个activity 或 fragment 只添加一个permission fragment
if (mFragment != null) {
dynamicPermissionFragment = (DynamicPermissionFragment) mFragment;
} else {
dynamicPermissionFragment = DynamicPermissionFragment.newInstance();
fragmentManager
.beginTransaction()
.add(dynamicPermissionFragment, DYNAMIC_PERMISSION_FRAGMENT_TAG)
.commitNow();
}
}
/**
* 发射权限 不需要回调,只需要检查权限向系统申请权限
*
* @param permissions 权限数组
*/
public void emitterPermission(String... permissions) {
emitterPermission(null, permissions);
}
/**
* 发射权限
*
* @param applyPermissionsCallback 回调
* @param permissions 权限数组
*/
@SuppressLint("LongLogTag")
public void emitterPermission(ApplyPermissionsCallback applyPermissionsCallback, String... permissions) {
if (permissions == null || permissions.length == 0) {
throw new NullPointerException("permissions no nulls allowed...");
}
try {
if (dynamicPermissionFragment == null && fragmentManager != null) {
generateApplyPermissionFragment(fragmentManager);
}
if (dynamicPermissionFragment != null) {
dynamicPermissionFragment.checkRegisteredPermissionInManifest(permissions);
dynamicPermissionFragment.setApplyPermissionsCallback(applyPermissionsCallback);
dynamicPermissionFragment.commitPermission(permissions);
}
} catch (Exception e) {
Log.e(TAG, "emitterPermission", e);
}
}
/**
* 判断是否有某个权限
*
* @param context context
* @param permission 权限名称
* @return 是否有某个存储权限
*/
public static boolean hasPermission(@NonNull Context context, String permission) {
return Build.VERSION.SDK_INT < 23
|| PermissionChecker.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
}
}
2.权限的实体类
/**
* Description : 权限的实体类
*/
public final class DynamicPermissionEntity {
//拒绝了此权限
public static final int PERMISSION_DENIED = 1;
//授予了权限
public static final int PERMISSION_GRANTED = 2;
//拒绝了此权限并且勾选了不在提示
public static final int PERMISSION_DENIED_AND_SELECTED_NO_PROMPT = 3;
//不能处理的权限 例如android 6.0 以下手机,请用try catch 捕获无权限的异常
public static final int PERMISSION_UN_HANDLE = 4;
// 权限名称
private String permissionName;
// 权限状态,默认为被拒绝的权限
private int permissionState = PERMISSION_DENIED;
public String getPermissionName() {
return permissionName;
}
public void setPermissionName(String permissionName) {
this.permissionName = permissionName;
}
public int getPermissionState() {
return permissionState;
}
public void setPermissionState(int permissionState) {
this.permissionState = permissionState;
}
/**
* 6.0 以下也默认为已经有权限
*
* @return 是否授予了某项权限
*/
public boolean isGranted() {
return permissionState == PERMISSION_GRANTED || permissionState == PERMISSION_UN_HANDLE;
}
/**
* 用户已经勾选了不在提示
*
* @return 是否应该给用户一个友好的提示
*/
public boolean shouldShowRequestPermissionRational() {
return permissionState == PERMISSION_DENIED_AND_SELECTED_NO_PROMPT;
}
@Override
public String toString() {
return "DynamicPermissionEntity{" +
"permissionName='" + permissionName + '\'' +
", permissionState=" + permissionState +
'}';
}
}
3.申请权限的fragment
/**
* Description : 申请权限的fragment
*/
public final class DynamicPermissionFragment extends Fragment {
// 权限的请求码
private static final int REQUEST_PERMISSION_CODE = 1000;
private static final String TAG = "DynamicPermissionFragment";
// activity
private Activity activity;
// 申请权限的回调
private DynamicPermissionEmitter.ApplyPermissionsCallback applyPermissionsCallback;
// 存放动态权限实体类与权限名称的映射关系
private Map<String, DynamicPermissionEntity> permissionEntityMap;
public void setApplyPermissionsCallback(DynamicPermissionEmitter.ApplyPermissionsCallback applyPermissionsCallback) {
this.applyPermissionsCallback = applyPermissionsCallback;
}
public static DynamicPermissionFragment newInstance() {
return new DynamicPermissionFragment();
}
/**
* 提交要申请的权限
* 此方法会提取出未授权的权限与已授权的权限,支队未授权的权限进行申请
*
* @param permissions 权限数组
*/
public void commitPermission(String... permissions) {
try {
permissionEntityMap = new HashMap<>();
if (Build.VERSION.SDK_INT < 23) {
//6.0 以下 无法检测到权限
for (String permission : permissions) {
DynamicPermissionEntity dynamicPermissionEntity = new DynamicPermissionEntity();
dynamicPermissionEntity.setPermissionName(permission);
dynamicPermissionEntity.setPermissionState(DynamicPermissionEntity.PERMISSION_UN_HANDLE);
permissionEntityMap.put(permission, dynamicPermissionEntity);
}
if (applyPermissionsCallback != null) {
// callback 之前做一次检查
Map<String, DynamicPermissionEntity> checkPermissionResult = checkPermissionEntityAndRemoveNullEntity(permissionEntityMap);
if (checkPermissionResult != null && checkPermissionResult.size() != 0) {
applyPermissionsCallback.applyPermissionResult(checkPermissionResult);
}
}
return;
}
List<String> unGrantedPermissions = new ArrayList<>(); //未授权的权限列表
for (String permission : permissions) {
if (hasPermission(permission)) {
DynamicPermissionEntity dynamicPermissionEntity = new DynamicPermissionEntity();
dynamicPermissionEntity.setPermissionName(permission);
dynamicPermissionEntity.setPermissionState(DynamicPermissionEntity.PERMISSION_GRANTED);
permissionEntityMap.put(permission, dynamicPermissionEntity);
} else {
unGrantedPermissions.add(permission);
}
}
if (unGrantedPermissions.size() == 0) {
if (applyPermissionsCallback != null) {
// callback 之前做一次检查
Map<String, DynamicPermissionEntity> checkPermissionResult = checkPermissionEntityAndRemoveNullEntity(permissionEntityMap);
if (checkPermissionResult != null && checkPermissionResult.size() != 0) {
applyPermissionsCallback.applyPermissionResult(checkPermissionResult);
}
}
return;
}
// 开始请求权限
applyDynamicPermissions(unGrantedPermissions.toArray(new String[]{}));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param permission 权限
* @return 是否拥有某个权限
*/
public boolean hasPermission(String permission) {
//ContextCompat这种方式检查权限在小米手机上会有问题,使用PermissionChecker 检查权限会正常
//return ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED;
return Build.VERSION.SDK_INT < 23 ||
PermissionChecker.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED;
}
/**
* 请求权限
*
* @param permissions 权限list
*/
@TargetApi(23)
private void applyDynamicPermissions(String... permissions) {
requestPermissions(permissions, REQUEST_PERMISSION_CODE);
}
/**
* 检查要请求的权限在manifest中是否注册
*
* @param permissions 权限列表
*/
@SuppressLint("LongLogTag")
public void checkRegisteredPermissionInManifest(String... permissions) {
PackageManager pm = activity.getPackageManager();
if (pm != null) {
try {
String[] requestedPermissions = pm.getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS).requestedPermissions;
if (requestedPermissions != null) {
if (!Arrays.asList(requestedPermissions).containsAll(Arrays.asList(permissions))) {
throw new IllegalArgumentException("please register the permissions in manifest...");
}
} else {
if (permissions.length != 0) {
throw new IllegalArgumentException("please register the permissions in manifest...");
}
}
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "haveRegisteredPermissionInManifest", e);
}
}
}
/**
* 是否勾选了不在提示
*
* @param permission 权限
* @return true 勾选了不在提示, false没有勾选不在提示,只是拒绝了某个权限
*/
private boolean isSelectedNoTips(@NonNull String permission) {
return !ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
activity = (Activity) context;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
try {
if (activity == null || activity.isFinishing()) {
// 页面关闭不处理结果
return;
}
if (REQUEST_PERMISSION_CODE == requestCode && permissions.length == grantResults.length) {
for (int i = 0; i < permissions.length; i++) {
String permission = permissions[i];
int grant = grantResults[i];
DynamicPermissionEntity dynamicPermissionEntity = new DynamicPermissionEntity();
dynamicPermissionEntity.setPermissionName(permission);
if (grant == PackageManager.PERMISSION_GRANTED) {
dynamicPermissionEntity.setPermissionState(DynamicPermissionEntity.PERMISSION_GRANTED);
} else {
if (isSelectedNoTips(permission)) {
dynamicPermissionEntity.setPermissionState(DynamicPermissionEntity.PERMISSION_DENIED_AND_SELECTED_NO_PROMPT);
} else {
dynamicPermissionEntity.setPermissionState(DynamicPermissionEntity.PERMISSION_DENIED);
}
}
if (permissionEntityMap != null) {
permissionEntityMap.put(permission, dynamicPermissionEntity);
}
}
if (applyPermissionsCallback != null) {
// callback 之前做一次检查
Map<String, DynamicPermissionEntity> checkPermissionResult = checkPermissionEntityAndRemoveNullEntity(permissionEntityMap);
if (checkPermissionResult != null && checkPermissionResult.size() != 0) {
applyPermissionsCallback.applyPermissionResult(checkPermissionResult);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* key 或者 value 如果有为空的 直接移除
* 防止key 或 value为空,省区使用的地方在去判断
*
* @param permissionEntityMap 权限名称对应权限实体类的映射
* @return 结果
*/
private Map<String, DynamicPermissionEntity> checkPermissionEntityAndRemoveNullEntity(Map<String, DynamicPermissionEntity> permissionEntityMap) {
try {
if (permissionEntityMap != null && permissionEntityMap.size() != 0) {
Iterator<Map.Entry<String, DynamicPermissionEntity>> iterator = permissionEntityMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, DynamicPermissionEntity> next = iterator.next();
String key = next.getKey();
DynamicPermissionEntity value = next.getValue();
if (TextUtils.isEmpty(key) || value == null) {
// TODO: 2018/12/1 有key 或 value 为空的情况,如果需要log 在这里输出
iterator.remove();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return permissionEntityMap;
}
}
4.在清单中配置权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
5.调用
private DynamicPermissionEmitter permissionEmitter;
permissionEmitter.emitterPermission(new DynamicPermissionEmitter.ApplyPermissionsCallback() {
@Override
public void applyPermissionResult(Map<String, DynamicPermissionEntity> permissionEntityMap) {
DynamicPermissionEntity dynamicPermissionEntity = permissionEntityMap.get(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (dynamicPermissionEntity.isGranted()) {
Toast.makeText(MainActivity.this, "允许", Toast.LENGTH_LONG).show();
} else if (dynamicPermissionEntity.shouldShowRequestPermissionRational()) {
Toast.makeText(MainActivity.this, "勾选不在提示并且拒绝", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "拒绝", Toast.LENGTH_LONG).show();
}
}
}, Manifest.permission.WRITE_EXTERNAL_STORAGE);