Unable to read Gmail and system app notifications with NotificationListenerServic

I’m building an Android app that includes a feature for logging all incoming notifications on the device. To capture these notifications, I’m using NotificationListenerService, and for persistent storage, I’m utilizing Room Database. For the most part, this implementation works well — the app is able to read and store notifications from a variety of apps successfully.

However, I’m encountering issues specifically with some apps like Gmail, Pinterest, and a few other Google-related apps. Notifications from these apps are either incomplete or not processed correctly, even though other apps work just fine. Here’s a snippet from the code handling the notifications:

override fun onNotificationPosted(sbn: StatusBarNotification?) {
    super.onNotificationPosted(sbn)

    CoroutineScope(Dispatchers.IO).launch {
        val notification = sbn?.notification ?: return@launch

        // Skip notifications from our own app
        if (sbn.packageName == packageName) return@launch

        // Ignore ongoing notifications from foreground services
        if ((notification.flags and Notification.FLAG_FOREGROUND_SERVICE) != 0) return@launch

        val extras = notification.extras

        val packageName = sbn.packageName
        val appName = packageName?.let { packageManager.getApplicationInfo(it, 0) }?.let {
            packageManager.getApplicationLabel(it)
        }.toString()
        val title = extras?.getString(Notification.EXTRA_TITLE) ?: ""
        val text = extras?.getString(Notification.EXTRA_TEXT) ?: ""
        val bigText = extras?.getString(Notification.EXTRA_BIG_TEXT) ?: ""
        val subText = extras?.getString(Notification.EXTRA_SUB_TEXT) ?: ""
        val category = packageName?.let { getCategory(it) }.toString()
        val postTime = System.currentTimeMillis()
        val isRead = false

        val imageKey = generateImageKey(packageName, title)

        val largeIconPath = getExistingImagePath(imageKey)
            ?: handleLargeIcon(extras, imageKey)

        Log.d("NotificationCapture", "App: $appName, Title: $title, Text: $text, BigText: $bigText, SubText: $subText")

        val style = extras.getString("android.template")
        Log.d("NotificationStyle", "Template Style: $style")

        saveToDatabase(
            packageName,
            appName,
            title,
            text,
            bigText,
            subText,
            category,
            postTime,
            largeIconPath,
            isRead
        )
    }
}

Now, although this function successfully retrieves and stores notification data from most third-party apps, it struggles with some system-level or protected apps. Notifications from Gmail and other Google apps either return empty EXTRA_TEXT or are missing vital fields, which makes it impossible to log the full content.

Has anyone run into this limitation and figured out a workaround? Is there any method or pattern to better extract full notification details from system apps like Gmail, without breaching platform restrictions or requiring root?

Any advice or direction would be super helpful. Thanks in advance!

1 Like