how to stop notification thats in handler thread

459 views Asked by At

I have a custom notification that has four RemoteView TextViews. When onPause() gets called I want to post the notification and then update it every second while the screen is on. When onResume() gets called I want to cancel the notification. So far I have it set up so that I have a volatile boolean that gets set to true when onPause() gets called and set to false when onResume() gets called. I have a method that starts a HandlerThread and then checks the volatile boolean. If the boolean is true it is supposed to update the notification and if it is false it is supposed to cancel the notification and shutdown the HandlerThread.

Everything seems to be working fine as far as starting the notification and updating it every second. However, when onResume() is called it is not stopping the notification.

I do not have the screen on stuff coded in yet because I was trying to figure out how to shutdown the notification and and HandlerThread before I moved on to that.

Here is my code so far:

void setUpTimerNotif() {

    handlerThread = new HandlerThread("TimerNotificationHandler", Process.THREAD_PRIORITY_BACKGROUND);

    handlerThread.start();

    timerNotificationHandler = new Handler(handlerThread.getLooper());

    timerNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    Intent timerNotifIntent = new Intent(MainActivity.this, MainActivity.class);
    timerNotifIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

    final PendingIntent pendingTimerNotifIntent = PendingIntent.getActivity(MainActivity.this,
            1234, timerNotifIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    final RemoteViews remoteTimerViews = new RemoteViews(getPackageName(), R.layout.timer_notification);

    final NotificationCompat.Builder timerNotificationBuilder = new NotificationCompat.Builder(MainActivity.this);

    if (timerNotificationRunning) {
        timerNotificationHandler.postDelayed(
                new Runnable() {
                    @Override
                    public void run() {

                        long timerNotifTimeOne = wakeUpTime - System.currentTimeMillis();
                        long timerNotifTimeTwo = wakeUpTimeTwo - System.currentTimeMillis();
                        long timerNotifTimeThree = wakeUpTimeThree - System.currentTimeMillis();
                        long timerNotifTimeFour = wakeUpTimeFour - System.currentTimeMillis();

                        String timeOne = timerFormat(timerNotifTimeOne);
                        String timeTwo = timerFormat(timerNotifTimeTwo);
                        String timeThree = timerFormat(timerNotifTimeThree);
                        String timeFour = timerFormat(timerNotifTimeFour);

                        String hmsOne = ("Timer 1: " + timeOne);
                        String hmsTwo = ("Timer 2: " + timeTwo);
                        String hmsThree = ("Timer 3: " + timeThree);
                        String hmsfour = ("Timer 4: " + timeFour);

                        remoteTimerViews.setTextViewText(R.id.timer_one_notification_view, hmsOne);

                        remoteTimerViews.setTextViewText(R.id.timer_two_notification_view, hmsTwo);

                        remoteTimerViews.setTextViewText(R.id.timer_three_notification_view, hmsThree);

                        remoteTimerViews.setTextViewText(R.id.timer_four_notification_view, hmsfour);

                        timerNotificationBuilder.setPriority(Notification.PRIORITY_HIGH)
                                .setAutoCancel(false)
                                .setOngoing(true)
                                .setOnlyAlertOnce(true)
                                .setSmallIcon(R.mipmap.ic_launcher)
                                .setContentIntent(pendingTimerNotifIntent)
                                .setCustomBigContentView(remoteTimerViews)
                                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC);

                        timerNotificationManager.notify(1234, timerNotificationBuilder.build());

                        timerNotificationHandler.post(this);

                    }
                }, 1000
        );
    } else {
        timerNotificationManager.cancelAll();

        if (timerNotificationHandler != null) {
            timerNotificationHandler.removeCallbacksAndMessages(null);
        }

        timerNotificationHandler.getLooper().quit();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            handlerThread.quitSafely();
        } else {
            handlerThread.quit();

            /*try {
                handlerThread.join();
                handlerThread = null;
                timerNotificationHandler = null;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
        }

        Log.v(TAG, "Timer Notification Cancelled");
    }

}
1

There are 1 answers

3
Blundell On BEST ANSWER

The most "android" way to do this would be to use a background Service.

https://developer.android.com/guide/components/services.html

When your app moves into the background (onPause) you either start the service or post a message to the saying stating this, and the opposite with onResume.

(the problem with your current solution is your Activity could be killed at anytime onStop/onDestroy but you would still want the on going notification updates)


Notice you create your HandlerThread using the MainThreads Looper:

 timerNotificationHandler = new Handler(handlerThread.getLooper());

but then in your else statement you tell this looper to quit:

 timerNotificationHandler.getLooper().quit();

I'm not quite sure what behaviour this gives! But i have a feeling it is wrong - you don't want to stop the mainthreads looper from looping, it means your activity won't work as expected (and might be your issue).

https://developer.android.com/reference/android/os/Looper.html#quit()


In your else statement you might also want to cancel your notification:

https://developer.android.com/reference/android/app/NotificationManager.html#cancel(int)

timerNotificationManager.cancel(1234);