Android 检测权限启用/禁用状态变更并更新按钮的最优方案
onWindowFocusChanged方案可行性
是可行的。你提到的状态栏修改通知权限、分屏模式下修改悬浮窗权限的场景,都会触发当前应用窗口的焦点变化,当窗口重新获得焦点时onWindowFocusChanged回调会被触发,此时检测权限状态即可同步更新按钮文本,完全可以替代轮询方案,不会产生多余的性能消耗。
更优实现方案
分两类权限分别处理,可以兼顾覆盖场景和性能:
1. 通知权限监听
- Android 11(API 30)及以上版本可以注册系统广播:
- 监听单个通知渠道封禁状态:
ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED - 监听应用全局通知开关状态:
ACTION_APP_BLOCK_STATE_CHANGED
收到广播时直接更新button_A状态即可,无需等待窗口焦点变更,实时性更高。
- 监听单个通知渠道封禁状态:
- 低版本系统可以用
onWindowFocusChanged+onResume组合兜底检测。
2. 悬浮窗权限监听
系统未提供专门的状态变更广播,使用onWindowFocusChanged回调检测是当前最优方案,在窗口获得焦点时调用Settings.canDrawOverlays(context)检测状态,更新button_B即可覆盖所有用户修改权限的场景。
参考实现代码
override fun onResume() { super.onResume() updatePermissionButtonStates() } override fun onWindowFocusChanged(hasFocus: Boolean) { super.onWindowFocusChanged(hasFocus) if (hasFocus) { updatePermissionButtonStates() } } private fun updatePermissionButtonStates() { // 更新通知权限按钮状态 val isNotificationEnabled = NotificationManagerCompat.from(this).areNotificationsEnabled() button_A.text = "areNotificationsEnabled ( ${if(isNotificationEnabled) "On" else "Off"} )" // 更新悬浮窗权限按钮状态 val isCanDrawOverlays = Settings.canDrawOverlays(this) button_B.text = "canDrawOverlays ( ${if(isCanDrawOverlays) "On" else "Off"} )" }
该方案完全替代250ms轮询的实现,无额外性能损耗,覆盖所有你提到的异常场景。
内容的提问来源于stack exchange,提问作者Taha Sami
相关产品推荐
相关产品推荐

