Android通知拦截APP问题:如何实现类似focused mode的通知拦截与恢复显示?
解决方案
要实现彻底拦截通知且后续可恢复显示的功能,推荐基于Android官方提供的NotificationListenerService来实现,以下是具体步骤:
核心实现:NotificationListenerService拦截与恢复
这是Android系统专门用于监听、拦截和处理通知的服务,能精准控制通知的显示与存储,适配绝大多数Android版本。配置权限与服务声明
在AndroidManifest.xml中添加必要权限并注册服务:<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" /> <uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" /> <service android:name=".NotificationBlockerService" android:label="通知拦截服务" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> <intent-filter> <action android:name="android.service.notification.NotificationListenerService" /> </intent-filter> </service>注意:首次启动应用时,需引导用户前往系统设置开启"通知访问权限",否则服务无法正常工作。
拦截通知并隐藏显示
自定义NotificationListenerService子类,重写onNotificationPosted方法,在通知发布时直接移除它,同时将通知关键数据存入数据库:@Override public void onNotificationPosted(StatusBarNotification sbn) { super.onNotificationPosted(sbn); // 读取拦截开关状态(需自行实现,比如从SharedPreferences获取) if (isBlockingModeActive()) { // 立即移除通知,阻止其显示在状态栏 cancelNotification(sbn.getKey()); // 将通知的包名、标题、内容、通知ID、渠道ID等信息存入数据库 saveNotificationToDatabase(sbn); } }恢复已拦截的通知
当用户关闭拦截模式时,从数据库取出保存的通知数据,通过NotificationManager重新发布:private void restoreStoredNotifications() { NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); List<StoredNotification> savedNotifications = getSavedNotificationsFromDB(); for (StoredNotification notification : savedNotifications) { NotificationCompat.Builder builder = new NotificationCompat.Builder(this, notification.getChannelId()) .setContentTitle(notification.getTitle()) .setContentText(notification.getContent()) .setSmallIcon(R.drawable.ic_default_notification) .setPriority(NotificationCompat.PRIORITY_DEFAULT); // 使用原通知ID发布,确保恢复后的通知与原通知逻辑一致 notificationManager.notify(notification.getNotificationId(), builder.build()); } // 可选择清空已恢复的通知记录,或标记为已恢复 clearRestoredNotificationsInDB(); }
简化方案:系统级通知策略(API 24+)
若只需要全局拦截所有非关键通知(类似系统专注模式),可使用NotificationManager的通知策略API,适合快速实现全局拦截,但无法单独保存恢复特定通知:NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 仅允许闹钟通知,拦截其他所有通知 NotificationPolicy policy = new NotificationPolicy( NotificationPolicy.PRIORITY_CATEGORY_ALARMS, 0, 0 ); notificationManager.setNotificationPolicy(policy); }取消拦截时重置策略即可:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { notificationManager.setNotificationPolicy(new NotificationPolicy()); }
内容的提问来源于stack exchange,提问作者Ethan Rodrigo
相关产品推荐
相关产品推荐

