javaandroidkotlinnotificationsicons

How to Retrieve the Icon of a System Notification (e.g., "Do Not Disturb") from StatusBarNotification in Android?


I am trying to retrieve the icon displayed in a system notification, such as "Do Not Disturb turned on," using NotificationListenerService. The notification comes from the package com.android.systemui.

What I've Tried: Extracting the smallIcon and largeIcon:

// Extract large icon
val largeIcon = notification.getLargeIcon()

// Extract small icon
val smallIcon = notification.smallIcon

largeIcon is null. smallIcon is not null, but it contains a very basic black icon that is different from the actual icon displayed in the notification list. On my phone, the displayed icon is white on a blue background.

Question:

  1. Which field in the StatusBarNotification or Notification object contains the icon displayed in the system notification list (white on blue background for "Do Not Disturb")?
  2. How can I retrieve this icon and convert it into a Drawable, Bitmap, or Icon?

Additional Information:

  1. The package name of the notification is "com.android.systemui".
  2. The icon of the com.android.systemui package is not the same as the "Do Not Disturb" notification icon.
  3. My app has permissions for NotificationListenerService and UsageStats.

Any guidance on how to retrieve and display the actual notification icon would be greatly appreciated!


Solution

  • I ended up with creating app icon from small icon, using shape of my own app icon, so it will be default android shape:

        fun appIconBitmapFromSmallIcon(smallIcon: Icon): Bitmap {
            return try {
                // Load the small icon as a Drawable
                val smallIconDrawable = smallIcon.loadDrawable(applicationContext)
                val smallIconBitmap = smallIconDrawable?.let { getBitmapFromDrawable(it) }
    
                if (smallIconBitmap == null) {
                    return noImageBitmap
                }
    
                // Create a blue background that matches the app icon shape
                val size = 256 // Adjust to the desired icon size
                val appIconBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
                val canvas = Canvas(appIconBitmap)
    
                // Draw the app icon shape on the canvas
                val appIconShapeBitmap = getAppIconShapeBitmap(Color.rgb(23, 109, 238), size)
                canvas.drawBitmap(appIconShapeBitmap, 0f, 0f, null)
    
                // Convert small icon to white and scale it to fit in the center
                val whiteSmallIconBitmap = convertBitmapToWhite(smallIconBitmap)
                val overlaySize = size / 2 // Adjust size relative to the background
                val scaledSmallIcon = Bitmap.createScaledBitmap(
                    whiteSmallIconBitmap,
                    overlaySize,
                    overlaySize,
                    true
                )
                val left = (size - overlaySize) / 2
                val top = (size - overlaySize) / 2
    
                // Draw the small icon on top of the blue background
                canvas.drawBitmap(scaledSmallIcon, left.toFloat(), top.toFloat(), null)
    
                appIconBitmap
            } catch (e: Exception) {
                logger.error(e, "Failed to create app icon image")
                noImageBitmap
            }
        }
    
        // Helper method to convert Drawable to Bitmap
        private fun getBitmapFromDrawable(
            drawable: Drawable,
            width: Int? = null,
            height: Int? = null
        ): Bitmap {
            val finalWidth = width ?: drawable.intrinsicWidth
            val finalHeight = height ?: drawable.intrinsicHeight
            if (drawable is BitmapDrawable) {
                if (width == null && height == null) {
                    return drawable.bitmap
                } else {
                    return Bitmap.createScaledBitmap(drawable.bitmap, finalWidth, finalHeight, false)
                }
            }
            val bitmap = Bitmap.createBitmap(finalWidth, finalHeight, Bitmap.Config.ARGB_8888)
            val canvas = Canvas(bitmap)
            drawable.setBounds(0, 0, canvas.width, canvas.height)
            drawable.draw(canvas)
            return bitmap
        }
    
        // Helper method to convert a Bitmap to white
        private fun convertBitmapToWhite(bitmap: Bitmap): Bitmap {
            val result = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
            val canvas = Canvas(result)
            val paint = Paint(Paint.ANTI_ALIAS_FLAG)
            paint.colorFilter = PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)
            canvas.drawBitmap(bitmap, 0f, 0f, paint)
            return result
        }
    
        // Helper method to get the app icon shape as a Bitmap
        private fun getAppIconShapeBitmap(color: Int, size: Int): Bitmap {
            // Get the current app icon as a Drawable
            val currentAppIconDrawable: Drawable =
                applicationContext.packageManager.getApplicationIcon(applicationContext.packageName)
    
            // Convert the Drawable to a Bitmap
            val bitmap = getBitmapFromDrawable(currentAppIconDrawable, size, size)
    
            // Create a new Bitmap to paint the icon in white
            val whiteBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
            val canvas = Canvas(whiteBitmap)
            val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    
            // Apply the desired color filter (white in this case)
            paint.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)
    
            // Draw the original icon onto the canvas with the white paint
            canvas.drawBitmap(bitmap, 0f, 0f, paint)
    
            return whiteBitmap
        }