Cuando estaba trabajando en un proyecto recientemente, encontré un requisito: enviar una notificación con los botones más y menos y un número. Después de hacer clic en el botón, el número de la notificación debe cambiarse en consecuencia.
Suena simple, ¿no es suficiente agregar eventos de clic a los dos botones? Sin embargo, la notificación no pertenece al proceso de la aplicación, sino al proceso mantenido por el sistema Android. El diseño personalizado en la notificación debe RemoteViews
implementarse a través de :
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_number);
NotificationCompat.Builder.setContent(remoteViews);
RemoteViews
Se utiliza para manejar el esquema de diseño de la visualización de procesos cruzados, generalmente utilizado para notificaciones y widgets de escritorio. Debido a los diferentes procesos, RemoteViews
el diseño aplicado no se puede usar directamente findViewById()
para encontrar el control. Encapsula algunos métodos para actualizar UI
, por ejemplo:
void setTextViewText(int viewId, CharSequence text);
void setViewVisibility(int viewId, int visibility);
void setProgressBar(int viewId, int max, int progress, boolean indeterminate);
void setImageViewResource(int viewId, int srcId);
Para obtener más métodos, consulte el documento oficial de la API.
No proporciona un método para agregar directamente un evento de clic al control. Entonces encontré un dilema.
Entonces, ¿podemos escribir directamente el diseño de toda la notificación como un control personalizado y realizar el clic del botón en el control personalizado? Lamentablemente, no es posible. Al enviar una notificación, se informará directamente el siguiente error:
android.app.RemoteServiceException: Bad notification posted from package
com.example.xujiafeng.notificationrefresh
De hecho, es normal pensarlo detenidamente. Si puede configurar el evento de clic de una manera tan simple, RemoteViews
es imposible para nosotros configurar el método de evento de clic para el control sin exponerlo a nosotros.
Entonces, ¿qué más hay?
RemoteViews
Aunque no existe un método para establecer directamente el evento de clic para el control, se proporcionan los siguientes métodos:
void setOnClickPendingIntent (int viewId, PendingIntent pendingIntent)
Los documentos oficiales explicación de este método son: el equivalente de llamar
setOnClickListener(android.view.View.OnClickListener)
para iniciar la oferta PendingIntent
.
Y PendingIntent
es un retraso Intent
, que contiene una interna Intent
, cuando se cumplen ciertas condiciones que no va a empezar Intent
, tiene cuatro maneras de conseguir el objeto:
getActivity(Context, int, Intent, int);
getActivities(Context, int, Intent[], int);
getBroadcast(Context, int, Intent, int);
getService(Context, int, Intent, int);
Por el nombre del método se puede entender que cuando se Intent
inicia, se iniciará Activity
, enviará una transmisión e iniciará el servicio.
Entonces, si queremos implementar un clic RemoteViews
en un botón para comenzar más tarde Activity
, el código es el siguiente:
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 21, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.iv_add, pendingIntent);
Volviendo a nuestra pregunta anterior, ¿cómo realizar el cambio del número en la notificación haciendo clic en el botón?
El método es controlar el botón para enviar una transmisión, y luego la aplicación monitorea la transmisión y envía la misma id
notificación nuevamente después de recibir la transmisión . La nueva notificación cambia el número. Esta es la idea específica, la siguiente es la implementación específica del código.
Código para enviar notificación:
private void sendNotification()
{
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_number);
Intent addIntent = new Intent();
addIntent.setAction("com.example.xujiafeng.notificationrefresh.add");
remoteViews.setOnClickPendingIntent(R.id.iv_add, PendingIntent.getBroadcast(MainActivity.this, 10, addIntent, PendingIntent.FLAG_UPDATE_CURRENT));
Intent minusIntent = new Intent();
addIntent.setAction("com.example.xujiafeng.notificationrefresh.minus");
remoteViews.setOnClickPendingIntent(R.id.iv_add, PendingIntent.getBroadcast(MainActivity.this, 10, minusIntent, PendingIntent.FLAG_UPDATE_CURRENT));
remoteViews.setTextViewText(R.id.tv_value, String.valueOf(value));
notification = new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("ContentTitle")
.setContentText("ContentText")
.setWhen(System.currentTimeMillis())
.setTicker("Ticker")
.setContent(remoteViews)
.build();
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(12, notification);
}
Receptor de transmisión:
public class NotificationReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
switch (action)
{
case "com.example.xujiafeng.notificationrefresh.add":
value++;
sendNotification();
break;
case "com.example.xujiafeng.notificationrefresh.minus":
value--;
sendNotification();
break;
}
}
}
Registrarse para transmitir:
IntentFilter filter = new IntentFilter();
filter.addAction(ADD_ACTION);
filter.addAction(MINUS_ACTION);
mReceiver = new NotificationReceiver();
registerReceiver(mReceiver, filter);
Esto se hace, el efecto de ejecución es el siguiente: