29

I'm currently creating a foreground service with a notification that appears in the notification bar when the service starts. If the service stops, the notification dismisses. My question is, is there a way to stop the service when "clear all notifications" or a dismiss of the notification (swipe) occurs?

Updated to include implementation of notification:

public int onStartCommand(Intent intent, int flags, int startId)
{   
    Log.d(CLASS, "onStartCommand service started.");

    if (getString(R.string.service_start_action) == intent.getAction())
    {
        Intent intentForeground = new Intent(this, ServiceMain.class)
            .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);    
        PendingIntent pendIntent = PendingIntent.getActivity(getApplicationContext(), 0, intentForeground, 0);      
        Notification notification;
        Notification.Builder builder = new Notification.Builder(getApplicationContext())
            .setSmallIcon(android.R.drawable.btn_star)
            .setTicker("Service started...")
            .setContentIntent(pendIntent)
            .setDefaults(Notification.DEFAULT_ALL)
            .setOnlyAlertOnce(true)
            .setOngoing(false);
        notification = builder.build();
        notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;

        startForeground(SERV_NOTIFY, notification);
        player.start();
    }
    else
    {
        Log.d(CLASS, "onStartCommand unable to identify acition.");
    }

    return START_STICKY;        
}
d.moncada
  • 16,900
  • 5
  • 53
  • 82
  • Have a look at this sample from Google: https://github.com/googlesamples/android-ActiveNotifications. It shows how to listen for a dismissed notification, as well as an entire group of notifications. – IgorGanapolsky Jul 08 '16 at 14:50
  • 1
    As far as I know you cannot 'create' a foreground service without creating a notification. Android requires this as they don't want you running services behind the scene without the user knowing it. Removing notification when your activity has been destroyed and your service running in foreground warrants a notification, you cannot just simply cancel it. Canceling the notification can only be done by canceling the foreground service itself via the call '.stopForeground(true)', the boolean parameter indicates whether you want to stop the foreground along with the notification. – Neon Warge Mar 09 '18 at 03:36

6 Answers6

38

The user is not allowed to swipe away a notification generated by an ongoing foreground service.

Hence, stopForeground(false) first, which allows the notification to be swiped away by the user thereafter (at least on Lollipop+). For pre-Lollipop, you may have to stopForeground(true), which stops foreground and removes the notification, then re-issue the notification with notificationManager.notify(yourNotificationID, yourNotificationObject), so that your notification is visible but swipeable.

Crucially, set up the notification object with a delete intent that is triggered when the user swipes it away.

(new NotificationCompat.builder(this).setDeleteIntent(deletePendingIntent)).build()

where deletePendingIntent is something like

Intent deleteIntent = new Intent(this, YourService.class);
deleteIntent.putExtra(someKey, someIntValue);
PendingIntent deletePendingIntent = PendingIntent.getService(this,
someIntValue, 
deleteIntent, 
PendingIntent.FLAG_CANCEL_CURRENT);

When the user swipes it away, the intent with its extra is delivered to the service. Handle the delivered extra within onStartCommand, i.e. check that intent != null, intent.getExtras() != null, then extract the value from the extras bundle given someKey, and if it matches someIntValue, then call stopSelf().

Vasily Kabunov
  • 6,511
  • 13
  • 49
  • 53
Kevin Lee
  • 2,307
  • 26
  • 31
  • 5
    I had to use startForeground(false) but I also had to remove the call to .setOngoing(true) from my NotificationBuilder code – caitcoo0odes Sep 01 '17 at 05:02
  • 1
    In Android 13 and above, the user can dismiss the notification even without calling `stopForeground` – Adam Burley Jul 13 '23 at 15:16
8

this code works for me:

this.stopForeground(false);
mNotificationManager.cancel(NOTIFY_ID);

and you should set your return value of onStartCommand, STRAT_STICKY will restart your service.

cmnewfan
  • 129
  • 1
  • 9
6

The notification of a foregraound service cannot be cleared. The only way is stopping the service.

So I beleive the issue you want to solve, will never happen.

Luis
  • 11,978
  • 3
  • 27
  • 35
5

My question is, is there a way to stop the service when "clear all notifications" or a dismiss of the notification (swipe) occurs?

Assuming that your Notification is set up to allow it to be cleared, the deleteIntent should be invoked when it is cleared. You could set this to a getBroadcast() PendingIntent, pointing to a manifest-registered BroadcastReceiver that calls stopService().

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • thanks, this was going to be my initial approach but once the service's notification is in the notification bar, there's no 'clear all notifications' button and the swipe to dismiss ability seems to be disabled. – d.moncada Oct 13 '12 at 20:02
  • @moncadad: Edit your question, post the code where you are creating the `Notification`, and comment back here to let me know that you posted it. – CommonsWare Oct 13 '12 at 20:04
  • 4
    @moncadad: Hmmm... Well, you're not setting `FLAG_NO_CLEAR`, and I do not see in the source where `Notification.Builder` is setting `FLAG_NO_CLEAR`, so Android must treat `FLAG_FOREGROUND_SERVICE` as implying `FLAG_NO_CLEAR`. BTW, you do not have to set `FLAG_FOREGROUND_SERVICE` yourself -- `startForeground()` does that for you, per the docs. I have always set `FLAG_NO_CLEAR` myself on these, and I assumed (incorrectly, apparently) that leaving it off would result in a normal `Notification`, one where you might lose foreground privileges if the user cleared you. – CommonsWare Oct 13 '12 at 21:24
  • 1
    Thanks for the help, so it looks like that this behavior is not allowed per service notification. I think I will add a "dismiss" button within the notification itself to stop the service. – d.moncada Oct 13 '12 at 21:47
  • @moncadad: Last I checked, buttons are not supported in the notification itself, the exception being the actions in the "big" styles introduced in Android 4.1. – CommonsWare Oct 13 '12 at 22:01
  • @CommonsWare Will the deleteIntent actually be called for foreground service notification ? If so, is it possible to be notified about it only if the user has dismissed it alone, and not when using the clear-all-notifications action ? – android developer Aug 20 '18 at 14:33
  • @androiddeveloper: "Will the deleteIntent actually be called for foreground service notification ?" -- I have never tried it. Usually I set my foreground service notifications to be ongoing, so they are not individually dismissable. – CommonsWare Aug 20 '18 at 21:30
  • @CommonsWare It's possible to avoid having the foreground service notification to be dismissable by not setting it as ongoing, or even set it to false? – android developer Aug 21 '18 at 05:21
  • @androiddeveloper: Sorry, but I am having difficulty parsing that question. – CommonsWare Aug 21 '18 at 10:51
  • @CommonsWare OK. I will explain in other way: For a foreground service that you start, is it possible to let users dismiss its notification just like normal notificaitons? Is it possible to use "ongoing" for this, by setting its value to "false" ? According to my tests, it's impossible, but maybe you've found a way. – android developer Aug 21 '18 at 17:09
  • @androiddeveloper: I have not experimented with that, sorry. – CommonsWare Aug 21 '18 at 18:55
0

There is a dismissIntent you can set in the notification you create, though I thought foreground Service notifications cannot be cleared?

dnkoutso
  • 6,041
  • 4
  • 37
  • 58
0

I did the following and it worked for me:

  1. I created a notification before calling the foreground service with by same id and Notification Channel which are used with foreground service's notification

  2. I canceled the notification by the notification id

  3. I created another notification with your required structure

  4. You can dismiss or swipe this last notification without stop your foreground service

sɐunıɔןɐqɐp
  • 3,332
  • 15
  • 36
  • 40
abdo
  • 1
  • 1