Управление аудиофокусом

Два или более приложений Android могут одновременно воспроизводить звук в один и тот же выходной поток, и система смешивает все вместе. Хотя это технически впечатляет, для пользователя это может быть очень неудобно. Чтобы избежать одновременного воспроизведения звука всеми музыкальными приложениями, Android вводит понятие аудиофокуса . Только одно приложение может удерживать аудиофокус одновременно.

Когда вашему приложению необходимо вывести звук, оно должно запросить фокус на воспроизведение звука. Получив фокус, оно может воспроизводить звук. Однако после получения фокуса на воспроизведение звука вы можете потерять возможность его удерживать до окончания воспроизведения. Другое приложение может запросить фокус, что перехватит ваше право на воспроизведение звука. В этом случае ваше приложение должно приостановить воспроизведение или уменьшить громкость, чтобы пользователи могли легче услышать новый источник звука.

В версиях Android до 12 (уровень API 31) управление аудиофокусом не осуществляется системой. Поэтому, хотя разработчикам приложений рекомендуется соблюдать рекомендации по управлению аудиофокусом, если приложение продолжает воспроизводить громкий звук даже после потери аудиофокуса на устройстве под управлением Android 11 (уровень API 30) или ниже, система не может это предотвратить. Однако такое поведение приложения приводит к ухудшению пользовательского опыта и часто заставляет пользователей удалять некорректно работающее приложение.

Хорошо разработанное аудиоприложение должно управлять фокусом на звуке в соответствии со следующими общими рекомендациями:

  • Вызовите requestAudioFocus() непосредственно перед началом воспроизведения и убедитесь, что он возвращает значение AUDIOFOCUS_REQUEST_GRANTED . Вызовите requestAudioFocus() в функции обратного вызова onPlay() вашей медиасессии.

  • Когда другое приложение получает аудиоактив, остановите или приостановите воспроизведение, или уменьшите (то есть, приглушите) громкость.

  • Когда воспроизведение останавливается (например, когда в приложении больше нечего воспроизводить), отмените фокус на воспроизведении звука. Вашему приложению не обязательно отменять фокус на воспроизведении звука, если пользователь приостанавливает воспроизведение, но оно может возобновить его позже.

  • Используйте AudioAttributes для описания типа воспроизводимого вашим приложением звука. Например, для приложений, воспроизводящих речь, укажите CONTENT_TYPE_SPEECH .

Обработка фокуса на звуке различается в зависимости от версии установленной операционной системы Android:

Android 12 (уровень API 31) или более поздняя версия.
Управление аудиофокусировкой осуществляется системой. Система принудительно приостанавливает воспроизведение звука из одного приложения, когда другое приложение запрашивает аудиофокусировку. Система также отключает воспроизведение звука при входящем звонке.
Android 8.0 (уровень API 26) до Android 11 (уровень API 30)
Управление фокусом звука не осуществляется системой, но включает в себя некоторые изменения, внесенные начиная с Android 8.0 (уровень API 26).
Android 7.1 (уровень API 25) и ниже
Управление фокусом на аудио не осуществляется системой, и приложения управляют фокусом на аудио с помощью функций requestAudioFocus() и abandonAudioFocus() .

Акцент на звуке в Android 12 и выше

Приложение для воспроизведения мультимедиа или игры, использующее аудиофокус, не должно воспроизводить звук после потери фокуса. В Android 12 (уровень API 31) и выше система обеспечивает такое поведение. Когда приложение запрашивает аудиофокус, в то время как другое приложение находится в фокусе и воспроизводит звук, система принудительно выводит звук из воспроизводящего приложения. Добавление эффекта затухания обеспечивает более плавный переход при переключении между приложениями.

Такое затухание происходит при выполнении следующих условий:

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

  2. Второе приложение запрашивает фокус на звуке с помощью AudioManager.AUDIOFOCUS_GAIN .

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

Существующие модели поведения фокусировки звука

Вам также следует знать о других случаях, связанных с изменением фокуса звука.

Автоматическое приседание

Функция автоматического приглушения звука (временное снижение уровня звука одного приложения для обеспечения четкого звучания другого) была введена в Android 8.0 (уровень API 26).

Благодаря тому, что система реализует функцию приглушения звука, вам не нужно будет реализовывать её в своём приложении.

Автоматическое приглушение звука также происходит, когда звуковое уведомление перехватывает фокус у воспроизводимого приложения. Начало воспроизведения уведомления синхронизируется с концом процесса приглушения.

Автоматическое приглушание звука происходит при выполнении следующих условий:

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

    • Приложение успешно запросило фокусировку звука с любым уровнем усиления .
    • Приложение не воспроизводит аудио с типом контента AudioAttributes.CONTENT_TYPE_SPEECH .
    • Приложение не установило AudioFocusRequest.Builder.setWillPauseWhenDucked(true) .
  2. Второе приложение запрашивает фокус на звуке с помощью AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK .

При выполнении этих условий аудиосистема приглушает все активные проигрыватели первого приложения, пока второе приложение находится в фокусе. Когда второе приложение теряет фокус, оно возвращает их в исходное состояние. Первое приложение не получает уведомления о потере фокуса, поэтому ему ничего не нужно делать.

Обратите внимание, что автоматическое приглушение звука не выполняется, когда пользователь слушает речевой контент, поскольку пользователь может пропустить некоторые фрагменты программы. Например, голосовые подсказки для навигации по дорогам не приглушаются.

Отключить воспроизведение текущего звука для входящих телефонных звонков

Некоторые приложения работают некорректно и продолжают воспроизводить звук во время телефонных звонков. В такой ситуации пользователю приходится находить и отключать звук или закрывать проблемное приложение, чтобы услышать звонок. Чтобы предотвратить это, система может отключать звук других приложений во время входящего звонка. Система активирует эту функцию, когда поступает входящий телефонный звонок и приложение соответствует следующим условиям:

  • Приложение имеет либо атрибут использования AudioAttributes.USAGE_MEDIA , либо AudioAttributes.USAGE_GAME .
  • Приложение успешно запросило фокусировку на аудио (любое усиление фокуса) и воспроизводит звук.

Если приложение продолжает воспроизведение во время звонка, его воспроизведение отключается до завершения звонка. Однако, если приложение начинает воспроизведение во время звонка, этот плеер не отключается, если предположить, что пользователь запустил воспроизведение намеренно.

Акцент на звуке в Android 8.0 — Android 11

Начиная с Android 8.0 (уровень API 26), при вызове requestAudioFocus() необходимо передать параметр AudioFocusRequest . AudioFocusRequest содержит информацию об аудиоконтексте и возможностях вашего приложения. Система использует эту информацию для автоматического управления усилением и потерей аудиофокуса. Чтобы освободить аудиофокус, вызовите метод abandonAudioFocusRequest() , который также принимает AudioFocusRequest в качестве аргумента. Используйте один и тот же экземпляр AudioFocusRequest как при запросе, так и при освобождении фокуса.

Для создания объекта AudioFocusRequest используйте AudioFocusRequest.Builder . Поскольку в запросе на фокусировку всегда должен быть указан тип запроса, этот тип указывается в конструкторе построителя. Используйте методы построителя для установки остальных полей запроса.

Поле FocusGain обязательно для заполнения; все остальные поля необязательны.

Метод Примечания
setFocusGain() Это поле обязательно для каждого запроса. Оно принимает те же значения, что и durationHint использовавшийся в вызове requestAudioFocus() до Android 8.0: AUDIOFOCUS_GAIN , AUDIOFOCUS_GAIN_TRANSIENT , AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK или AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE .
setAudioAttributes() AudioAttributes описывают сценарий использования вашего приложения. Система учитывает их при получении и потере аудиофокуса приложением. Атрибуты заменяют понятие типа потока. В Android 8.0 (уровень API 26) и более поздних версиях типы потоков для любых операций, кроме регулировки громкости, считаются устаревшими. Используйте те же атрибуты в запросе фокуса, что и в вашем аудиоплеере (как показано в примере после этой таблицы).

Сначала укажите атрибуты с помощью AudioAttributes.Builder , а затем используйте этот метод для присвоения атрибутов запросу.

Если не указано иное, по умолчанию используется AudioAttributes.USAGE_MEDIA AudioAttributes

setWillPauseWhenDucked() Когда другое приложение запрашивает фокус с параметром AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK , приложение, находящееся в фокусе, обычно не получает обратный вызов onAudioFocusChange() поскольку система может выполнить приглушение звука самостоятельно . Если вам нужно приостановить воспроизведение, а не приглушать звук, вызовите setWillPauseWhenDucked(true) и создайте и установите OnAudioFocusChangeListener , как описано в разделе автоматического приглушения звука .
setAcceptsDelayedFocusGain() Запрос на получение фокуса для воспроизведения звука может завершиться неудачей, если фокус заблокирован другим приложением. Этот метод включает в себя отложенное получение фокуса : возможность асинхронного получения фокуса, когда он становится доступным.

Обратите внимание, что отложенное получение фокуса работает только в том случае, если вы также укажете AudioManager.OnAudioFocusChangeListener в аудиозапросе, поскольку вашему приложению необходимо получить обратный вызов, чтобы узнать, что фокус был предоставлен.

setOnAudioFocusChangeListener() Объект OnAudioFocusChangeListener требуется только в том случае, если вы также указываете willPauseWhenDucked(true) или setAcceptsDelayedFocusGain(true) в запросе.

Существует два способа установки обработчика: один с аргументом `handler`, другой без него. Обработчиком называется поток, в котором выполняется обработчик. Если вы не указываете обработчик, используется обработчик, связанный с основным Looper .

В следующем примере показано, как использовать AudioFocusRequest.Builder для создания AudioFocusRequest , а также для запроса и отмены фокуса на аудиопотоке:

Котлин

// initializing variables for audio focus and playback management
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {
    setAudioAttributes(AudioAttributes.Builder().run {
        setUsage(AudioAttributes.USAGE_GAME)
        setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        build()
    })
    setAcceptsDelayedFocusGain(true)
    setOnAudioFocusChangeListener(afChangeListener, handler)
    build()
}
val focusLock = Any()

var playbackDelayed = false
var playbackNowAuthorized = false

// requesting audio focus and processing the response
val res = audioManager.requestAudioFocus(focusRequest)
synchronized(focusLock) {
    playbackNowAuthorized = when (res) {
        AudioManager.AUDIOFOCUS_REQUEST_FAILED -> false
        AudioManager.AUDIOFOCUS_REQUEST_GRANTED -> {
            playbackNow()
            true
        }
        AudioManager.AUDIOFOCUS_REQUEST_DELAYED -> {
            playbackDelayed = true
            false
        }
        else -> false
    }
}

// implementing OnAudioFocusChangeListener to react to focus changes
override fun onAudioFocusChange(focusChange: Int) {
    when (focusChange) {
        AudioManager.AUDIOFOCUS_GAIN ->
            if (playbackDelayed || resumeOnFocusGain) {
                synchronized(focusLock) {
                    playbackDelayed = false
                    resumeOnFocusGain = false
                }
                playbackNow()
            }
        AudioManager.AUDIOFOCUS_LOSS -> {
            synchronized(focusLock) {
                resumeOnFocusGain = false
                playbackDelayed = false
            }
            pausePlayback()
        }
        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
            synchronized(focusLock) {
                // only resume if playback is being interrupted
                resumeOnFocusGain = isPlaying()
                playbackDelayed = false
            }
            pausePlayback()
        }
        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
            // ... pausing or ducking depends on your app
        }
    }
}

Java

// initializing variables for audio focus and playback management
audioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
playbackAttributes = new AudioAttributes.Builder()
        .setUsage(AudioAttributes.USAGE_GAME)
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .build();
focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
        .setAudioAttributes(playbackAttributes)
        .setAcceptsDelayedFocusGain(true)
        .setOnAudioFocusChangeListener(afChangeListener, handler)
        .build();
final Object focusLock = new Object();

boolean playbackDelayed = false;
boolean playbackNowAuthorized = false;

// requesting audio focus and processing the response
int res = audioManager.requestAudioFocus(focusRequest);
synchronized(focusLock) {
    if (res == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
        playbackNowAuthorized = false;
    } else if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
        playbackNowAuthorized = true;
        playbackNow();
    } else if (res == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
        playbackDelayed = true;
        playbackNowAuthorized = false;
    }
}

// implementing OnAudioFocusChangeListener to react to focus changes
@Override
public void onAudioFocusChange(int focusChange) {
    switch (focusChange) {
        case AudioManager.AUDIOFOCUS_GAIN:
            if (playbackDelayed || resumeOnFocusGain) {
                synchronized(focusLock) {
                    playbackDelayed = false;
                    resumeOnFocusGain = false;
                }
                playbackNow();
            }
            break;
        case AudioManager.AUDIOFOCUS_LOSS:
            synchronized(focusLock) {
                resumeOnFocusGain = false;
                playbackDelayed = false;
            }
            pausePlayback();
            break;
        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
            synchronized(focusLock) {
                // only resume if playback is being interrupted
                resumeOnFocusGain = isPlaying();
                playbackDelayed = false;
            }
            pausePlayback();
            break;
        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
            // ... pausing or ducking depends on your app
            break;
        }
    }
}

Автоматическое приседание

В Android 8.0 (уровень API 26), когда другое приложение запрашивает фокус с AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK система может приглушать и восстанавливать громкость без вызова функции обратного вызова onAudioFocusChange() этого приложения.

Хотя автоматическое приглушение звука является допустимым поведением для приложений воспроизведения музыки и видео, оно бесполезно при воспроизведении озвученного контента, например, в приложении для аудиокниг. В этом случае приложение должно вместо этого приостанавливать воспроизведение.

Если вы хотите, чтобы ваше приложение приостанавливало воспроизведение при нажатии кнопки приглушения, а не уменьшало громкость автоматически, создайте OnAudioFocusChangeListener с методом обратного вызова onAudioFocusChange() , реализующим желаемое поведение паузы/возобновления. Вызовите setOnAudioFocusChangeListener() для регистрации обработчика и вызовите setWillPauseWhenDucked(true) чтобы указать системе использовать ваш обратный вызов вместо автоматического приглушения.

Отложенное усиление фокусировки

Иногда система не может удовлетворить запрос на получение аудиофокуса, поскольку фокус «заблокирован» другим приложением, например, во время телефонного звонка. В этом случае requestAudioFocus() возвращает AUDIOFOCUS_REQUEST_FAILED . В такой ситуации ваше приложение не должно продолжать воспроизведение звука, поскольку фокус не был получен.

Метод ` setAcceptsDelayedFocusGain(true) позволяет вашему приложению обрабатывать запрос на фокус асинхронно. При установке этого флага запрос, отправленный после блокировки фокуса, возвращает AUDIOFOCUS_REQUEST_DELAYED . Когда условие, блокировавшее аудиофокус, перестаёт существовать, например, когда заканчивается телефонный звонок, система удовлетворяет ожидающий запрос на фокус и вызывает метод onAudioFocusChange() для уведомления вашего приложения.

Для обработки задержки получения фокуса необходимо создать обработчик OnAudioFocusChangeListener с методом обратного вызова onAudioFocusChange() , реализующим желаемое поведение, и зарегистрировать обработчик, вызвав setOnAudioFocusChangeListener() .

Акцент на звуке в Android 7.1 и более ранних версиях.

При вызове функции requestAudioFocus() необходимо указать подсказку о длительности воспроизведения, которая может быть учтена другим приложением, в данный момент удерживающим фокус и воспроизводящим аудио:

  • Запросите постоянный фокус на воспроизведение звука ( AUDIOFOCUS_GAIN ), если вы планируете воспроизводить звук в обозримом будущем (например, при воспроизведении музыки) и ожидаете, что предыдущий обладатель фокуса на воспроизведение звука прекратит работу.
  • Запросите временный фокус ( AUDIOFOCUS_GAIN_TRANSIENT ), если вы ожидаете воспроизведения звука в течение короткого времени и планируете приостановить воспроизведение предыдущего трека.
  • Запросить временный фокус с приглушением ( AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK ) указывает на то, что вы ожидаете воспроизведения звука только в течение короткого времени и что предыдущий владелец фокуса может продолжать воспроизведение, если он «приглушает» (уменьшает) свой аудиовыход. Оба аудиовыхода смешиваются в аудиопоток. Приглушение особенно подходит для приложений, которые используют аудиопоток периодически, например, для голосовых подсказок водителя.

Для метода requestAudioFocus() также требуется обработчик AudioManager.OnAudioFocusChangeListener . Этот обработчик следует создать в той же активности или службе, которая управляет вашей медиасессией. Он реализует функцию обратного вызова onAudioFocusChange() , которую ваше приложение получает, когда другое приложение получает или теряет фокус на аудиопотоке.

Следующий фрагмент кода запрашивает постоянный аудиофокус на потоке STREAM_MUSIC и регистрирует обработчик OnAudioFocusChangeListener для обработки последующих изменений аудиофокуса. (Обработчик событий изменения фокуса описан в разделе «Реагирование на изменение аудиофокуса ».)

Котлин

audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
lateinit var afChangeListener AudioManager.OnAudioFocusChangeListener

...
// Request audio focus for playback
val result: Int = audioManager.requestAudioFocus(
        afChangeListener,
        // Use the music stream.
        AudioManager.STREAM_MUSIC,
        // Request permanent focus.
        AudioManager.AUDIOFOCUS_GAIN
)

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // Start playback
}

Java

AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
AudioManager.OnAudioFocusChangeListener afChangeListener;

...
// Request audio focus for playback
int result = audioManager.requestAudioFocus(afChangeListener,
                             // Use the music stream.
                             AudioManager.STREAM_MUSIC,
                             // Request permanent focus.
                             AudioManager.AUDIOFOCUS_GAIN);

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // Start playback
}

После завершения воспроизведения вызовите метод abandonAudioFocus() .

Котлин

audioManager.abandonAudioFocus(afChangeListener)

Java

// Abandon audio focus when playback complete
audioManager.abandonAudioFocus(afChangeListener);

Это уведомляет систему о том, что вам больше не требуется фокус, и отменяет регистрацию связанного обработчика OnAudioFocusChangeListener . Если вы запрашивали временный фокус, это уведомит приложение, которое приостановило или приглушило звук, о том, что оно может продолжить воспроизведение или восстановить громкость.

Реагирование на изменение фокуса звука

Когда приложение получает аудиофокус, оно должно иметь возможность освободить его, когда другое приложение запросит аудиофокус для себя. В этом случае ваше приложение получает вызов метода onAudioFocusChange() в объекте AudioFocusChangeListener , который вы указали при вызове метода requestAudioFocus() .

Параметр focusChange передаваемый в метод onAudioFocusChange() указывает на тип происходящего изменения. Он соответствует подсказке длительности, используемой приложением, получающим фокус. Ваше приложение должно соответствующим образом реагировать.

Кратковременная потеря фокуса
Если смена фокуса кратковременна ( AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK или AUDIOFOCUS_LOSS_TRANSIENT ), ваше приложение должно приглушить звук (если вы не полагаетесь на автоматическое приглушение ) или приостановить воспроизведение, но в остальном сохранить то же состояние.

При кратковременной потере фокуса на воспроизведении звука следует продолжать отслеживать изменения фокуса и быть готовым возобновить нормальное воспроизведение, когда фокус восстановится. Когда блокирующее приложение теряет фокус, вы получаете обратный вызов ( AUDIOFOCUS_GAIN ). В этот момент вы можете восстановить громкость до нормального уровня или перезапустить воспроизведение.

Постоянная потеря концентрации
Если потеря фокуса на воспроизведении звука является постоянной ( AUDIOFOCUS_LOSS ), значит, звук воспроизводится другим приложением. Ваше приложение должно немедленно приостановить воспроизведение, поскольку оно никогда не получит обратный вызов AUDIOFOCUS_GAIN . Для возобновления воспроизведения пользователь должен выполнить явное действие, например, нажать кнопку воспроизведения в уведомлении или пользовательском интерфейсе приложения.

Приведённый ниже фрагмент кода демонстрирует, как реализовать обработчик событий OnAudioFocusChangeListener и его функцию обратного вызова onAudioFocusChange() . Обратите внимание на использование Handler для задержки вызова функции остановки при окончательной потере фокуса на аудиопотоке.

Котлин

private val handler = Handler()
private val afChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange ->
    when (focusChange) {
        AudioManager.AUDIOFOCUS_LOSS -> {
            // Permanent loss of audio focus
            // Pause playback immediately
            mediaController.transportControls.pause()
            // Wait 30 seconds before stopping playback
            handler.postDelayed(delayedStopRunnable, TimeUnit.SECONDS.toMillis(30))
        }
        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
            // Pause playback
        }
        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
            // Lower the volume, keep playing
        }
        AudioManager.AUDIOFOCUS_GAIN -> {
            // Your app has been granted audio focus again
            // Raise volume to normal, restart playback if necessary
        }
    }
}

Java

private Handler handler = new Handler();
AudioManager.OnAudioFocusChangeListener afChangeListener =
  new AudioManager.OnAudioFocusChangeListener() {
    public void onAudioFocusChange(int focusChange) {
      if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
        // Permanent loss of audio focus
        // Pause playback immediately
        mediaController.getTransportControls().pause();
        // Wait 30 seconds before stopping playback
        handler.postDelayed(delayedStopRunnable,
          TimeUnit.SECONDS.toMillis(30));
      }
      else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
        // Pause playback
      } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
        // Lower the volume, keep playing
      } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
        // Your app has been granted audio focus again
        // Raise volume to normal, restart playback if necessary
      }
    }
  };

Обработчик использует объект Runnable , который выглядит следующим образом:

Котлин

private var delayedStopRunnable = Runnable {
    mediaController.transportControls.stop()
}

Java

private Runnable delayedStopRunnable = new Runnable() {
    @Override
    public void run() {
        getMediaController().getTransportControls().stop();
    }
};

Чтобы гарантировать, что отложенная остановка не сработает, если пользователь перезапустит воспроизведение, вызывайте метод mHandler.removeCallbacks(mDelayedStopRunnable) в ответ на любые изменения состояния. Например, вызывайте removeCallbacks() в методах onPlay() , onSkipToNext() и т. д. вашего коллбэка. Также следует вызывать этот метод в методе onDestroy() вашего сервиса при очистке ресурсов, используемых сервисом.