Mam konfigurację usługi pierwszego planu w systemie Android. Chciałbym zaktualizować tekst powiadomienia. Tworzę usługę, jak pokazano poniżej.
Jak mogę zaktualizować tekst powiadomienia skonfigurowany w ramach tej usługi pierwszego planu? Jaka jest najlepsza praktyka w zakresie aktualizowania powiadomienia? Każdy przykładowy kod będzie mile widziany.
public class NotificationService extends Service {
private static final int ONGOING_NOTIFICATION = 1;
private Notification notification;
@Override
public void onCreate() {
super.onCreate();
this.notification = new Notification(R.drawable.statusbar, getText(R.string.app_name), System.currentTimeMillis());
Intent notificationIntent = new Intent(this, AbList.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
this.notification.setLatestEventInfo(this, getText(R.string.app_name), "Update This Text", pendingIntent);
startForeground(ONGOING_NOTIFICATION, this.notification);
}
Tworzę usługę w mojej głównej działalności, jak pokazano poniżej:
// Start Notification Service
Intent serviceIntent = new Intent(this, NotificationService.class);
startService(serviceIntent);
źródło
startService()
aby przekazać polecenie do usługi, po prostu zadzwoństartService()
ponownie, aby nakazać zaktualizowanie tekstu. Lub, jeśli dzwoniszbindService()
, dodaj metodę do interfejsu API, aby usługa zaktualizowała swój tekst. Albo zastanów się, czy to sama usługa powinna podejmować decyzję, czy zaktualizować tekst, czy nie. A może tekst jestSharedPeference
tym, na którym usługa ma nasłuchiwanie. W skrócie nie da się udzielić dokładnej porady.cancel()
ustawić powiadomienia przezstartForeground()
. Musisz usunąć status pierwszego planu samej usługi (używając,stopForeground()
jeśli chcesz, aby tekst naNotificationManager
działało zgodnie z oczekiwaniami.Jeśli chcesz zaktualizować zestaw powiadomień za pomocą funkcji startForeground (), po prostu utwórz nowe powiadomienie, a następnie użyj NotificationManager, aby je powiadomić.
Kluczową kwestią jest użycie tego samego identyfikatora powiadomienia.
Nie testowałem scenariusza wielokrotnego wywoływania metody startForeground () w celu zaktualizowania Notification, ale myślę, że użycie NotificationManager.notify byłoby lepsze.
Aktualizacja Powiadomienia NIE usunie Usługi z pierwszego planu (można to zrobić tylko poprzez wywołanie stopForground);
Przykład:
private static final int NOTIF_ID=1; @Override public void onCreate (){ this.startForeground(); } private void startForeground() { startForeground(NOTIF_ID, getMyActivityNotification("")); } private Notification getMyActivityNotification(String text){ // The PendingIntent to launch our activity if the user selects // this notification CharSequence title = getText(R.string.title_activity); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MyActivity.class), 0); return new Notification.Builder(this) .setContentTitle(title) .setContentText(text) .setSmallIcon(R.drawable.ic_launcher_b3) .setContentIntent(contentIntent).getNotification(); } /** * This is the method that can be called to update the Notification */ private void updateNotification() { String text = "Some text that will update the notification"; Notification notification = getMyActivityNotification(text); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(NOTIF_ID, notification); }
W dokumentacji Zjednoczone
źródło
notify()
lubstartForeground()
oba prowadzą do połączeniaonStartCommand()
.NotificationManager
do aktualizacji powiadomienia wyświetlanego za pomocąstartForeground
polega na tym, że połączeniestopForeground
nie będzie już usuwać powiadomienia. Zaktualizowanie go innym wywołaniemstartForeground
eliminuje ten problem.Poprawa odpowiedzi Luca Manzo w systemie Android 8.0+. Podczas aktualizacji powiadomienia będzie wydawać dźwięk i wyświetlać się jako Uwaga.
aby temu zapobiec, musisz dodać
setOnlyAlertOnce(true)
więc kod to:
private static final int NOTIF_ID=1; @Override public void onCreate(){ this.startForeground(); } private void startForeground(){ startForeground(NOTIF_ID,getMyActivityNotification("")); } private Notification getMyActivityNotification(String text){ if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){ ((NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel( NotificationChannel("timer_notification","Timer Notification",NotificationManager.IMPORTANCE_HIGH)) } // The PendingIntent to launch our activity if the user selects // this notification PendingIntent contentIntent=PendingIntent.getActivity(this, 0,new Intent(this,MyActivity.class),0); return new NotificationCompat.Builder(this,"my_channel_01") .setContentTitle("some title") .setContentText(text) .setOnlyAlertOnce(true) // so when data is updated don't make sound and alert in android 8.0+ .setOngoing(true) .setSmallIcon(R.drawable.ic_launcher_b3) .setContentIntent(contentIntent) .build(); } /** * This is the method that can be called to update the Notification */ private void updateNotification(){ String text="Some text that will update the notification"; Notification notification=getMyActivityNotification(text); NotificationManager mNotificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(NOTIF_ID,notification); }
źródło
new NotificationChannel
oto kod, aby to zrobić w twojej usłudze . Utwórz nowe powiadomienie, ale poproś menedżera powiadomień o powiadomienie o tym samym identyfikatorze powiadomienia, którego użyłeś w startForeground.
Notification notify = createNotification(); final NotificationManager notificationManager = (NotificationManager) getApplicationContext() .getSystemService(getApplicationContext().NOTIFICATION_SERVICE); notificationManager.notify(ONGOING_NOTIFICATION, notify);
pełne przykładowe kody można sprawdzić tutaj:
https://github.com/plateaukao/AutoScreenOnOff/blob/master/src/com/danielkao/autoscreenonoff/SensorMonitorService.java
źródło
not foreground
naforeground created
wiadomość.Wygląda na to, że żadna z istniejących odpowiedzi nie pokazuje, jak obsłużyć cały przypadek - aby rozpocząćForeground, jeśli jest to pierwsze połączenie, ale zaktualizować powiadomienie dla kolejnych połączeń.
Aby wykryć właściwy przypadek, możesz użyć następującego wzorca:
private void notify(@NonNull String action) { boolean isForegroundNotificationVisible = false; NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); StatusBarNotification[] notifications = notificationManager.getActiveNotifications(); for (StatusBarNotification notification : notifications) { if (notification.getId() == FOREGROUND_NOTE_ID) { isForegroundNotificationVisible = true; break; } } Log.v(getClass().getSimpleName(), "Is foreground visible: " + isForegroundNotificationVisible); if (isForegroundNotificationVisible){ notificationManager.notify(FOREGROUND_NOTE_ID, buildForegroundNotification(action)); } else { startForeground(FOREGROUND_NOTE_ID, buildForegroundNotification(action)); } }
Dodatkowo musisz zbudować powiadomienie i kanał jak w innych odpowiedziach:
private Notification buildForegroundNotification(@NonNull String action) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { createNotificationChannel(); } //Do any customization you want here String title; if (ACTION_STOP.equals(action)) { title = getString(R.string.fg_notitifcation_title_stopping); } else { title = getString(R.string.fg_notitifcation_title_starting); } //then build the notification return new NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle(title) .setOngoing(true) .build(); } @RequiresApi(Build.VERSION_CODES.O) private void createNotificationChannel(){ NotificationChannel chan = new NotificationChannel(CHANNEL_ID, getString(R.string.fg_notification_channel), NotificationManager.IMPORTANCE_DEFAULT); chan.setLightColor(Color.RED); chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); assert manager != null; manager.createNotificationChannel(chan); }
źródło