android - para - como quitar el flash de las notificaciones samsung j7 pro
¿Cómo puedo evitar el parpadeo de la actualización de notificaciones mientras cambio el botón? (3)
Tengo una notificación que admite reproducción, pausa adelante y atrá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 configurado el generador en una variable global y lo reutilizo en cada actualización, lo que funciona muy bien. pero reutilizándolo, significa que también todos los botones que agregué se reutilizan y no hay posibilidad de eliminar las Acciones que agregué antes.
El cambio de botón solo funciona si reinicializo NotificationCompat.Builder en cada actualización, lo que significa que vuelvo a parpadear.
¿Cómo evito parpadear, pero dejando que el botón cambie?
EDIT: Acabo de revisar Rocket Player, no resolvieron el problema también, pero Google Play Music sí lo hizo.
Como dijo Boris, el problema es que se creará una nueva notificación en cada actualización. Mi solución cubre la misma lógica, pero uso 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 en la clase.
El problema es que creas una nueva notificación cada vez que quieres actualizar. Tuve el mismo problema y se solucionó cuando hice lo siguiente:
- conservar la instancia de la notificación entre las diferentes llamadas de
createNotification
. - establezca esta instancia en nula cada vez que se elimine de la barra de notificaciones.
- haz 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 llame, notify
no aparecerá ningún parpadeo:
manager.notify(0, createNotification(interpret, title, paused));
PD: También enfrenté el problema de que si ejecutaba setLatestEventInfo
los setLatestEventInfo
grandes y pequeños quedaban arrugados. 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;
Buscando en el código de Adnroid esta línea mNotification.icon = 0;
desactiva el icono de atornillar.
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 difícil para empezar. Lo encontré hoy también, y siendo mi obstinado, encontré una solución después de buscar e intentar por un tiempo.
Cómo resolver este problema:
Para ser compatible con niveles de API inferiores a 19, mi solución es usar las clases NotificationCompat
de la biblioteca de soporte.
Según lo sugerido por otros, mantengo la referencia a NotificationCompat.Builder
durante el tiempo que se requiera la notificación. Las acciones que uso en mi Notificación solo se agregan en la creación inicial del Builder
, y aquellas acciones que cambiarán según la situación, también las almaceno en un miembro privado del servicio. Al cambiar, reutilizo el objeto Builder
y ajusto el objeto NotificationCompat.Action
acuerdo con mis necesidades. Luego llamo al método Builder.getNotification()
o Builder.build()
, dependiendo del nivel de API (probablemente no sea necesario debido a las librerías de soporte, pero no lo comprobé. Si puedo omitir eso, escriba un comentar, para que pueda mejorar mi código;)
Aquí hay un código de ejemplo 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 convenientes que simplemente crean los objetos PendingIntent
.
A continuación, se llama a este método cuando necesito actualizar la notificación utilizando NotificationManager
, y se entrega al método startForeground()
. Esto resuelve el parpadeo y los problemas con las acciones no actualizables en la notificación.