¿Cómo puedo evitar la actualización de notificaciones parpadeantes mientras cambia el botón

Tengo una notificación, que apoya el juego, pausa adelante y detrás.

private static Notification createNotification(String interpret, String title, boolean paused) { // if (builder == null) builder = new NotificationCompat.Builder(context); builder.setPriority(Notification.PRIORITY_MAX); builder.setAutoCancel(false); builder.setContentTitle(title); builder.setContentText(interpret); builder.setOngoing(true); builder.setOnlyAlertOnce(true); builder.setSmallIcon(R.drawable.ic_launcher); builder.setContentIntent(PendingIntent.getActivity(context, 9, new Intent(context, ApplicationActivity.class), Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)); builder.addAction(R.drawable.av_previous, "", PendingIntent.getBroadcast(context.getApplicationContext(), 0, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.PREVIOUS), PendingIntent.FLAG_CANCEL_CURRENT)); if (paused) builder.addAction(R.drawable.av_play, "", PendingIntent.getBroadcast(context.getApplicationContext(), 2, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.PLAY), PendingIntent.FLAG_CANCEL_CURRENT)); else builder.addAction(R.drawable.av_pause, "", PendingIntent.getBroadcast(context.getApplicationContext(), 3, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.PAUSE), PendingIntent.FLAG_CANCEL_CURRENT)); builder.addAction(R.drawable.av_next, "", PendingIntent.getBroadcast(context.getApplicationContext(), 1, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.NEXT), PendingIntent.FLAG_CANCEL_CURRENT)); Notification notification = builder.build(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) notification.tickerView = null; return notification; } 

Actualización de la notificación:

  public static void update(String interpret, String title, boolean paused) { NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(0, createNotification(interpret, title, paused)); } 

Para evitar el parpadeo en la actualización, he establecido el constructor en una variable global y lo vuelvo a usar en cada actualización, lo cual funciona muy bien. Pero reutilizarlo, significa que también todos los botones que he agregado se reutilizan y no hay posibilidad de eliminar las acciones que he añadido antes.

El cambio de botón sólo funciona si reinicio el NotificationCompat.Builder en cada actualización, lo que significa que vuelvo a parpadear.

¿Cómo evito parpadear, pero dejar que el botón cambie?

EDIT: Acaba de salir de Rocket Player, no solucionaron el problema también, pero Google Play Music no

Como Boris dijo, el problema es que una nueva notificación será construir cada actualización. Mi solución cubre la misma lógica, pero uso el NotificationBuilder

Aquí está el código:

 if (mNotificationBuilder == null) { mNotificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(iconId) .setContentTitle(title) .setContentText(message) .setLargeIcon(largeIcon) .setOngoing(true) .setAutoCancel(false); } else { mNotificationBuilder.setContentTitle(title) .setContentText(message); } 

Tenga en cuenta que mNotificationBuilder es un campo privado de la clase.

El problema es que se crea una nueva notificación cada vez que se desea actualizar. Tuve el mismo problema y se corrigió cuando hice lo siguiente:

  • Retener la instancia de la notificación entre diferentes llamadas de createNotification .
  • Establezca esta instancia en null cada vez que se quita de la barra de notificación.
  • Haga el siguiente código:

Código:

 private static Notification createNotification(String interpret, String title, boolean paused) { if (mNotification == null) { // do the normal stuff you do with the notification builder } else { // set the notification fields in the class member directly ... set other fields. // The below method is deprecated, but is the only way I have found to set the content title and text mNotification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); } return mNotification; } 

Y ahora cuando llamas a notify no parpadeará aparecerá:

 manager.notify(0, createNotification(interpret, title, paused)); 

PS: También me enfrenté a un problema que si setLatestEventInfo los iconos grandes y pequeños se scrwed. Por eso lo hice:

 int tmpIconResourceIdStore = mNotification.icon; // this is needed to make the line below not change the large icon of the notification mNotification.icon = 0; // The below method is deprecated, but is the only way I have found to set the content title and text mNotification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); mNotification.icon = tmpIconResourceIdStore; 

Mirando en el ccode de Adnroid esta línea mNotification.icon = 0; Desactiva el icono de tornillo hacia arriba.

Sé que esta es una pregunta bastante antigua, pero como no encontré una solución en ningún otro lugar, pensé que responder a esto ahora podría ayudar a otros con el mismo problema.

Este problema es un poco complicado para empezar. Lo encontré hoy también, y siendo mi auto obstinado, encontré una solución después de buscar y de intentar por un rato.

Cómo resolver este problema:

Para ser compatible con niveles de API inferiores a 19, mi solución es utilizar las clases de NotificationCompat de la biblioteca de soporte.

Como sugerido por otros, sigo la referencia a la NotificationCompat.Builder durante el tiempo que se requiere la notificación. Las acciones que utilizo en mi Notificación solo se agregan a la creación inicial del Builder , y aquellas acciones que cambiarán dependiendo de la situación, también almacenaré en un miembro privado del servicio. Al cambiar, vuelvo a usar el objeto Builder y ajustar el objeto NotificationCompat.Action según mis necesidades. Luego llamo al método Builder.getNotification() o Builder.build() , dependiendo del nivel de la API (probablemente no es necesario debido a las librerías de soporte, pero no lo compruebo.) Si puedo omitirlo, por favor escriba un Comentario, para que pueda mejorar mi código;)

He aquí un ejemplo de código de lo que acabo de describir:

 public Notification createForegroundNotification(TaskProgressBean taskProgressBean, boolean indeterminate) { Context context = RewardCalculatorApplication.getInstance(); long maxTime = TaskUtils.getMaxTime(taskEntry); long taskElapsedTime = TaskUtils.calculateActualElapsedTime(taskProgressBean); long pauseElapsedTime = taskProgressBean.getPauseElapsedTime(); int pauseToggleActionIcon; int pauseToggleActionText; PendingIntent pauseToggleActionPI; boolean pauseButton = pauseElapsedTime == 0; if(pauseButton) { pauseToggleActionIcon = R.drawable.ic_stat_av_pause; pauseToggleActionText = R.string.btnTaskPause; pauseToggleActionPI = getPendingIntentServicePause(context); } else { pauseToggleActionIcon = R.drawable.ic_stat_av_play_arrow; pauseToggleActionText = R.string.btnTaskContinue; pauseToggleActionPI = getPendingIntentServiceUnpause(context); } String contentText = context.getString(R.string.taskForegroundNotificationText, TaskUtils.formatTimeForDisplay(taskElapsedTime), TaskUtils.formatTimeForDisplay(pauseElapsedTime), TaskUtils.formatTimeForDisplay(taskProgressBean.getPauseTotal())); // check if we have a builder or not... boolean createNotification = foregroundNotificationBuilder == null; if(createNotification) { // create one foregroundNotificationBuilder = new NotificationCompat.Builder(context); // set the data that never changes...plus the pauseAction, because we don't change the // pauseAction-object, only it's data... pauseAction = new NotificationCompat.Action(pauseToggleActionIcon, getString(pauseToggleActionText), pauseToggleActionPI); foregroundNotificationBuilder .setContentTitle(taskEntry.getName()) .setSmallIcon(R.drawable.ic_launcher) .setContentIntent(getPendingIntentActivity(context)) .setOngoing(true) .addAction(R.drawable.ic_stat_action_done, getString(R.string.btnTaskFinish), getPendingIntentServiceFinish(context)) .addAction(pauseAction); } // this changes with every update foregroundNotificationBuilder.setContentText(contentText); if(indeterminate) { foregroundNotificationBuilder.setProgress(0, 0, true); } else { foregroundNotificationBuilder.setProgress((int) maxTime, (int) taskElapsedTime, false); } // if this is not the creation but the button has changed, change the pauseAction's data... if(!createNotification && (pauseButton != foregroundNotificationPauseButton)) { foregroundNotificationPauseButton = pauseButton; pauseAction.icon = pauseToggleActionIcon; pauseAction.title = getString(pauseToggleActionText); pauseAction.actionIntent = pauseToggleActionPI; } return (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) ? foregroundNotificationBuilder.getNotification() // before jelly bean... : foregroundNotificationBuilder.build(); // since jelly bean... } 

Las variables foregroundNotificationBuilder , pauseAction y foregroundNotificationPauseButton son miembros privados de la clase de servicio. Los getPendingIntent...() son métodos de conveniencia que simplemente crean los objetos PendingIntent .

A continuación, se llama a este método cuando necesito actualizar la notificación mediante NotificationManager , así como entregarla al método startForeground() . Esto soluciona el parpadeo y los problemas con las acciones no actualizables en la notificación.

  • Notificación de Parse Push no enviando desde Android al Canal
  • Android mediaplayer loops para siempre en ICS
  • incapaz de transferir datos a través de la intención durante la notificación
  • ¿Cómo obtener URI actual / tono de llamada predeterminado para SMS entrantes?
  • Intención de reanudar una actividad previamente detenida (llamada desde una notificación)
  • Notificaciones push iOS y código nativo cliente-cliente de Android
  • Cerrar la barra de estado cuando se hace clic en la notificación de botón
  • Saber si la aplicación recibió la notificación desde el lado del servidor
  • Notificación de notificación de vibración / tono de llamada
  • Cambio de los botones de acción en una notificación
  • Cómo mostrar el recuento de notificaciones en el icono de la barra de herramientas en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.