如何更新 Android 中前台服务的通知文本?

发布于 2024-10-30 17:06:22 字数 1019 浏览 1 评论 0原文

我在 Android 中有一个前台服务设置。我想更新通知文本。我正在创建如下所示的服务。

如何更新此前台服务中设置的通知文本?更新通知的最佳做法是什么?任何示例代码将不胜感激。

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

    }

我正在我的主要活动中创建服务,如下所示:

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

I have a foreground service setup in Android. I would like to update the notification text. I am creating the service as shown below.

How can I update the notification text that is setup within this foreground service? What is the best practise for updating the notification? Any sample code would be appreciated.

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

    }

I am creating the service in my main activity as shown below:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浪漫人生路 2024-11-06 17:06:22

当你想更新startForeground()设置的Notification时,只需构建一个新的notification,然后使用NotificationManager来通知它。

关键点是使用相同的通知ID。

我没有测试重复调用startForeground()来更新Notification的场景,但我认为使用NotificationManager.notify会更好。

更新通知不会将服务从前台状态中删除(这只能通过调用 stopForground 来完成);

示例:

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

文档指出

要设置通知以便更新,请使用
通过调用 NotificationManager.notify() 来通知 ID。更新
发出此通知后,更新或创建
NotificationCompat.Builder 对象,从中构建一个 Notification 对象
并使用您之前使用的相同 ID 发出通知
如果之前的通知仍然可见,系统会更新它
来自 Notification 对象的内容。如果之前的
通知已被驳回,已创建新通知
相反。

When you want to update a Notification set by startForeground(), simply build a new notication and then use NotificationManager to notify it.

The key point is to use the same notification id.

I didn't test the scenario of repeatedly calling startForeground() to update the Notification, but I think that using NotificationManager.notify would be better.

Updating the Notification will NOT remove the Service from the foreground status (this can be done only by calling stopForground );

Example:

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

The documentation states

To set up a notification so it can be updated, issue it with a
notification ID by calling NotificationManager.notify(). To update
this notification after you've issued it, update or create a
NotificationCompat.Builder object, build a Notification object from
it, and issue the Notification with the same ID you used previously.
If the previous notification is still visible, the system updates it
from the contents of the Notification object. If the previous
notification has been dismissed, a new notification is created
instead.

软甜啾 2024-11-06 17:06:22

我认为使用相同的唯一 ID 和带有新信息的 Notification 再次调用 startForeground() 会起作用,尽管我还没有尝试过这种情况。

更新:根据评论,您应该使用 NotifcationManager 更新通知,并且您的服务继续保持在前台模式。看看下面的答案。

I would think that calling startForeground() again with the same unique ID and a Notification with the new information would work, though I have not tried this scenario.

Update: Based on the comments, you should use NotifcationManager to update the notification and your service continues to stay in the foreground mode. Take a look at the answer below.

伴随着你 2024-11-06 17:06:22

改进了 Android 8.0+ 中 Luca Manzo 的答案,更新通知时它将发出声音并显示为“平视”。
为了防止您需要添加 setOnlyAlertOnce(true)

所以代码是:

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

Improving on Luca Manzo answer in android 8.0+ when updating the notification it will make sound and show as Heads-up.
to prevent that you need to add setOnlyAlertOnce(true)

so the code is:

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);
}
忘东忘西忘不掉你 2024-11-06 17:06:22

这是在您的服务中执行此操作的代码。创建一个新通知,但要求通知管理器通知您在 startForeground 中使用的相同通知 ID。

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

notificationManager.notify(ONGOING_NOTIFICATION, notify);

有关完整的示例代码,您可以在此处查看:

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

here's the code to do so in your service. Create a new notification, but ask notification manager to notify the same notification id you used in startForeground.

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

notificationManager.notify(ONGOING_NOTIFICATION, notify);

for full sample codes, you can check here:

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

云之铃。 2024-11-06 17:06:22

似乎现有的答案都没有显示如何处理完整的情况 - 如果是第一次调用,则启动Foreground,但更新后续调用的通知。

您可以使用以下模式来检测正确的情况:

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

此外,您需要像其他答案中那样构建通知和通道:

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

It seems none of the existing answers show how to handle the full case - to startForeground if it's the first call but update the notification for subsequent calls.

You can use the following pattern to detect the right case:

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

Additionally you need to build the notification and channel as in other answers:

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文