Android notification manager TransactionTooLargeException

Viewed 802

I am using a foreground service with ongoing notification which updates very frequently.

When the service launches I initialize the notification manager with the notification builder and keep all the references.

The notification has custom layout with buttons. Each time the user presses a button I update the remote views and call the notificationManager.notify(service_id, notificationBuilderCompat.build()).

Eventually after many clicks I receive TransactionTooLargeException error with the size of the data parcel in bytes. Each notify() adds more bytes to this number.

What is the best approach to deal with this?

Demo of the code used:

class MyService: LifecycleService() {

var notificationBuilderCompat: NotificationCompat.Builder
var notificationManager: NotificationManager
var viewModel: ViewModel
val FOREGROUND_SERVICE = 10
val EXTRA_NOTIFICATION_TYPE = "EXTRA_NOTIFICATION_TYPE"
val NOTIFICATION_CHANNEL_ID = "channel_01"

override fun onCreate() {
    super.onCreate()

    // View model that holds the data
    viewModel = ViewModel()

    registerReceiver(broadcastReceiver, IntentFilter(NOTIFICATION_MESSAGE_INTENT)
    notificationManager = getSytemService(Context.NOTIFICATION_SERVICE) as NotificationManager

    // In case of android O
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        val channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, "notification_name", NotificationManager.IMPORTNACE_MAX)
        notificationManager.createNotificationChannel(channel)
    }

    notificationBuilderCompat = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL_ID)
}

ovveride fun onStartCommand(intent: Intent?, flags: Int, startId:Int): Int {

    // Received start notification command
    if (intent.action == START_FOREGROUND_ACTION) {
        setupNotification()
        viewModel.observerData.observe(this, Observer { data ->
            remoteViews.setTextViewText(R.id.notification_text, data)

            // This handles the update with the new data, and also where the exception happens
            notificationManager.notify(FOREGROUND_SERVICE, notificationBuilderCompat.build())
        })
    } else {
        stopForground(true)
        unregisterReceiver(broadcastReceiver)
        stopSelf()
    }
}

fun setupNotification() {
    remoteViews = RemoteViews(packageName, R.layout.item_notification)

    // Setting all the remote views here
    remoteViews.setImageViewResource(R.id.notification_app_icon, R.mipmap.ic_luancher)

    // Setting the click event
    val clickIntent = Intent(NOTIFICATION_MESSAGE_INTENT)
    clickIntent.putExtra(EXTRA_NOTIFICATION_TYPE, 1)
    val clickPendingIntent = PendingIntent.getBroadcast(this, 1, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT)
    remoteVies.setOnClickPendingIntent(R.id.notification_button, clickPendingIntent)

    notificationBuilderCompat.setContent(remoteViews)
        .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
        .setTicker("Notificaion on")
        .setCustomBigContentView(remoteViews)
        .setSmallIcon(R.drawable.icon)
        .setPriority(NotificationCompat.PRIORITY_MAX)
        .setOngoing(true)
        .setOnlyAlertOnce(true)
        .setDefaults(0)

    startForeground(FORGROUND_SERVICE, notificationBuilderCompat.build()
}

// This is the broadcast receiver class to handle the click on the notification button
val broadcastReceiver = object: BroadcastReceiver() {
    ovveride fun onReceive(context: Context?, intent: Intent?) {
        // Getting the notification type
        val notificationType = intent!!.getIntExtra(EXTRA_NOTIFICATION_TYPE, 0)

        if (notificationType == 1) {
            // Updating the data here which invokes the observer
            viewModel.updateData()
        }
    }
}

}

0 Answers
Related