Search code examples
androidmultithreadingandroid-serviceandroid-notificationsandroid-notification-bar

Android Service Multiple Threads and startForeground()


I have a Service that facilitates the downloading of files from a server. Everytime an Intent is received in onStartCommand, I start a new Thread, put the Thread into a map with the url being downloaded as the key, and create a notification to show the progress of the download. If there are no Threads in the map, a flag is set in the Thread that signifies that it should use startForeground when the Notificationis being created or updated. Subsequent Threads/Notifications are show using NotificationManager.notify with the FLAG_AUTO_CANCEL off and the FLAG_ONGOING_EVENT on. Each Thread has its own unique id that is sent to startForeground or notify. When the file is finished downloading, or the user cancels the download (by pressing a button in the Notification's RemoteView, if it is the "foreground thread/notification," stopForeground(true) is called, the Notification is populated with a new RemoteView that shows whether the download completed or not, and the next running Thread has its "foreground" flag set to true.

The problem is, if I have, let's say, two files downloading, there will be one Notification/Thread that is connected to startForeground and one that is not. If I cancel the "foreground" one, everything is fine. However, if I press the cancel button on the non-foreground one, the foreground one is dismissed (and pressing the cancel button again will then dismiss the proper one). If I don't cancel any, and I start a 3rd download that completes before the others, the completed Notification shows, but the other two that are still going start to blink and rapidly move up and down in the status bar.

How do I make sure that the Service will always be in the foreground as long as there are downloads going on, without the notifications jumping around in the situation noted above, and with the cancelling working properly?


Solution

  • What I ended up doing was making a variable in the Service called isInForeground that is global to all of the Threads. It signifies whether startForeground has been called, without a subsequent call to stopForeground.

    In my updateNotification method, I check isInForeground. If it is false I set it to true, set the Thread's isForegroundNotification flag to true, and call startForeground with that Thread's Notification. In my stopNotification method, if the Thread's isForegroundNotification is true, I set it and isInForeground to false and call stopForeground(true).