Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Foreground Service Notification Delayed

Tags:

java

android

I've run into a peculiar issue with the app I am building (compile/target SDK 31, min SDK 24). I have a timer service that needs to run if the app/activity is no longer in the foreground. On the onPause of my activity I launch my service as such:

Intent serviceIntent = new Intent(activity, TimerService.class);
startService(serviceIntent);

The service launches perfectly fine as when I observe the console logs it is doing the proper calculations for calculating the remaining time.

The problem I have run into is that when the app first launches, or strangely enough if it has been idle for say 5+ minutes (usually idle in the background while I use other apps), when I first launch the service the first notification is delayed by upwards of 15 seconds. Since the service is indeed running, it's as if all the notification requests in those 15 seconds are being ignored by the phone because the first notification that appears will start at the right time (e.g. 45 seconds remaining if the timer is set to 1 minute).

The service looks like this:

    public static final int timerRunningId = 1;

    private Timer timer;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        startForeground(timerRunningId, timerRunningNotification("Timer starting..."));
        super.onCreate();
    }

    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                // timer logic, ignored for brevity but it would be calculate the timestamp needed for method below
                Notification notification = timerRunningNotification("dummyTimestamp");
                updateNotification(displayTime);
            }
        }, 0, 500);
        return START_REDELIVER_INTENT;
    }

    private void updateNotification(Notification notification ) {
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(timerRunningId, notification);
    }

    private Notification timerRunningNotification(String content) {
        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this,
                65, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
        return new NotificationCompat.Builder(this, Variables.TIMER_RUNNING_CHANNEL) // note i define this in my MainActivity according to the docs
                .setContentTitle("Timer")
                .setContentText(content)
                .setSmallIcon(R.drawable.notification_icon)
                .setSound(null)
                .setContentIntent(contentIntent)
                .setOnlyAlertOnce(true)
                .build();
    }

It was my understanding that the service would start in the onCreate() and initialize a notification with id=1 saying "Timer starting" and would immediately get replaced by the counting down timer notifications since the updateNotification method updates to the same id=1.

Since this bug only happens if the app first launched or has been idle for a while, I am having a hard time debugging what could be wrong. After the bug occurs I can use the timer perfectly and the moment the service starts the notification shows properly.

Anyone have any ideas as to what is happening? I wrote the code for this nearly two years ago so it's possible there is a better way of launching notifications, but from what I saw in the docs my updateNotification method should be valid.

The device I am testing this on is running Android 12, so I'm also curious if maybe it is only specific to certain devices (I don't ever remember seeing this bug in my version I released two years ago before Android 12)

like image 461
Jesse R Avatar asked Aug 24 '26 05:08

Jesse R


1 Answers

Add the method to NotificationCompat.Builder:

new NotificationCompat.Builder(...)
                .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)

From docs:

Devices that run Android 12 (API level 31) or higher provide a streamlined experience for short-running foreground services. On these devices, the system waits 10 seconds before showing the notification associated with a foreground service. There are a few exceptions; several types of services always display a notification immediately.

If a foreground service has at least one of the following characteristics, the system shows the associated notification immediately after the service starts, even on devices that run Android 12 or higher:

  • The service is associated with a notification that includes action buttons.
  • The service has a foregroundServiceType of mediaPlayback, mediaProjection, or phoneCall.
  • The service provides a use case related to phone calls, navigation, or media playback, as defined in the notification's category attribute.
  • The service has opted out of the behavior change by passing FOREGROUND_SERVICE_IMMEDIATE into setForegroundServiceBehavior() when setting up the notification.
like image 94
plplmax Avatar answered Aug 26 '26 22:08

plplmax