Android中如何检测应用通知开关状态的变化?
检测应用通知权限开关状态变化的问题解决
问题描述
我正在寻找一种检测用户开启/关闭我的应用通知的方法。尝试了以下代码,但监听器并未触发,尽管OP值确实发生了变化:
val appOpsManager: AppOpsManager = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager appOpsManager.startWatchingMode("android:post_notification", context.packageName) { op, _ -> Log.d("foo", "$op value changed") }
原因分析及解决方案
1. 优先使用NotificationManager的官方监听方案
从Android 10(API 29)开始,AppOpsManager.startWatchingMode针对通知权限的监听触发逻辑被限制,推荐使用NotificationManager提供的专用监听接口,兼容性和可靠性更强:
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val permissionChangeListener = object : NotificationManager.OnNotificationPolicyChangedListener { override fun onNotificationPolicyChanged() { val isEnabled = notificationManager.areNotificationsEnabled() Log.d("foo", "通知权限状态变化:${if (isEnabled) "已开启" else "已关闭"}") } } // 注册监听 notificationManager.addOnNotificationPolicyChangedListener(permissionChangeListener) // 注意:在页面销毁或不再需要监听时,务必移除监听 // notificationManager.removeOnNotificationPolicyChangedListener(permissionChangeListener)
2. 修复AppOpsManager监听的问题
如果坚持使用AppOpsManager,需要注意几个关键点:
- 使用官方常量替代硬编码字符串,避免拼写错误:
AppOpsManager.OP_POST_NOTIFICATION - 部分系统版本需要声明
android.permission.OBSERVE_APP_OPS权限 - 部分厂商定制系统可能拦截AppOps监听事件,需做好兼容
修改后的代码:
val appOpsManager: AppOpsManager = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager appOpsManager.startWatchingMode(AppOpsManager.OP_POST_NOTIFICATION, context.packageName) { _, _ -> val mode = appOpsManager.checkOpNoThrow(AppOpsManager.OP_POST_NOTIFICATION, android.os.Process.myUid(), context.packageName) val isEnabled = mode == AppOpsManager.MODE_ALLOWED Log.d("foo", "通知权限变化:$isEnabled") }
3. Android 12+ 可用的广播监听方案
Android 12(API 31)及以上系统支持通过动态注册广播监听通知设置变化:
val settingChangeReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (Intent.ACTION_APP_NOTIFICATION_SETTINGS_CHANGED == intent?.action) { val targetPackage = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME) if (targetPackage == context?.packageName) { val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val isEnabled = notificationManager.areNotificationsEnabled() Log.d("foo", "通知权限状态更新:${if (isEnabled) "开启" else "关闭"}") } } } } // 动态注册广播(静态注册无效) context.registerReceiver(settingChangeReceiver, IntentFilter(Intent.ACTION_APP_NOTIFICATION_SETTINGS_CHANGED)) // 记得在合适时机注销广播 // context.unregisterReceiver(settingChangeReceiver)
内容的提问来源于stack exchange,提问作者Marek Teuchner
相关产品推荐
相关产品推荐

