How to update progress in notification without notification icon blinking?

681 views Asked by At

In my Android application i am downloading files inside a Foreground Service. Before starting downloading i am displaying a notification with 0 progress and then updating the progress in NotificationBuilder. The issue i am facing is Notification small icon keeps blinking when progress is updated in NotificationBuilder even though i am reusing the same NotificationBuilder. I have also set setOngoing=true but this is not working, tried setting setOnlyAlertOnce=true as well.

Below is my code

import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.annotation.Nullable
import androidx.core.app.NotificationCompat
import com.downloader.OnDownloadListener
import com.downloader.PRDownloader
import java.util.*


class ForegroundService() : Service() {
    val testPathDir = "/storage/emulated/0/MyAppFolder”
    val testVideoLink =
        "https://scontent.fisb6-2.fna.fbcdn.net/v/t66.36240-6/121382477_483887163110055_1614404568115456703_n.mp4?_nc_cat=104&ccb=1-5&_nc_sid=985c63&efg=eyJ2ZW5jb2RlX3RhZyI6Im9lcF9zZCJ9&_nc_ohc=hxnnGTvs10gAX_4BaOw&_nc_ht=scontent.fisb6-2.fna&oh=00_AT9SCG-m8bEJsfsyFNKQEZZFcG7JdiNcL05cZjoPekq1Eg&oe=621C0873"
    private val notificationManager =
        MyApplication.applicationContext()
            .getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    private var totalProgress = 0L
    private var maxProgress = 100

    override fun onCreate() {
        super.onCreate()
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        val notificationId: Int = intent.getIntExtra("notificationId", 0)
        val channelId =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                createNotificationChannel(
                    "my_service123", "My Background Service124",
                    NotificationManager.IMPORTANCE_HIGH,
                    MyApplication.applicationContext()
                )
            } else {
                "my_service123"
            }

        val notificationBuilder = NotificationCompat.Builder(
            MyApplication.applicationContext(),
            channelId
        )
        notificationBuilder
            .setContentTitle("Downloading")
            .setTicker("Downloader")
            .setSmallIcon(R.drawable.ic_icon_1_copy_2)
            .setOngoing(true)
            .setProgress(100, 0, false)
            .build()

        startForeground(notificationId, notificationBuilder.build());
        notificationManager.notify(notificationId, notificationBuilder.build())

        //do heavy work on a background thread
        downlaodVideo(notificationId, notificationBuilder)
        return START_NOT_STICKY
    }

    override fun onDestroy() {
        super.onDestroy()
    }

    @Nullable
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }
    
    private fun updateNotification(
        notificationId: Int,
        currentProgress: Int,
        notificationBuilder: NotificationCompat.Builder
    ) {
        notificationBuilder.setProgress(maxProgress, currentProgress, false)
        notificationManager.notify(notificationId, notificationBuilder.build())

    }

    private fun downlaodVideo(
        notificationId: Int,
        notificationBuilder: NotificationCompat.Builder
    ) {
        val testFileName = Random(System.currentTimeMillis()).nextInt(1000).toString() + ".mp4"
        PRDownloader.download(testVideoLink, testPathDir, testFileName.toString())
            .build()
            .setOnStartOrResumeListener {
                Thread.sleep(150)
            }
            .setOnPauseListener { }
            .setOnCancelListener { }
            .setOnProgressListener {
                totalProgress = it.totalBytes
                val currentProgress = (it.currentBytes * 100 / totalProgress).toInt()
                updateNotification(notificationId, currentProgress, notificationBuilder)
            }


            .start(object : OnDownloadListener {
                override fun onDownloadComplete() {
                    val doneNotifId = Random(System.currentTimeMillis()).nextInt(1000)
                    showNotification(
                        MyApplication.applicationContext(),
                        doneNotifId,
                        "test",
                        "mp4",
                        testVideoLink
                    )
                    stopForeground(true)
                }

                override fun onError(error: com.downloader.Error?) {
                    val errMsg = error?.serverErrorMessage
                }

            })
    }
}

Can somebody please help me out with this? Any help will be appreciated.

Thank you

1

There are 1 answers

1
Manohar On

Try adding .setOnlyAlertOnce(true) to the notification builder

notificationBuilder
        .setContentTitle("Downloading")
        .setTicker("Downloader")
        .setSmallIcon(R.drawable.ic_icon_1_copy_2)
        .setOngoing(true)
        .setOnlyAlertOnce(true)
        .setProgress(100, 0, false)
        .build()

See the documentation

You can optionally call setOnlyAlertOnce() so your notification interupts the user (with sound, vibration, or visual clues) only the first time the notification appears and not for later updates.