Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListenableWorker does not remove notification icon

I am using ListenableWorker to perform background tasks. Also I want OS to be aware of my service importance, so I call

 setForegroundAsync(new ForegroundInfo(WorkerConstants.NOTIFICATION_FOREGROUND_ID,
 builder.build()));

As suggested in the google documentation.

But when my service stopped or cancelled, i can still see foreground service notification and i cannot remove it.

Furthermore, I added cancel button to this notification, but it does nothing, I cannot close it:

PendingIntent intent = WorkManager.getInstance(getApplicationContext())
                            .createCancelPendingIntent(getId());
                    builder.addAction(R.drawable.ic_redesign_exit,"Stop",intent);

Any suggestions?

like image 771
Sergei Yendiyarov Avatar asked Mar 05 '20 08:03

Sergei Yendiyarov


People also ask

How does a listenableworker work?

A ListenableWorker only signals when the work should start and stop and leaves the threading entirely up to you. The start work signal is invoked on the main thread, so it is very important that you go to a background thread of your choice manually. The abstract method ListenableWorker.startWork () returns a ListenableFuture of the Result.

How to fix Action Center not showing notifications?

Go back to the settings page, previously mentioned in step 1 and 2.Toggle the ‘Let apps run in the background’ switch to on, as described in Step 2.Restart once again. Action Center is now showing notifications. As well as the "Safe to remove" pop-up for flash drives without issues.

How to remove redundant icons from the notification areas?

Although those redundant icons won’t appear in either the main or hidden notification areas, it’s recommended to remove them if there a number of unused entries. There is no way to remove anything through the select icons window and it has to be done manually. Here are 6 ways in which you can do it.

Why are all the notification area icons missing from my Window?

The main issue with the window that lists all the notification area icons is unused or even uninstalled software can leave entries behind and it can get a bit messy. Although those redundant icons won’t appear in either the main or hidden notification areas, it’s recommended to remove them if there a number of unused entries.


Video Answer


2 Answers

I filed an issue to google tracker with this. And found out that was totally worng.

Official response as follows:

Looking at your sample app, you are introducing a race between completion of your ListenableFuture returned by CallbackToFutureAdaptor, and the main looper.

Even without the use of REPLACE one of your Notification updates is posted after your Worker is marked as successful.

However, you can actually avoid the race condition by waiting for the call to setForegroundAsync() to be completed (because that also returns a ListenableFuture). Once you do that - you never have a notification that shows up after your Worker is done.

I will also go ahead and file an improvement on how we can automatically do this even when developers get this wrong.

try {
    // This ensures that you waiting for the Notification update to be done.
    setForegroundAsync(createForegroundInfo(0)).get();
} catch (Throwable throwable) {
    // Handle this exception gracefully
    Log.e("FgLW", "Something bad happened", throwable);
}
like image 178
Sergei Yendiyarov Avatar answered Nov 10 '22 00:11

Sergei Yendiyarov


If you have some branch that can end worker immedietaly - add 1 second delay for notification to propagate. setForeground claims to be synchronous, but it's clearly not - there's always time notification needs to show. And calling cancel on not shown notification does nothing. It's clearly a race condition, one not handled by google (i'm not even sure if that can be handled by app).

Extended explanation:

I have code that in single scenario can return immediately. Worker looks like that:

setForeground(getForegroundInfo())
loggingRepository.uploadLogs()

That's it, could not be simpler. BUT, logging repository have this check on start:

if (!userIdentity.isLoggedIn) return

So if user is not loggedIn - do nothing. And if this scenario happend - notification just stayed on. The only thing i had to do is to add delay like that (it's a CoroutineWorker)

setForeground(getForegroundInfo())
loggingRepository.uploadLogs()
delay(1000)
like image 20
Jakoss Avatar answered Nov 10 '22 00:11

Jakoss