Android에서 포 그라운드 서비스의 알림 텍스트를 어떻게 업데이트합니까?


133

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

답변:


61

이 시나리오를 시도하지는 않았지만 startForeground()동일한 고유 ID와 Notification새 정보를 사용하여 다시 호출하면 효과가 있다고 생각합니다 .

업데이트 : 주석에 따라 NotifcationManager를 사용하여 알림을 업데이트해야하며 서비스는 계속 포 그라운드 모드로 유지됩니다. 아래 답변을보십시오.


1
그래도 내 활동에서 어떻게 호출하는지 예를 들어 주시겠습니까? 포 그라운드 서비스에서 메소드를 호출하는 방법에 대한 좋은 샘플을 찾을 수 없었습니다.
누가

1
@Luke : 서비스를 사용하는 데는 여러 가지 패턴이 있으며, 어떤 패턴을 따르는 지 잘 모르겠습니다. startService()서비스에 명령을 전달하기 위해 호출 하는 경우 startService()다시 호출 하여 텍스트를 업데이트하도록 지시하십시오. 또는를 호출하는 경우 bindService()서비스가 텍스트를 업데이트하도록 메소드를 API에 추가하십시오. 또는 서비스 자체가 텍스트 업데이트 여부를 결정하는 것이되어야하는지 고려하십시오. 또는 텍스트는 SharedPeference서비스에 리스너가있는 것입니다. 초록에 정확한 조언을 제공하는 것은 불가능합니다.
CommonsWare

9
더 명확히하기 위해 :에 cancel()의해 설정된 알림을 설정할 수 없습니다 startForeground(). 서비스 자체의 전경 상태를 제거해야합니다 ( stopForeground()티커 텍스트를 다시 표시하려면 사용하십시오.이 답변으로 인해 실제로 가능하다고 생각했기 때문에 시간을 잃었습니다.
slinden77

4
이 답변은 명백히 잘못 되었으므로이 답변을 다운 보트했습니다 . developer.android.com/training/notify-user/managing.html 제발 @CommonsWare는이 답변을 제거하는 것을 고려하십시오. 캐주얼 브라우저. 감사.
HYS

2
나를 위해 작동하지 않았습니다 (이전 프로젝트 에서이 동일한 방법을 사용하는 것을 기억합니다). 사용 NotificationManager나는 예상대로 일했다.
user149408

224

startForeground ()로 설정된 알림을 업데이트하려면 새 알림을 작성한 다음 NotificationManager를 사용하여 알림을 보내십시오.

핵심은 동일한 알림 ID를 사용하는 것입니다.

알림을 업데이트하기 위해 startForeground ()를 반복적으로 호출하는 시나리오를 테스트하지는 않았지만 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);
}

문서의 상태

업데이트 할 수 있도록 알림을 설정하려면을 호출하여 알림 ID로 알림을 발행하십시오 NotificationManager.notify(). 이 알림을 발행 한 후 업데이트하려면, NotificationCompat.Builder오브젝트를 업데이트 또는 작성하고, 오브젝트를 빌드하고 Notification, Notification이전에 사용한 것과 동일한 ID로 발행하십시오 . 이전 알림이 여전히 표시되면 시스템은 Notification객체 의 내용에서 알림을 업데이트 합니다. 이전 알림이 해제 된 경우 대신 새 알림이 작성됩니다.


35
이것은 올바른 답변입니다! 위의 답변은 매우 잘못되었으며 오도의 소지가 있습니다. 바보 같은 알림을 업데이트하기 위해 서비스를 다시 시작할 필요는 없습니다.
Radu

7
@Radu 나는 이것이 최적의 답변이라는 것에 동의하지만 (Commonsware의 답변에 의해 약간 더 긴 코드 경로를 피합니다) Commonsware의 답변이 무엇인지 잘못 알고 있습니다-start / stopForegound는 서비스를 시작 / 중지하지 않지만 전경에 영향을 미칩니다. .
Stevie

@ Stevie 그 Stevie 주셔서 감사합니다 아마 당신이 맞을 것입니다. 아직도 나는 그것도 엉망으로하지 않을 것입니다!
Radu

notify()또는 startForeground()둘 다를 호출하면 call로 이어 onStartCommand()집니다.
M. Reza Nasirloo

10
NotificationManager표시되는 알림을 업데이트하는 데 사용하는 데 문제 startForeground가 있으면 호출 stopForeground해도 더 이상 알림이 제거되지 않습니다. startForeground이 문제 를 피하기 위해 다른 호출로 업데이트하십시오 .
Tad

21

알림을 업데이트 할 때 안드로이드 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);
}

당신은 내 하루를 구했습니다. 감사합니다
Rubén Viguera

1
누락 된 키워드가 있어야합니다new NotificationChannel
7 시간

5

서비스에서 수행하는 코드 는 다음과 같습니다 . 새 알림을 작성하지만 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


이것이 startService의 포 그라운드 상태를 유지할지 확실하지 않습니다.
Martin Marconcini 2016 년

@Daniel Kao 솔루션이 포 그라운드 서비스를 시작하지 않습니다
IgorGanapolsky

4
내가 틀렸다면 정정하되, 사람들이이 답변에 투표하지 않더라도 무엇이 잘못되었는지 설명해 주시겠습니까? 이 질문은 Foreground 서비스를 시작하는 방법이 아니라 포 그라운드 서비스의 알림을 업데이트하는 방법을 묻습니다. 이것은 사람들이 작업에 동의하고 포 그라운드 상태를 유지한다는 Luca와 사실상 같은 대답입니다.
TheIT December

@TheIT 작동하지 않습니다. 알림 상태 not foregroundforeground created메시지가됩니다.
Vyacheslav

1
startForeground () 가 이미 호출 되었으므로 중복 알림이 발생 합니다.
IgorGanapolsky

2

기존 답변 중 전체 사례를 처리하는 방법을 보여주지 않는 것 같습니다. 첫 번째 통화 인 경우 startForeground를 시작하고 후속 통화에 대한 알림을 업데이트하십시오.

다음 패턴을 사용하여 올바른 사례를 감지 할 수 있습니다.

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);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.