0

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

Кажется, что все работает нормально, начиная с уведомления и обновляя его каждую секунду. Однако, когда 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()); 

но в своем заявлении еще вы сказать этому петлитель бросить:

timerNotificationHandler.getLooper().quit(); 

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

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


В вашем заявлении еще вы также можете отменить оповещение:

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

timerNotificationManager.cancel(1234); 
+0

Большое спасибо за ваш ответ. Я еще не пробовал использовать сервис для этого. Я только программировал около двух месяцев, и это мой первый реальный проект. Короче, я ноб. Если я удалю Looper.quit() и изменим на NotificationManager.cancel (1234) и раскомментирует блок catch try, он отменит уведомление, но затем он вернется через секунду. Любая идея, что может вызвать это? Кроме того, просто чтобы быть уверенным ... Я должен использовать handlerthread для этого, не так ли? Это то, что казалось лучшим решением. Еще раз спасибо за ваш ответ. – IINEWMANII

+0

Thats, вероятно, потому, что вы вызываете 'removeCallbacksAndMessages', но' postDelayed' не публикует сообщения в течение 1 секунды, поэтому он публикует сообщение после этого. Вы можете исправить это несколькими способами: создать еще один runnable, который отменяет все через 1.1 секунды, или добавить флаг в runnable, чтобы не отправлять себя снова после отмены – Blundell

+0

Я, наконец, получил его, не заставляя телефон замерзать LOL. Теперь я перехожу к тому, чтобы уведомление было обновлено только в том случае, если экран включен. Я пытаюсь настроить api на 17, так что кажется, что это трудно понять, поскольку isScreenOn() устарел. – IINEWMANII

Смежные вопросы