Search code examples
androidmultithreadingnotificationsandroid-notificationsandroid-pendingintent

Cancel button on Notification to remove Notification


I have a Notification that has a Progress Bar and a Cancel button. I am using Thread to increment the Progress Bar and the Cancel button is supposed to clear the notification.

Here's the code for Notification

    remoteViews = new RemoteViews(getPackageName(), R.layout.customnotification);
    Intent intent = new Intent(this, LocationBroadcastReceiver.class);
    intent.putExtra("CancelServiceAndNotification","CancelServiceAndNotification");
    intent.putExtra("ID",1);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(),
       0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    remoteViews.setOnClickPendingIntent(R.id.bCancel, pendingIntent);

Code for incrementing Progress Bar using Thread

     thread = new Thread(new Runnable() {
        @Override
        public void run() {
            int incr;
            for(incr = 0;incr<=100;incr+=10){
                remoteViews.setProgressBar(R.id.progressBar, 100, incr, false);
                if(cancelNotification){

                }
                notificationManager.notify(1,notification);
                try{
                    Thread.sleep(1000);
                }
                catch (Exception e){

                }

            }
            notificationManager.cancel(1);
        }
    });
    thread.start();

In Broadcast Receiver, I am trying to cancel the notification using

NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.cancel(ID);

The problem is that when I click on Cancel button the notification disappear for a second but then appear again, may be due to the thread still running. How to destroy the thread from broadcast Receiver class? What should I do to remove the notification on cancel button click ?


Solution

  • To stop the thread you should interrupt it, for example when receiving "CancelServiceAndNotification" in your BroadcastReceiver you can call :

    thread.interrupt();
    

    Then, in your run() method :

        if (Thread.currentThread().isInterrupted()) {
            // we were interrupted, should stop immediately
            return;
        }
    

    If thread is interrupted while sleeping it will throw InterruptedException and clear interrupted flag, so in your case it is very important that you return from run() when catching InterruptedException :

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // we were interrupted, should stop immediately
            return;
        }
    

    And you should cancel notification the same way you do :

    // make sure you pass 1 as id here as you use it for notify()
    notificationManager.cancel(1);
    

    That should work.

    However, it is strongly not recommended to update UI from non-main thread (which you do from you custom thread when calling remoteViews.setProgressBar).

    I recommend using custom AsyncTask for doing background job in doInBackground (instead of your run() method and updating progress of your notification in its onProgressUpdate.
    You can cancel AsyncTask by calling cancel() on it in a similar way you interrupt() a thread as shown above.

    Hope that helps.