悬浮窗权限获取

  • ~3.00K 字

做一个应用Log的实时显示,发现需要用到SYSTEM_ALERT_WINDOW权限,视同通用方式获取后发现并不行。

普通权限获取流程

我们在项目中采用的是PermissionsDispatcher,使用方式也很简单,只需要在类上注解@RuntimePermissions ,写一个public void的方法,例如initAfterPermissionChecked,此方法中写权限获取后的操作即可,方法上用@NeedsPermission(Manifest.permission.CAMERA)注解即可,多个权限可以写成下面的形式

1
@NeedsPermission({Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION})

编译代码后自动生成类名 + PermissionsDispatcher的Java文件,例如LaunchActivityPermissionsDispatcher,在需要获取权限的地方直接调用方法名 + WithPermissionCheck(this); 生成的Java文件中已经给你生成好了这个方法,例如initAfterPermissionCheckedWithPermissionCheck(),其他针对各种授权与否的处理就不细说了。

问题

对于SYSTEM_ALERT_WINDOW权限,我本想采用相同的方法处理,直接在权限列表后加入Manifest.permission.SYSTEM_ALERT_WINDOW,结果编译后直接报错

1
Method 'initAfterPermissionChecked()' defines 'android.permission.SYSTEM_ALERT_WINDOW' with other permissions at the same time.

根据这个issues

大概意思就是WRITE_SETTINGSSYSTEM_ALERT_WINDOW这类权限不能作为普通权限申请流程的一部分一起申请,因为我们一般需要重新跳转到设置界面去授予权限。

解决

在新的类中获取SYSTEM_ALERT_WINDOW权限,同样的流程,类名上注解@RuntimePermissions ,新建public void 方法并注解@NeedsPermission(Manifest.permission.SYSTEM_ALERT_WINDOW),这里我写的是

1
2
3
4
@NeedsPermission(Manifest.permission.SYSTEM_ALERT_WINDOW)
public void checkSystemAlertPermission(){

}

获取权限到地方直接用的

1
LoginActivityPermissionsDispatcher.checkSystemAlertPermissionWithPermissionCheck(this);

获取。编译运行后发现存在一个问题,那就是这个权限会直接跳转到设置界面,我们需要给个Dialog让用户选择

1
2
3
4
5
6
7
8
9
10
11
new AlertDialog.Builder(this)
.setTitle("提示")
.setMessage("显示Log需要在设置中打开系统悬浮窗权限,是否打开?")
.setPositiveButton("确定", (dialog, which) -> {
LoginActivityPermissionsDispatcher.checkSystemAlertPermissionWithPermissionCheck(this);
dialog.dismiss();
})
.setNegativeButton("取消", (dialog, which) -> {
dialog.dismiss();
})
.show();

我们同样不能再进入的时候每次都弹窗让用户选择,毕竟该权限可能已经授予了。于是我选择了使用ContextCompat或者PermissionCheckercheckSelfPermission()方法来校验当前权限是否获取到,但是每次获取的值都是PackageManager.PERMISSION_DENIED,于是我们采用另一种方法去获取权限是否授予

1
Settings.canDrawOverlays(this)

方法注释如下

至此,我们就能正常获取SYSTEM_ALERT_WINDOW权限了

1
2
3
4
5
6
7
8
9
10
11
12
13
if (!Settings.canDrawOverlays(this)) {
new AlertDialog.Builder(this)
.setTitle("提示")
.setMessage("显示Log需要在设置中打开系统悬浮窗权限,是否打开?")
.setPositiveButton("确定", (dialog, which) -> {
LoginActivityPermissionsDispatcher.checkSystemAlertPermissionWithPermissionCheck(this);
dialog.dismiss();
})
.setNegativeButton("取消", (dialog, which) -> {
dialog.dismiss();
})
.show();
}
赞助喵
非常感谢您的喜欢!
赞助喵
分享这一刻
让朋友们也来瞅瞅!