如何获取Android通知日志中的通知数据并在应用中处理展示
如何在Android应用中访问并处理通知日志数据
嘿,我来帮你一步步搞定获取通知日志数据并展示的问题!Android系统在不同版本提供了不同的API来实现这个需求,我会分情况给你讲清楚:
1. 先搞定权限问题
权限是第一步,不同版本的要求不一样:
- Android 11(API 30)及以上:需要
READ_NOTIFICATION_HISTORY权限,这个权限没法通过常规的权限弹窗申请,得引导用户去系统设置里开启。 - Android 10及以下:需要开启「通知监听」权限,同样得跳转到系统设置让用户手动开启。
2. 获取通知历史数据
方案一:Android 11+ 用官方API直接拿
从API 30开始,系统给了NotificationManager.getNotificationHistory()这个便捷方法,能直接获取最近的通知记录(系统限制最多500条)。
先检查权限,没有的话跳设置:
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (!notificationManager.isNotificationHistoryAccessGranted) { // 跳转到通知历史权限设置页 startActivity(Intent(Settings.ACTION_NOTIFICATION_HISTORY_SETTINGS)) return } }
然后就能拿到数据了,每条通知里包含你要的所有信息:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val notificationHistory = notificationManager.notificationHistory notificationHistory.forEach { notification -> // 提取你需要的字段 val appPackage = notification.packageName // 发送通知的应用包名 val isOpened = notification.isNotificationOpened // 是否已被用户打开 val postTimestamp = notification.postTime // 通知到达时间(毫秒时间戳) val title = notification.extras.getString(Notification.EXTRA_TITLE) // 通知标题 val content = notification.extras.getString(Notification.EXTRA_TEXT) // 通知内容 // 这里可以把数据存到本地数据库,或者直接用于UI展示 } }
方案二:Android 10及以下 用NotificationListenerService
低版本没有直接的API,得靠通知监听服务来捕获通知,同时记录状态。
第一步:注册服务
在AndroidManifest.xml里添加服务声明:
<service android:name=".MyNotificationListener" android:label="我的通知日志监听" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> <intent-filter> <action android:name="android.service.notification.NotificationListenerService" /> </intent-filter> </service>
第二步:实现监听服务
创建一个继承自NotificationListenerService的类,监听通知的发布和移除事件:
class MyNotificationListener : NotificationListenerService() { // 新通知发布时触发,在这里记录通知基本信息 override fun onNotificationPosted(sbn: StatusBarNotification) { super.onNotificationPosted(sbn) val appPackage = sbn.packageName val postTimestamp = sbn.postTime val title = sbn.notification.extras.getString(Notification.EXTRA_TITLE) val content = sbn.notification.extras.getString(Notification.EXTRA_TEXT) // 把这些信息存到本地(比如Room数据库),初始标记为未打开 } // 通知被移除时触发,判断是否是用户打开导致的 override fun onNotificationRemoved(sbn: StatusBarNotification, rankingMap: RankingMap?, reason: Int) { super.onNotificationRemoved(sbn, rankingMap, reason) if (reason == NotificationListenerService.REASON_CLICK) { // 通知被用户点击打开了,更新本地数据的状态为已打开 val appPackage = sbn.packageName val postTimestamp = sbn.postTime // 这里根据包名和时间戳找到对应的记录,更新isOpened字段 } } // 如果需要获取当前活跃的通知(历史通知的一部分),可以调用这个方法 fun getActiveNotifications(): List<StatusBarNotification> { return activeNotifications.toList() } }
第三步:引导用户开启权限
让用户跳转到通知监听设置页开启权限:
fun openNotificationListenerSettings() { startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS")) }
3. 数据处理与UI展示
拿到数据后,接下来就是处理和展示了:
- 存储数据:推荐用Room数据库来存储通知记录,方便后续查询、排序(比如按时间倒序)。
- 展示UI:用RecyclerView来列表展示每条通知,你还可以根据包名获取应用的图标和名称,让界面更友好:
fun getAppInfo(packageName: String): Pair<Drawable?, String> { val packageManager = packageManager return try { val appInfo = packageManager.getApplicationInfo(packageName, 0) val appIcon = packageManager.getApplicationIcon(appInfo) val appName = packageManager.getApplicationLabel(appInfo).toString() Pair(appIcon, appName) } catch (e: PackageManager.NameNotFoundException) { // 找不到应用信息时,用包名代替名称,图标用默认图 Pair(null, packageName) } }
一些关键注意事项
- Android 11+的
getNotificationHistory()只能拿到最近的500条通知,系统会自动清理旧记录,所以如果需要长期保存,得自己存到本地。 - 通知监听服务在设备重启后会被禁用,你可以监听开机广播,然后引导用户重新开启权限。
- 隐私合规很重要!一定要在应用里明确告知用户你为什么需要获取通知数据,符合Google Play的隐私政策,不然容易被下架。
内容的提问来源于stack exchange,提问作者Manas Kulkarni




