目录
效果图
一、环境配置
二、新建工具类
三、开始使用
备注(一):用户手动设置权限
手动设置效果图
备注(二):在Fragment中如何调用动态权限申请
备注(三):悬浮窗权限处理
1、配置环境
2、核心代码
3、在需要使用的地方调用上面的函数
悬浮窗申请效果图
AndroidManifest.xml中先配置需要的权限,这里以【读写通讯录】权限为例:
新建一个工具类PermissionUtil.class,用于循环【验证权限】、【申请权限】及【申请权限后用户的选择结果】的操作处理。
/**
* 权限工具类
*/
public class PermissionUtil {
/**
* 判断是否权限都已授权,存在未授权则进行申请授权
* @param activity
* @param permissions 权限列表
* @param requestCode
* @return
*/
public static boolean checkPermission (Activity activity, String[] permissions, int requestCode ) {
// 默认已经授权
int check = PackageManager.PERMISSION_GRANTED;
// 判断安卓版本是否是大于6.0(6.0及以上才需要申请权限)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 循环处理
for (String permission : permissions) {
// 验证单个权限是否授权-【核心】
check = ContextCompat.checkSelfPermission(activity, permission);
// 判断发现存在某一个未授权
if (check != PackageManager.PERMISSION_GRANTED) {
break;
}
}
}
// 存在某一个未授权,重新进行申请权限
if (check != PackageManager.PERMISSION_GRANTED) {
// 执行权限列表的申请-【核心】
ActivityCompat.requestPermissions(activity, permissions, requestCode);
return false;
}
return true;
}
/**
* 判断权限集合是否授权结果里是否存在未授权的情况,如果有返回false,否则反之
* @param grantResults
* @return
*/
public static boolean checkGrant (int[] grantResults) {
// 判断是否存在结果集合,没有直接返回false
if (grantResults != null) {
// 循环判断
for (int grant : grantResults) {
// 判断是否有未授权
if (grant != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
return false;
}
}
在需要使用的activity中,添加以下代码,通过前面的工具类PermissionUtil中的checkPermission方法进行【验证权限】和【申请权限】,然后通过onRequestPermissionsResult监听【申请权限后用户的选择结果】:
private static final int REQUEST_CODE = 1; // 申请权限状态标识
private static final String[] PERMISSIONS_CONTACTS = new String[] {
// 申请权限集合
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// 判断是否有获取对应权限,没有则进行申请
PermissionUtil.checkPermission(getActivity(), PERMISSIONS_CONTACTS, REQUEST_CODE);
}
/**
* 判断申请权限用户是否同意
* @param requestCode The request code passed in
* @param permissions The requested permissions. Never null.
* @param grantResults The grant results for the corresponding permissions
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (PermissionUtil.checkGrant(grantResults)) {
// 用户授予了权限,执行相应操作
Log.d(TAG, "用户授予了权限");
} else {
// 用户拒绝了权限
Log.e(TAG, "用户拒绝了权限");
}
}
}
因为用户一旦拒绝2次权限申请,就不会再提示该权限的申请,就需要一个一个跳转该app的系统设置-权限页面,让用户手动设置的方法,如下所示:
// 跳转设置-权限
private void jumpToSetting () {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", getPackageName(), null));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
代码基本一致,只是要在父activity中加上这一段代码:
// 在Activity中遍历所有的Fragment,并调用它们的onRequestPermissionsResult方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
悬浮窗权限比较特殊,无法弹出给用户选择,需要跳转到系统设置,让用户自己手动开启
直接复制粘贴拿去用就好:
// 判断是否有悬浮窗权限
public boolean isOverlayPermission(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return Settings.canDrawOverlays(context);
} else {
try {
Class clazz = Settings.class;
Method method = clazz.getDeclaredMethod("canDrawOverlays", Context.class);
return (Boolean) method.invoke(null, context);
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
// 跳转系统设置-悬浮窗页面
public void jumpToPermission() {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getContext().getPackageName()));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// 判断是否有获取悬浮窗,有的话才执行startService
if (isOverlayPermission(getContext())) {
// 悬浮窗权限已被授予,可以显示悬浮窗
Log.d(TAG, "悬浮窗权限已被授予");
} else {
// 悬浮窗权限未被授予
Log.e(TAG, "悬浮窗权限未被授予");
// 跳转系统设置去手动开启
jumpToPermission();
}
}