Разрешить отмену уведомления после вызова stopForeground (false) - программирование
Подтвердить что ты не робот

Разрешить отмену уведомления после вызова stopForeground (false)

У меня есть служба Media, которая использует startForeground() для отображения уведомления при запуске воспроизведения. Он имеет кнопки паузы/остановки при воспроизведении, кнопки воспроизведения/остановки во время паузы.

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
// setup...

Notification n = mBuilder.build();

if (state == State.Playing) {
    startForeground(mId, n);
}
else {
    stopForeground(false);
    mNotificationManager.notify(mId, n);        
}

Проблема заключается в том, когда я показываю/обновляю уведомление в этом приостановленном состоянии, вам должно быть разрешено удалить его. mBuilder.setOngoing(false) кажется, не имеет эффекта, поскольку предыдущий startForeground переопределяет его.

Вызов stopForeground(true); с тем же кодом работает так, как ожидалось, но уведомление мигает, когда оно уничтожается и воссоздается. Есть ли способ "обновить" уведомление, созданное из startForeground, чтобы его можно было удалить после вызова stop?

Изменить: В соответствии с запросом здесь полный код, создающий уведомление. createNotification вызывается всякий раз, когда служба воспроизводится или приостанавливается.

private void createNotification() {
    NotificationCompat.Builder mBuilder = 
            new NotificationCompat.Builder(this)
    .setSmallIcon(R.drawable.ic_launcher)
    .setContentTitle("No Agenda")
    .setContentText("Live stream");

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
    {
        if (state == State.Playing) {
            Intent pauseIntent = new Intent(this, MusicService.class);
            pauseIntent.setAction(ACTION_PAUSE);
            PendingIntent pausePendingIntent =     PendingIntent.getService(MusicService.this, 0, pauseIntent, 0);              

            mBuilder.addAction(R.drawable.pause, "Pause", pausePendingIntent);
            //mBuilder.setOngoing(true);
        }
        else if (state == State.Paused) {
            Intent pauseIntent = new Intent(this, MusicService.class);
            pauseIntent.setAction(ACTION_PAUSE);
            PendingIntent pausePendingIntent =  PendingIntent.getService(MusicService.this, 0, pauseIntent, 0);

            mBuilder.addAction(R.drawable.play, "Play", pausePendingIntent);
            mBuilder.setOngoing(false);
        }

        Intent stopIntent = new Intent(this, MusicService.class);
        stopIntent.setAction(ACTION_STOP);
        PendingIntent stopPendingIntent = PendingIntent.getService(MusicService.this, 0, stopIntent, 0);

        setNotificationPendingIntent(mBuilder);
        mBuilder.addAction(R.drawable.stop, "Stop", stopPendingIntent);
    }
    else
    {
        Intent resultIntent = new Intent(this, MainActivity.class);
        PendingIntent intent = PendingIntent.getActivity(this, 0, resultIntent, 0);

        mBuilder.setContentIntent(intent);
    }

    Notification n = mBuilder.build();

    if (state == State.Playing) {
        startForeground(mId, n);
    }
    else {
        stopForeground(true);
        mNotificationManager.notify(mId, n);
    }
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setNotificationPendingIntent(NotificationCompat.Builder mBuilder) {
    Intent resultIntent = new Intent(this, MainActivity.class);

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    stackBuilder.addParentStack(MainActivity.class);
    stackBuilder.addNextIntent(resultIntent);

    PendingIntent resultPendingIntent =
            stackBuilder.getPendingIntent(
                0,
                PendingIntent.FLAG_UPDATE_CURRENT
            );

    mBuilder.setContentIntent(resultPendingIntent);
}

Последующее редактирование:

В одном из приведенных ниже комментариев упоминается, что ответ может быть "хрупким", а с момента выхода Android 4.3 поведение startForeground изменилось. startForeground заставит ваше приложение показывать уведомление на переднем плане, а метод следует просто вызвать с уведомлением, чтобы показать. Я не тестировал, но принятый ответ может работать не так, как предполагалось.

Что касается остановки мигания при вызове stopForeground, я не думаю, что это стоит бороться с фреймворком.

Там некоторые дополнительная информация об изменении уведомлений Android 4.3 здесь.

4b9b3361

Ответ 1

Вы можете использовать другой подход.
Поскольку вы должны использовать переднюю службу для такой задачи (воспроизведение мультимедиа), я предлагаю вам продолжать делать start foreground(), но вместо того, чтобы передавать ему уведомление, просто установите id 0 и уведомление null, как это, startForeground(0, null);.

Таким образом, служба переднего плана не будет отображать уведомления.

Теперь для ваших целей вы можете использовать регулярные уведомления и обновлять свои состояния (текущее, макет, текст и т.д.), таким образом, вы не зависите от поведения уведомления об обслуживании переднего плана.

Надеюсь, что это поможет.

Ответ 2

В соответствии с docs это поведение по дизайну до Lollipop

Приложения, нацеленные на этот или более поздний выпуск, получат эти новые изменения в поведении:

...

  • Вызов Service.stopForeground с методом removeNotification false изменит уведомление по-прежнему, чтобы оно больше не было принудительным.

Ответ 3

Вместо stopService(true) вызов stopService(false) будет сохранять уведомление как есть (без текущего состояния), если он не будет удален пользователем или удален программно или если служба перестанет работать. Поэтому просто вызовите stopService (false) и обновите уведомление, чтобы показать приостановленное состояние, и теперь уведомление может быть отклонено пользователем. Это также предотвращает мигание, поскольку мы не воссоздаем уведомление.