Как остановить уведомления, которые в потоке обработчика

У меня есть пользовательское уведомление, которое имеет четыре RemoteView TextViews. Когда вызывается onPause(), я хочу опубликовать уведомление, а затем обновлять его каждую секунду, пока экран включен. Когда вызывается onResume(), я хочу отменить уведомление. Пока что я настроил его так, чтобы у меня был volatile, который получает значение true, когда вызывается onPause(), и устанавливается в false, когда вызывается onResume(). У меня есть метод, который запускает HandlerThread, а затем проверяет логическое значение volatile. Если булево значение равно true, оно должно обновить уведомление, а если оно ложное, оно должно отменить уведомление и закрыть HandlerThread.

Кажется, все работает нормально, начиная с уведомления и обновляя его каждую секунду. Однако, когда вызывается onResume(), это не останавливает уведомление.

У меня пока нет экрана с закодированным материалом, потому что я пытался выяснить, как отключить уведомление и HandlerThread, прежде чем перейти к этому.

Вот мой код до сих пор:

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 ответ

Решение

Самый "андроидный" способ сделать это - использовать фоновый сервис.

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

Когда ваше приложение переходит в фоновый режим (onPause), вы либо запускаете службу, либо публикуете сообщение, в котором говорится об этом, и наоборот с помощью onResume.

(проблема с вашим текущим решением заключается в том, что ваша активность может быть в любой момент прервана в onStop / onDestroy, но вы все равно хотите получать обновления уведомлений)


Обратите внимание, что вы создаете свой HandlerThread с помощью MainThreads Looper:

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

но затем в своем выражении else вы говорите этому петлителю выйти:

 timerNotificationHandler.getLooper().quit();

Я не совсем уверен, какое поведение это дает! Но у меня есть ощущение, что это неправильно - вы не хотите останавливать петлю mainthreads от циклов, это означает, что ваша деятельность не будет работать так, как ожидалось (и может быть вашей проблемой).

https://developer.android.com/reference/android/os/Looper.html


В своем заявлении else вы также можете отменить свое уведомление:

https://developer.android.com/reference/android/app/NotificationManager.html

timerNotificationManager.cancel(1234);
Другие вопросы по тегам