Permitir cancelación de la notificación después de llamar a stopForeground (false)

Tengo un servicio de medios que usa startForeground () para mostrar una notificación cuando se inicia la reproducción. Tiene botones de pausa / parada al reproducir, botones de reproducción / parada mientras está en pausa.

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this); // setup... Notification n = mBuilder.build(); if (state == State.Playing) { startForeground(mId, n); } else { stopForeground(false); mNotificationManager.notify(mId, n); } 

El problema aquí es cuando se muestra / actualizar la notificación en su estado de pausa, se le debe permitir eliminarlo. mBuilder.setOngoing(false) parece no tener ningún efecto ya que el startForeground anterior startForeground anula.

Llamar stopForeground(true); Con el mismo código funciona como se esperaba, pero la Notificación parpadea cuando se destruye y se vuelve a crear. ¿Hay una forma de "actualizar" la notificación creada desde startForeground para permitir que se elimine después de llamar a stop?

Editar: Según se solicita, aquí está el código completo que crea la notificación. CreateNotification se llama cuando el servicio se reproduce o pausa.

 private void createNotification() { NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_launcher) .setContentTitle("No Agenda") .setContentText("Live stream"); if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { if (state == State.Playing) { Intent pauseIntent = new Intent(this, MusicService.class); pauseIntent.setAction(ACTION_PAUSE); PendingIntent pausePendingIntent = PendingIntent.getService(MusicService.this, 0, pauseIntent, 0); mBuilder.addAction(R.drawable.pause, "Pause", pausePendingIntent); //mBuilder.setOngoing(true); } else if (state == State.Paused) { Intent pauseIntent = new Intent(this, MusicService.class); pauseIntent.setAction(ACTION_PAUSE); PendingIntent pausePendingIntent = PendingIntent.getService(MusicService.this, 0, pauseIntent, 0); mBuilder.addAction(R.drawable.play, "Play", pausePendingIntent); mBuilder.setOngoing(false); } Intent stopIntent = new Intent(this, MusicService.class); stopIntent.setAction(ACTION_STOP); PendingIntent stopPendingIntent = PendingIntent.getService(MusicService.this, 0, stopIntent, 0); setNotificationPendingIntent(mBuilder); mBuilder.addAction(R.drawable.stop, "Stop", stopPendingIntent); } else { Intent resultIntent = new Intent(this, MainActivity.class); PendingIntent intent = PendingIntent.getActivity(this, 0, resultIntent, 0); mBuilder.setContentIntent(intent); } Notification n = mBuilder.build(); if (state == State.Playing) { startForeground(mId, n); } else { stopForeground(true); mNotificationManager.notify(mId, n); } } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void setNotificationPendingIntent(NotificationCompat.Builder mBuilder) { Intent resultIntent = new Intent(this, MainActivity.class); TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); stackBuilder.addParentStack(MainActivity.class); stackBuilder.addNextIntent(resultIntent); PendingIntent resultPendingIntent = stackBuilder.getPendingIntent( 0, PendingIntent.FLAG_UPDATE_CURRENT ); mBuilder.setContentIntent(resultPendingIntent); } 

Edición de seguimiento:

Uno de los comentarios a continuación mencionó que la respuesta puede ser "frágil", ya partir de la liberación de Android 4.3, el comportamiento detrás de startForeground ha cambiado. StartForeground obligará a su aplicación a mostrar una notificación mientras está en primer plano, y el método sólo se debe llamar con la notificación para mostrar. No he probado, pero la respuesta aceptada ya no puede funcionar como estaba previsto.

En términos de detener el parpadeo cuando se llama stopForeground , no creo que valga la pena luchar contra el marco para.

Hay alguna información adicional sobre el cambio de notificación de Android 4.3 aquí .

Usted puede considerar el uso de un enfoque diferente.
Puesto que usted debe utilizar el servicio del primero plano para tal tarea (el jugar de los medios) le sugiero que usted continúe haciendo el start foreground() , pero en vez de pasarle una notificación apenas fije la identificación 0 y la notificación null como esto startForeground(0, null); .

De esta manera, el servicio de primer plano no mostrará ninguna notificación.

Ahora, para sus propósitos, puede utilizar notificaciones regulares y actualizar sus estados (en curso, diseño, texto, etc …), de esta manera no dependerá del comportamiento de notificación del servicio de primer plano.

Espero que esto ayude.

De acuerdo con documentos este comportamiento es por diseño antes de Lollipop

Las aplicaciones dirigidas a esta o una versión posterior obtendrán estos nuevos cambios de comportamiento:

  • Llamar Service.stopForeground con removeNotification false modificará la notificación todavía publicada para que ya no se vea forzada a estar en curso.

En lugar de stopService(true) , stopService(false) conservará la notificación como está (sin estado en curso) a menos que sea descartada por el usuario / eliminada mediante programación o si el servicio se detiene. Por lo tanto, sólo llama a stopService (false) y notificación de actualización para mostrar el estado de pausa y ahora la notificación puede ser rechazada por el usuario. Esto también evita que parpadee ya que no estamos recreando la notificación.

  • Uso de un servicio de Android para manejar una conexión de red
  • Evitando el retraso de inicialización de Google TTS Engine en Android
  • Cámara Android: se ejecuta en segundo plano desde el servicio
  • RemoteViews para la actualización de widget supera el error máximo de uso de memoria de mapa de bits
  • Obtenga la ubicación de Android GPS una vez cada pocos minutos
  • Comunicación Android de servicio a actividad a alta frecuencia: ¿la mejor opción?
  • Problemas al llamar a AsyncTask de IntentService
  • Matar la aplicación android del administrador de tareas mata los servicios iniciados por la aplicación
  • Servicio automático llamado en la actividad de destrucción
  • Prácticas recomendadas para informar de la ubicación del usuario continuamente
  • Android geofencing cuando se mata la aplicación
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.