Android 13: User can dismiss notification even after setting "setOnGoing(true)"
Asked Answered
E

2

7

I am making a foreground service and as we know that such services need a notification to keep running. However since Android 13, the user can dismiss it just by swiping, thus the app is killed.

I tried to use setOnGoing(true) on the notification builder but no use.

I need to make the notification non-dismissable.

This is my code in Kotlin .

      private fun startForegroundServiceWithNotification() {
        Log.d("myTag", "startForegroundServiceWithNotification")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channelId = CHANNEL_ID
            val channelName = "Wish2Go step counter"
            val chan = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
            val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            service.createNotificationChannel(chan)
        }


        var builder = NotificationCompat.Builder(this, CHANNEL_ID)
            .setOngoing(true)
            .setContentTitle("Counting steps")
            .setPriority(NotificationCompat.PRIORITY_HIGH)

        var notification = builder.build()
        notification.flags = Notification.FLAG_ONGOING_EVENT
        startForeground(1001, notification)

    }
Eight answered 24/2, 2023 at 22:42 Comment(5)
"as we know that such services need a notification to keep running" - that is not a requirement in Android 13. What makes you think it is?Meilhac
@Meilhac first line in the documentation "Foreground services perform operations that are noticeable to the user. Foreground services show a status bar notification, to make users aware that your app is performing a task in the foreground and is consuming system resources."Eight
@AhmadElMadi Please refer to this answer and check if this is working for you. Prevent user from dismissing notification Also there is a bug on android 13 about this. They say's it will be fixed in future updates. Able to dismiss foreground service notification on android 13Gaby
@Gaby I just did , but no use . I still can dismiss it . Edited the snippit above.Eight
@Gaby Thanks , I hope they will fix it soon .Eight
E
2

I found the issue i had, apparently that i forgot to set the smallIcon for my notification

private fun startForegroundServiceWithNotification() {
    Log.d("myTag", "startForegroundServiceWithNotification")
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channelId = CHANNEL_ID
        val channelName = "Wish2Go step counter"
        val chan = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
        val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        service.createNotificationChannel(chan)
    }


    var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setOngoing(true)
        .setContentTitle("Counting steps")
        .setContentText("Open the app to see how are you doing.")
        .setSmallIcon(R.mipmap.ic_launcher_round) //Missing this was the issue 
        .setPriority(NotificationCompat.PRIORITY_HIGH)

    var notification = builder.build()
    notification.flags = Notification.FLAG_ONGOING_EVENT
    startForeground(1001, notification)

}

After setting the small Icon the notification acted as expected .

Eight answered 26/2, 2023 at 23:51 Comment(0)
D
2

I have a similar foreground service in an app I made. In my app, I update the notification every second using a timer, because my app displays a countdown timer as part of the notification. If the user has dismissed the notification, it reappears after one second. Maybe you can try something similar with your app.

I'd try creating a thread with an infinite loop that sleeps for one second and then refreshes the notification. This is in Java, but you get the idea.

// init and build notification, same as before 
notification = builder.build();

// create a notification manager
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

// infinite loop with a 'kill switch' for when the user manually stops the service from the app
new Thread(new Runnable() {
    @Override
    public void run() {
        while(!killSwitch) {
            try {
                Thread.sleep(1000);  // sleep for one second

                /* make sure the first parameter here matches the id you defined when 
                   you initialized the notification */
                notificationManager.notify(1001, builder.build());

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}).start();
Distillery answered 25/2, 2023 at 8:14 Comment(5)
Sorry, just realized the while loop should go inside the thread, otherwise it'll try to generate a bunch of new threads. Updated.Distillery
Thanks, but would it run after killing the app and dismiss the notification , I am not so confident with Android apps lifecycleEight
Right, so you will have to send a broadcast from your app to the service with the kill switch if the user stops the app. The main activity in the app will send a broadcast with the kill switch, and the service activity will have a broadcast receiver that listens for the kill switch. See Broadcasts overview for more info. There are a number of good tutorials online as well. Good luck!Distillery
Hi Rob , thanks for your help , but i think i found the issue. The problem was that I did not set the small icon for the notification . once that is set then its all good . one thing though , the icon seems too small though .Eight
Nice, well that's a much easier fix than what I thought you'd have to do! Interesting that the icon was the issue.Distillery
E
2

I found the issue i had, apparently that i forgot to set the smallIcon for my notification

private fun startForegroundServiceWithNotification() {
    Log.d("myTag", "startForegroundServiceWithNotification")
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channelId = CHANNEL_ID
        val channelName = "Wish2Go step counter"
        val chan = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
        val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        service.createNotificationChannel(chan)
    }


    var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setOngoing(true)
        .setContentTitle("Counting steps")
        .setContentText("Open the app to see how are you doing.")
        .setSmallIcon(R.mipmap.ic_launcher_round) //Missing this was the issue 
        .setPriority(NotificationCompat.PRIORITY_HIGH)

    var notification = builder.build()
    notification.flags = Notification.FLAG_ONGOING_EVENT
    startForeground(1001, notification)

}

After setting the small Icon the notification acted as expected .

Eight answered 26/2, 2023 at 23:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.