Android'de bir ön plan hizmeti için bildirim metnini nasıl güncellerim?


133

Android'de bir ön plan hizmet kurulumum var. Bildirim metnini güncellemek istiyorum. Hizmeti aşağıda gösterildiği gibi oluşturuyorum.

Bu ön plan hizmetinde ayarlanan bildirim metnini nasıl güncelleyebilirim? Bildirimi güncellemek için en iyi uygulama nedir? Herhangi bir örnek kod takdir edilecektir.

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);

    }

Hizmeti aşağıda gösterildiği gibi ana faaliyetimde oluşturuyorum:

    // Start Notification Service
    Intent serviceIntent = new Intent(this, NotificationService.class);
    startService(serviceIntent);

Yanıtlar:


61

Bu senaryoyu denememiş olsam da startForeground(), aynı benzersiz kimlik ve Notificationyeni bilgilerle tekrar arama yapmanın işe yarayacağını düşünürdüm.

Güncelleme: Yorumlara bağlı olarak, bildirimi güncellemek için NotifcationManager'ı kullanmanız gerekir ve hizmetiniz ön plan modunda kalmaya devam eder. Aşağıdaki cevaba bir göz atın.


1
Yine de bunu Faaliyetimden nasıl adlandıracağıma dair bir örnek verebilir misiniz? Ön plan hizmetimde yöntemleri nasıl arayacağım konusunda iyi bir örnek bulamadım.
Luke

1
@Luke: Bir hizmeti kullanmak için herhangi bir sayıda model var ve sizinkinin neyi takip ettiği hakkında hiçbir fikrim yok. startService()Servise bir komut iletmek için arıyorsanız startService(), metnini güncellemesini söylemek için tekrar aramanız yeterlidir. Veya arama yapıyorsanız bindService(), hizmetin metnini güncellemesini sağlamak için API'nize bir yöntem ekleyin. Ya da, metni güncelleyip güncellememe kararını hizmetin kendisi mi vermesi gerektiğini düşünün. Veya belki de metin, SharedPeferencehizmetin bir dinleyicisinin olduğu bir metindir . Özet olarak size doğru tavsiyelerde bulunmak imkansızdır.
CommonsWare

9
daha fazla açıklığa kavuşturmak için: cancel()tarafından ayarlanmış bir Bildirim olamaz startForeground(). Hizmetin kendisinin ön plan durumunu kaldırmanız gerekir ( stopForeground()eğer kayan yazı metninin tekrar görünmesini istiyorsanız kullanın. Saatlerimi kaybettim çünkü bu cevaplar bana bunun gerçekten mümkün olduğuna inanmamı
sağladı

4
Açıkça yanlış olduğu için bu yanıta oy verdim : developer.android.com/training/notify-user/managing.html Lütfen @CommonsWare bu yanıtı kaldırmayı düşünün, çünkü yüksek itibar puanınız bu yanıtı "kutsal gerçek" yapıyor gündelik tarayıcı. Teşekkürler.
HYS

2
Benim için işe yaramadı (önceki bir projede aynı yöntemi kullandığımı hatırlamama rağmen). Kullanmak NotificationManagerbeklediğim gibi çalıştı.
user149408

224

StartForeground () tarafından ayarlanan bir Bildirimi güncellemek istediğinizde, yeni bir bildirim oluşturun ve ardından bunu bildirmek için NotificationManager'ı kullanın.

Kilit nokta, aynı bildirim kimliğini kullanmaktır.

Bildirimi güncellemek için tekrar tekrar startForeground () çağırma senaryosunu test etmedim, ancak NotificationManager.notify'ı kullanmanın daha iyi olacağını düşünüyorum.

Bildirimi güncellemek, Hizmeti ön plandaki durumdan KALDIRMAZ (bu yalnızca stopForground çağrılarak yapılabilir);

Misal:

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);
}

dokümantasyon devletler

Güncellenmesi için bir bildirim ayarlamak için arayarak bir bildirim kimliği verin NotificationManager.notify(). Bu bildirimi yayınladıktan sonra güncellemek için, bir NotificationCompat.Buildernesneyi güncelleyin veya oluşturun, ondan bir nesne oluşturun Notificationve Notificationdaha önce kullandığınız aynı kimlikle verin. Önceki bildirim hala görünüyorsa, sistem bunu Notificationnesnenin içeriğinden günceller . Önceki bildirim reddedilmişse, bunun yerine yeni bir bildirim oluşturulur.


35
BU DOĞRU CEVAP! Yukarıdaki cevap çok yanlış ve yanıltıcıdır. Aptalca bir bildirimi güncellemek için hizmetinizi yeniden başlatmanız gerekmez.
Radu

7
@Radu Bunun en uygun cevap olduğunu kabul etsem de (Commonsware'in cevabının aldığı biraz daha uzun kod yolunu önler), Commonsware'in cevabının ne yaptığı konusunda yanılıyorsunuz - start / stopForegound hizmeti başlatmaz / durdurmaz, sadece ön planını etkiler .
Stevie

@ Stevie Stevie için teşekkürler, muhtemelen haklısın. Yine de ben bununla uğraşmam!
Radu

Arama notify()veya startForeground()aramaya hem kurşun onStartCommand().
M. Reza Nasirloo

10
NotificationManagerİle gösterilen bir bildirimi güncellemek için kullanmanın sorunu startForeground, aramanın stopForegroundartık bildirimi kaldırmayacağıdır. startForegroundBu sorunu ortadan kaldırmak için başka bir çağrı ile güncellemek .
Tad

22

Luca Manzo cevabını Android 8.0+ sürümünde iyileştirmek, bildirimi güncellerken ses çıkarır ve Uyarı olarak gösterilir.
eklemeniz gerektiğini önlemek içinsetOnlyAlertOnce(true)

yani kod:

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);
}

Günümü kurtardın. Teşekkürler
Rubén Viguera

2
Eksik anahtar kelime, olmalıdırnew NotificationChannel
7hny

5

işte bunu hizmetinizde yapmak için kod . Yeni bir bildirim oluşturun, ancak bildirim yöneticisinden startForeground'da kullandığınız aynı bildirim kimliğini bildirmesini isteyin.

Notification notify = createNotification();
final NotificationManager notificationManager = (NotificationManager) getApplicationContext()
    .getSystemService(getApplicationContext().NOTIFICATION_SERVICE);

notificationManager.notify(ONGOING_NOTIFICATION, notify);

tam örnek kodlar için burayı kontrol edebilirsiniz:

https://github.com/plateaukao/AutoScreenOnOff/blob/master/src/com/danielkao/autoscreenonoff/SensorMonitorService.java


Bunun startService'in ön plan durumunu koruyacağından emin değilim.
Martin Marconcini

@Daniel Kao Çözümünüz bir ön plan hizmeti
başlatmıyor

4
Yanılıyorsam düzeltin ama bu yanıta oy veren insanlar lütfen sorunun ne olduğu konusunda daha açıklayıcı olabilir mi? Soru, bir Ön Plan hizmetinin nasıl başlatılacağını değil, bir ön plan hizmetinin bildiriminin nasıl güncelleneceğini soruyor. Bu, insanların işe yaradığını kabul ettiği ve ön plan durumunu sürdürdüğü Luca ile etkin bir şekilde aynı cevaptır.
TheIT

@ TheIT Çalışmıyor. Bildirim durumu mesaj not foregroundiçin olur foreground created.
Vyacheslav

1
StartForeground () zaten çağrıldığı için bu , yinelenen bir bildirimle sonuçlanır .
IgorGanapolsky

2

Görünüşe göre mevcut yanıtların hiçbiri tüm vakanın nasıl ele alınacağını göstermiyor - ilk çağrı ise Ön Plan'ı başlatmak, ancak sonraki çağrılar için bildirimi güncellemek.

Doğru durumu tespit etmek için aşağıdaki modeli kullanabilirsiniz:

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));
    }
}

Ek olarak, diğer cevaplarda olduğu gibi bildirimi ve kanalı oluşturmanız gerekir:

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);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.