studio pie oreo developer android android-notifications android-remoteview

pie - api 26 android studio



¿Cómo actualizar la notificación con RemoteViews? (3)

Estoy creando una notificación con RemoteViews desde un Service personalizado, que se ejecuta con la notificación en modo de primer plano (es decir, el servicio permanecerá activo mientras la notificación sea visible para el usuario). La notificación se establece como En curso para que el usuario no pueda borrarla.

Me gustaría cambiar, por ejemplo, el mapa de bits que se muestra en ImageView , contenido dentro del diseño de la vista remota o cambiar el valor del texto en un TextView . El diseño en la vista remota se establece con el archivo de diseño XML.

Mi problema es que una vez que se crea una notificación y es visible para el usuario, si llamo a cualquiera de las funciones de setImageViewResource() como setImageViewResource() para cambiar el Bitmap muestra en un ImageView , el cambio no está visible, a menos que llame a setImageViewResource() que llamo después :

NotificationManager.notify( id, notification );

o

Service.startForeground(id,notification);

Aunque esto no me suena bien. No puedo creer que para actualizar la interfaz de usuario de RemoteViews en una notificación que ya se ha creado, tenga que volver a inicializar la notificación. Si tengo el control Button en una notificación, se actualiza solo al tocar y liberar. Así que tiene que haber una manera de hacer esto correctamente, pero no sé cómo.

Aquí está mi código que crea una notificación dentro de mi instancia de Service :

this.notiRemoteViews = new MyRemoteViews(this,this.getApplicationContext().getPackageName(),R.layout.activity_noti1); Notification.Builder notibuilder = new Notification.Builder(this.getApplicationContext()); notibuilder.setContentTitle("Test"); notibuilder.setContentText("test"); notibuilder.setSmallIcon(R.drawable.icon2); notibuilder.setOngoing(true); this.manager = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE); this.noti = notibuilder.build(); this.noti.contentView = this.notiRemoteViews; this.noti.bigContentView = this.notiRemoteViews; this.startForeground(NOTIFICATION_ID, this.noti);

Y la función que ''fuerza'' la IU cambia a la notificación:

public void updateNotiUI(){ this.startForeground(NOTIFICATION_ID, this.noti); }

Dentro de la clase MyRemoteViews , cuando es necesario, hago esto para realizar cambios en la interfaz de usuario:

this.setImageViewResource(R.id.iconOFF, R.drawable.icon_off2); this.ptMyService.updateNotiUI();

¿Alguien puede decirme cuál es la forma correcta de actualizar los componentes de UI de RemoteViews en la notificación?


Aquí hay un ejemplo detallado para que actualice la notificación usando RemoteViews :

private static final int NOTIF_ID = 1234; private NotificationCompat.Builder mBuilder; private NotificationManager mNotificationManager; private RemoteViews mRemoteViews; private Notification mNotification; ... // call this method to setup notification for the first time private void setUpNotification(){ mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // we need to build a basic notification first, then update it Intent intentNotif = new Intent(this, MainActivity.class); intentNotif.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent pendIntent = PendingIntent.getActivity(this, 0, intentNotif, PendingIntent.FLAG_UPDATE_CURRENT); // notification''s layout mRemoteViews = new RemoteViews(getPackageName(), R.layout.custom_notification_small); // notification''s icon mRemoteViews.setImageViewResource(R.id.notif_icon, R.drawable.ic_launcher); // notification''s title mRemoteViews.setTextViewText(R.id.notif_title, getResources().getString(R.string.app_name)); // notification''s content mRemoteViews.setTextViewText(R.id.notif_content, getResources().getString(R.string.content_text)); mBuilder = new NotificationCompat.Builder(this); CharSequence ticker = getResources().getString(R.string.ticker_text); int apiVersion = Build.VERSION.SDK_INT; if (apiVersion < VERSION_CODES.HONEYCOMB) { mNotification = new Notification(R.drawable.ic_launcher, ticker, System.currentTimeMillis()); mNotification.contentView = mRemoteViews; mNotification.contentIntent = pendIntent; mNotification.flags |= Notification.FLAG_NO_CLEAR; //Do not clear the notification mNotification.defaults |= Notification.DEFAULT_LIGHTS; // starting service with notification in foreground mode startForeground(NOTIF_ID, mNotification); }else if (apiVersion >= VERSION_CODES.HONEYCOMB) { mBuilder.setSmallIcon(R.drawable.ic_launcher) .setAutoCancel(false) .setOngoing(true) .setContentIntent(pendIntent) .setContent(mRemoteViews) .setTicker(ticker); // starting service with notification in foreground mode startForeground(NOTIF_ID, mBuilder.build()); } } // use this method to update the Notification''s UI private void updateNotification(){ int api = Build.VERSION.SDK_INT; // update the icon mRemoteViews.setImageViewResource(R.id.notif_icon, R.drawable.icon_off2); // update the title mRemoteViews.setTextViewText(R.id.notif_title, getResources().getString(R.string.new_title)); // update the content mRemoteViews.setTextViewText(R.id.notif_content, getResources().getString(R.string.new_content_text)); // update the notification if (api < VERSION_CODES.HONEYCOMB) { mNotificationManager.notify(NOTIF_ID, mNotification); }else if (api >= VERSION_CODES.HONEYCOMB) { mNotificationManager.notify(NOTIF_ID, mBuilder.build()); } }

Diseño para la Notificación, es decir, res/layout/custom_notification_small.xml :

<!-- We have to set the height to 64dp, this is the rule of the small notification --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="64dp" android:orientation="horizontal" android:id="@+id/notif_small" android:background="@drawable/notification_background"> <ImageView android:id="@+id/notif_icon" android:contentDescription="@string/notif_small_desc" android:layout_width="47dp" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_alignParentLeft="true" android:src="@drawable/ic_launcher" android:layout_marginLeft="7dp" android:layout_marginRight="9dp"/> <TextView android:id="@+id/notif_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/notif_icon" android:singleLine="true" android:paddingTop="8dp" android:textSize="17sp" android:textStyle="bold" android:textColor="#000000" android:text="@string/app_name"/> <TextView android:id="@+id/notif_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/notif_icon" android:paddingBottom="9dp" android:layout_alignParentBottom="true" android:singleLine="true" android:textSize="13sp" android:textColor="#575757" android:text="Content" /> </RelativeLayout>

Espero que este ejemplo te ayude mucho!

NOTA: No puede actualizar el NotificationCompat personalizado en pre-Honeycomb, así que agregué una forma alternativa de actualizarlo en el pre-Honeycomb, es decir, verificar el nivel de API primero y usar la Notification en desuso.


No almacene el objeto Notification , sino el objeto Notification.Builder . Producir una nueva notificación cada vez antes de empujarla a

NotificationManager.notify( id, notification );


Tendría que llamar a NotificationManager.notify(id, notification) para que Notification System sepa que desea actualizar la vista de notificación. Aquí está el enlace de documentos http://developer.android.com/training/notify-user/managing.html .

Tener un método que devuelva el objeto de notificación.

private Notification getNotification(NotificationCompat.Builder mBuilder) { RemoteViews mRemoteViews = new RemoteViews(getPackageName(), R.layout.notification_layout); // Update your RemoteViews mBuilder.setContent(mRemoteView); Notification mNotification = mBuilder.build(); // set mNotification.bigContentView if you want to return mNotification; } private void refreshNotification() { mNotificationManager.notify(getNotification(mNotificationBuilder), NOTIFICATION_ID); // mNotificationBuilder is initialized already }

Además, tenga en cuenta que bigContentView y RemoteViews no están completamente rediseñados. Si algunos de los elementos de bigContentView tienen la visibilidad establecida en GONE y si desea mostrarla la próxima vez, debe establecer la visibilidad de forma explícita en VISIBLE .