Loading... > 做一个应用Log的实时显示,发现需要用到`SYSTEM_ALERT_WINDOW`权限,视同通用方式获取后发现并不行。 ### 普通权限获取流程 我们在项目中采用的是[PermissionsDispatcher](https://github.com/permissions-dispatcher/PermissionsDispatcher),使用方式也很简单,只需要在类上注解`@RuntimePermissions` ,写一个`public void`的方法,例如`initAfterPermissionChecked`,此方法中写权限获取后的操作即可,方法上用`@NeedsPermission(Manifest.permission.CAMERA)`注解即可,多个权限可以写成下面的形式 ```java @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`,结果编译后直接报错 ```java Method 'initAfterPermissionChecked()' defines 'android.permission.SYSTEM_ALERT_WINDOW' with other permissions at the same time. ``` 根据这个[issues](https://github.com/permissions-dispatcher/PermissionsDispatcher/issues/431)  大概意思就是`WRITE_SETTINGS`和`SYSTEM_ALERT_WINDOW`这类权限不能作为普通权限申请流程的一部分一起申请,因为我们一般需要重新跳转到设置界面去授予权限。 ### 解决 在新的类中获取`SYSTEM_ALERT_WINDOW`权限,同样的流程,类名上注解`@RuntimePermissions` ,新建`public void `方法并注解`@NeedsPermission(Manifest.permission.SYSTEM_ALERT_WINDOW)`,这里我写的是 ```java @NeedsPermission(Manifest.permission.SYSTEM_ALERT_WINDOW) public void checkSystemAlertPermission(){ } ``` 获取权限到地方直接用的 ```java LoginActivityPermissionsDispatcher.checkSystemAlertPermissionWithPermissionCheck(this); ``` 获取。编译运行后发现存在一个问题,那就是这个权限会直接跳转到设置界面,我们需要给个`Dialog`让用户选择 ```java new AlertDialog.Builder(this) .setTitle("提示") .setMessage("显示Log需要在设置中打开系统悬浮窗权限,是否打开?") .setPositiveButton("确定", (dialog, which) -> { LoginActivityPermissionsDispatcher.checkSystemAlertPermissionWithPermissionCheck(this); dialog.dismiss(); }) .setNegativeButton("取消", (dialog, which) -> { dialog.dismiss(); }) .show(); ``` 我们同样不能再进入的时候每次都弹窗让用户选择,毕竟该权限可能已经授予了。于是我选择了使用`ContextCompat`或者`PermissionChecker`的`checkSelfPermission()`方法来校验当前权限是否获取到,但是每次获取的值都是`PackageManager.PERMISSION_DENIED`,于是我们采用另一种方法去获取权限是否授予 ```java Settings.canDrawOverlays(this) ``` 方法注释如下  至此,我们就能正常获取`SYSTEM_ALERT_WINDOW`权限了 ```java 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(); } ``` 最后修改:2023 年 04 月 04 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,请随意赞赏