0

J'ai une notification personnalisée qui a quatre TextViews RemoteView. Quand onPause() est appelée, je veux poster la notification et la mettre à jour toutes les secondes pendant que l'écran est allumé. Quand onResume() est appelé, je veux annuler la notification. Jusqu'à présent je l'ai configuré de sorte que j'ai un booléen volatil qui est mis à vrai quand onPause() est appelé et mis à false quand onResume() est appelé. J'ai une méthode qui démarre un HandlerThread, puis vérifie le booléen volatile. Si le booléen est vrai, il est supposé mettre à jour la notification et s'il est faux, il est censé annuler la notification et arrêter le HandlerThread.comment arrêter la notification thats dans thread de gestionnaire

Tout semble fonctionner correctement pour démarrer la notification et la mettre à jour toutes les secondes. Toutefois, lorsque onResume() est appelé, il n'arrête pas la notification.

L'écran n'a pas encore été codé car j'essayais de comprendre comment arrêter la notification et HandlerThread avant de passer à autre chose.

Voici mon code à ce jour:

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"); 
    } 

} 

Répondre

1

La façon la plus « android » de le faire serait d'utiliser un service d'arrière-plan.

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

Lorsque votre application se déplace dans l'arrière-plan (OnPause) vous soit démarrer le service ou envoyer un message à la dire en indiquant cela, et le contraire avec onResume.

(le problème avec votre solution actuelle est votre activité pourrait être tué à tout moment onStop/OnDestroy mais vous auriez encore envie le processus continu des mises à jour de notification)


Avis vous créez votre HandlerThread en utilisant les MainThreads Looper:

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

mais dans votre déclaration d'autre vous dire ce looper de quitter:

timerNotificationHandler.getLooper().quit(); 

Je ne suis pas tout à fait sûr quel comportement cela donne! Mais j'ai l'impression que c'est faux - vous ne voulez pas arrêter la boucle principale de threads, cela signifie que votre activité ne fonctionnera pas comme prévu (et pourrait être votre problème).

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


Dans votre déclaration, sinon vous pouvez également annuler votre notification:

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

timerNotificationManager.cancel(1234); 
+0

Merci beaucoup pour votre réponse. Je n'ai pas encore essayé d'utiliser un service pour le faire. Je n'ai programmé que depuis deux mois et c'est mon premier vrai projet. En bref je suis un noob. Si je supprime le Looper.quit() et change à NotificationManager.cancel (1234) et décommentez le bloc try catch il annulera la notification, mais il reviendra une seconde plus tard. Une idée de ce que cela pourrait causer? Aussi, juste pour être sûr ..... Je devrais utiliser handlerthread pour cela, non? C'est ce qui semblait être la meilleure solution. Merci encore pour votre réponse. – IINEWMANII

+0

C'est probablement parce que vous appelez 'removeCallbacksAndMessages' mais' postDelayed' ne publie pas pendant 1 seconde, donc il publie le message après. Vous pouvez le résoudre de plusieurs façons: créer un autre runnable qui annule tout après 1,1 seconde, ou ajouter un drapeau au runnable pour ne plus le poster une fois annulé – Blundell

+0

J'ai finalement réussi à le faire fonctionner sans que le téléphone se bloque lol. Maintenant je continue à faire en sorte que la notification ne sera mise à jour que si l'écran est allumé. J'essaie de cibler api aussi bas que 17 donc il semble que cela pourrait être difficile à comprendre puisque isScreenOn() est obsolète. – IINEWMANII