Audiofokus verwalten

Zwei oder mehr Android-Apps können gleichzeitig Audio auf denselben Ausgabestream ausgeben. Das System mischt alles zusammen. Das ist zwar technisch beeindruckend, kann aber für Nutzer sehr ärgerlich sein. Damit nicht alle Musik-Apps gleichzeitig wiedergegeben werden, gibt es in Android das Konzept des Audio-Fokus. Es kann immer nur eine App den Audiofokus haben.

Wenn Ihre App Audio ausgeben muss, sollte sie den Audiofokus anfordern. Wenn es den Fokus hat, kann es Ton wiedergeben. Nachdem Sie den Audiofokus erhalten haben, können Sie ihn möglicherweise nicht bis zum Ende der Wiedergabe beibehalten. Eine andere App kann den Fokus anfordern, wodurch Ihr Audiofokus unterbrochen wird. In diesem Fall sollte die Wiedergabe in Ihrer App pausiert oder die Lautstärke verringert werden, damit Nutzer die neue Audioquelle besser hören können.

Vor Android 12 (API-Level 31) wird der Audiofokus nicht vom System verwaltet. App-Entwickler werden zwar aufgefordert, die Richtlinien für den Audiofokus einzuhalten, aber wenn eine App weiterhin laut wiedergegeben wird, nachdem sie den Audiofokus auf einem Gerät mit Android 11 (API-Level 30) oder niedriger verloren hat, kann das System dies nicht verhindern. Dieses App-Verhalten führt jedoch zu einer schlechten Nutzererfahrung und kann dazu führen, dass Nutzer die App deinstallieren.

Eine gut gestaltete Audio-App sollte den Audiofokus gemäß den folgenden allgemeinen Richtlinien verwalten:

  • Rufen Sie requestAudioFocus() unmittelbar vor Spielbeginn an und prüfen Sie, ob der Anruf AUDIOFOCUS_REQUEST_GRANTED zurückgibt. Rufen Sie requestAudioFocus() im onPlay()-Callback Ihrer Mediensitzung auf.

  • Wenn eine andere App den Audiofokus erhält, beenden oder pausieren Sie die Wiedergabe oder verringern Sie die Lautstärke.

  • Wenn die Wiedergabe beendet wird (z. B. wenn die App nichts mehr wiederzugeben hat), gib den Audiofokus auf. Ihre App muss den Audiofokus nicht aufgeben, wenn der Nutzer die Wiedergabe pausiert, aber möglicherweise später fortsetzt.

  • Verwenden Sie AudioAttributes, um den Audiotyp zu beschreiben, der in Ihrer App wiedergegeben wird. Geben Sie beispielsweise für Apps, die Sprache wiedergeben, CONTENT_TYPE_SPEECH an.

Die Audiofokussierung wird je nach Android-Version unterschiedlich gehandhabt:

Android 12 (API‑Level 31) oder höher
Der Audiofokus wird vom System verwaltet. Das System erzwingt, dass die Audiowiedergabe einer App ausgeblendet wird, wenn eine andere App den Audiofokus anfordert. Das System schaltet die Audiowiedergabe auch stumm, wenn ein eingehender Anruf eingeht.
Android 8.0 (API-Level 26) bis Android 11 (API-Level 30)
Der Audiofokus wird nicht vom System verwaltet, umfasst aber einige Änderungen, die ab Android 8.0 (API-Level 26) eingeführt wurden.
Android 7.1 (API-Level 25) und niedriger
Der Audiofokus wird nicht vom System verwaltet, sondern von Apps über requestAudioFocus() und abandonAudioFocus().

Audio-Fokus in Android 12 und höher

Eine Media- oder Spiele-App, die den Audiofokus verwendet, sollte nach dem Verlust des Fokus keine Audioinhalte mehr wiedergeben. Unter Android 12 (API-Level 31) und höher wird dieses Verhalten vom System erzwungen. Wenn eine App den Audiofokus anfordert, während eine andere App den Fokus hat und Audioinhalte wiedergibt, zwingt das System die wiedergebende App, die Lautstärke zu verringern. Durch das Einblenden wird der Übergang von einer App zur anderen flüssiger.

Dieses Ausblendverhalten tritt auf, wenn die folgenden Bedingungen erfüllt sind:

  1. Die erste App, die gerade wiedergegeben wird, erfüllt alle diese Kriterien:

  2. Eine zweite App fordert den Audiofokus mit AudioManager.AUDIOFOCUS_GAIN an.

Wenn diese Bedingungen erfüllt sind, blendet das Audiosystem die erste App aus. Am Ende des Ausblendens benachrichtigt das System die erste App über den Fokusverlust. Die Player der App bleiben stummgeschaltet, bis die App den Audiofokus wieder anfordert.

Vorhandenes Audiofokusverhalten

Außerdem sollten Sie diese anderen Fälle kennen, in denen der Audiofokus wechselt.

Automatisches Ducking

Die automatische Pegelabsenkung (vorübergehendes Verringern des Audiopegels einer App, damit eine andere App deutlich zu hören ist) wurde in Android 8.0 (API-Level 26) eingeführt.

Wenn das System Ducking implementiert, müssen Sie Ducking nicht in Ihrer App implementieren.

Die automatische Pegelabsenkung erfolgt auch, wenn eine Audiobenachrichtigung den Fokus von einer App übernimmt, die gerade wiedergegeben wird. Der Beginn der Benachrichtigungswiedergabe wird mit dem Ende der Pegelabsenkungsrampe synchronisiert.

Die automatische Absenkung erfolgt, wenn die folgenden Bedingungen erfüllt sind:

  1. Die erste App, die gerade wiedergegeben wird, erfüllt alle diese Kriterien:

  2. Eine zweite App fordert den Audiofokus mit AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK an.

Wenn diese Bedingungen erfüllt sind, dämpft das Audiosystem alle aktiven Player der ersten App, während die zweite App im Fokus ist. Wenn die zweite App den Fokus verliert, werden sie wieder angedockt. Die erste App wird nicht benachrichtigt, wenn sie den Fokus verliert, muss also nichts tun.

Hinweis: Wenn der Nutzer Sprachinhalte hört, wird die automatische Absenkung nicht durchgeführt, da er sonst möglicherweise einen Teil des Programms verpasst. Die Sprachnavigation für Routen wird beispielsweise nicht unterbrochen.

Aktuelle Audiowiedergabe bei eingehenden Anrufen stummschalten

Einige Apps verhalten sich nicht richtig und geben während Telefonanrufen weiterhin Audio wieder. In dieser Situation muss der Nutzer die störende App suchen und stummschalten oder beenden, um den Anruf hören zu können. Um dies zu verhindern, kann das System Audio von anderen Apps stummschalten, wenn ein Anruf eingeht. Das System ruft diese Funktion auf, wenn ein eingehender Anruf empfangen wird und eine App die folgenden Bedingungen erfüllt:

  • Die App hat entweder das Attribut AudioAttributes.USAGE_MEDIA oder AudioAttributes.USAGE_GAME.
  • Die App hat erfolgreich den Audiofokus angefordert (jede Art von Fokusgewinn) und gibt Audio wieder.

Wenn eine App während des Anrufs weiter abgespielt wird, wird die Wiedergabe stummgeschaltet, bis der Anruf beendet ist. Wenn jedoch während des Anrufs die Wiedergabe in einer App gestartet wird, wird der Player nicht stummgeschaltet, da davon ausgegangen wird, dass der Nutzer die Wiedergabe absichtlich gestartet hat.

Audiofokus in Android 8.0 bis Android 11

Ab Android 8.0 (API-Level 26) müssen Sie beim Aufrufen von requestAudioFocus() einen AudioFocusRequest-Parameter angeben. Das AudioFocusRequest enthält Informationen zum Audiokontext und zu den Funktionen Ihrer App. Das System verwendet diese Informationen, um die Verstärkung und den Verlust des Audiofokus automatisch zu verwalten. Rufen Sie zum Freigeben des Audiofokus die Methode abandonAudioFocusRequest() auf, die auch ein AudioFocusRequest als Argument akzeptiert. Verwenden Sie dieselbe AudioFocusRequest-Instanz, wenn Sie den Fokus anfordern und aufgeben.

Zum Erstellen eines AudioFocusRequest verwenden Sie ein AudioFocusRequest.Builder. Da in einer Fokusanfrage immer der Typ der Anfrage angegeben werden muss, ist der Typ im Konstruktor für den Builder enthalten. Verwenden Sie die Methoden des Builders, um die anderen Felder der Anfrage festzulegen.

Das Feld FocusGain ist erforderlich. Alle anderen Felder sind optional.

MethodHinweise
setFocusGain() Dieses Feld ist in jeder Anfrage erforderlich. Es verwendet dieselben Werte wie durationHint im Aufruf von requestAudioFocus() vor Android 8.0: AUDIOFOCUS_GAIN, AUDIOFOCUS_GAIN_TRANSIENT, AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK oder AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE.
setAudioAttributes() AudioAttributes beschreibt den Anwendungsfall für Ihre App. Das System berücksichtigt diese, wenn eine App den Audiofokus erhält oder verliert. Attribute ersetzen den Begriff „Streamtyp“. In Android 8.0 (API-Level 26) und höher sind Streamtypen für alle Vorgänge außer Lautstärkeregelungen veraltet. Verwende in der Fokusanfrage dieselben Attribute wie in deinem Audioplayer (siehe Beispiel nach dieser Tabelle).

Geben Sie zuerst die Attribute mit einem AudioAttributes.Builder an und weisen Sie sie dann mit dieser Methode der Anfrage zu.

Wenn nicht angegeben, wird standardmäßig AudioAttributes.USAGE_MEDIA verwendet.AudioAttributes

setWillPauseWhenDucked() Wenn eine andere App den Fokus mit AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK anfordert, erhält die App, die den Fokus hat, in der Regel keinen onAudioFocusChange()-Callback, da das System das Ducking selbst ausführen kann. Wenn Sie die Wiedergabe pausieren und nicht die Lautstärke verringern möchten, rufen Sie setWillPauseWhenDucked(true) auf und erstellen und legen Sie ein OnAudioFocusChangeListener fest, wie unter Automatische Lautstärkereduzierung beschrieben.
setAcceptsDelayedFocusGain() Eine Anfrage für den Audiofokus kann fehlschlagen, wenn der Fokus von einer anderen App gesperrt wird. Diese Methode ermöglicht die verzögerte Fokussierung: die Möglichkeit, den Fokus asynchron zu erlangen, wenn er verfügbar wird.

Die verzögerte Fokusübernahme funktioniert nur, wenn Sie auch ein AudioManager.OnAudioFocusChangeListener in der Audioanfrage angeben, da Ihre App den Callback empfangen muss, um zu wissen, dass der Fokus gewährt wurde.

setOnAudioFocusChangeListener() Ein OnAudioFocusChangeListener ist nur erforderlich, wenn Sie auch willPauseWhenDucked(true) oder setAcceptsDelayedFocusGain(true) in der Anfrage angeben.

Es gibt zwei Methoden zum Festlegen des Listeners: eine mit und eine ohne Handler-Argument. Der Handler ist der Thread, in dem der Listener ausgeführt wird. Wenn Sie keinen Handler angeben, wird der Handler verwendet, der mit dem Haupt-Looper verknüpft ist.

Das folgende Beispiel zeigt, wie Sie ein AudioFocusRequest.Builder verwenden, um ein AudioFocusRequest zu erstellen und den Audiofokus anzufordern und aufzugeben:

Kotlin

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

Automatisches Ducking

Unter Android 8.0 (API-Level 26) kann das System die Lautstärke verringern und wiederherstellen, ohne den onAudioFocusChange()-Callback der App aufzurufen, wenn eine andere App den Fokus mit AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK anfordert.

Das automatische Absenken der Lautstärke ist für Musik- und Videowiedergabe-Apps akzeptabel, aber nicht sinnvoll, wenn gesprochene Inhalte wiedergegeben werden, z. B. in einer Hörbuch-App. In diesem Fall sollte die App stattdessen pausieren.

Wenn Ihre App pausieren soll, wenn sie aufgefordert wird, die Lautstärke zu verringern, anstatt die Lautstärke zu verringern, erstellen Sie ein OnAudioFocusChangeListener mit einer onAudioFocusChange()-Callback-Methode, die das gewünschte Pausen-/Fortsetzungsverhalten implementiert. Rufen Sie setOnAudioFocusChangeListener() auf, um den Listener zu registrieren, und rufen Sie setWillPauseWhenDucked(true) auf, um dem System mitzuteilen, dass Ihr Callback verwendet werden soll und keine automatische Absenkung erfolgen soll.

Verzögerter Fokus

Manchmal kann das System eine Anfrage für den Audiofokus nicht gewähren, weil der Fokus von einer anderen App „gesperrt“ ist, z. B. während eines Anrufs. In diesem Fall gibt requestAudioFocus() AUDIOFOCUS_REQUEST_FAILED zurück. In diesem Fall sollte Ihre App die Audiowiedergabe nicht fortsetzen, da sie nicht den Fokus erhalten hat.

Die Methode setAcceptsDelayedFocusGain(true), mit der Ihre App eine Anfrage für den Fokus asynchron verarbeiten kann. Wenn dieses Flag festgelegt ist, wird bei einer Anfrage, die gestellt wird, wenn der Fokus gesperrt ist, AUDIOFOCUS_REQUEST_DELAYED zurückgegeben. Wenn die Bedingung, die den Audiofokus gesperrt hat, nicht mehr vorhanden ist, z. B. wenn ein Telefonanruf beendet wird, gewährt das System die ausstehende Fokusanfrage und ruft onAudioFocusChange() auf, um Ihre App zu benachrichtigen.

Um die verzögerte Fokussierung zu verarbeiten, müssen Sie ein OnAudioFocusChangeListener mit einer onAudioFocusChange()-Callback-Methode erstellen, die das gewünschte Verhalten implementiert, und den Listener registrieren, indem Sie setOnAudioFocusChangeListener() aufrufen.

Audiofokus in Android 7.1 und niedriger

Wenn Sie requestAudioFocus() aufrufen, müssen Sie einen Hinweis zur Dauer angeben, der möglicherweise von einer anderen App berücksichtigt wird, die derzeit den Fokus hat und die Wiedergabe steuert:

  • Fordern Sie den dauerhaften Audiofokus (AUDIOFOCUS_GAIN) an, wenn Sie Audio für die absehbare Zukunft abspielen möchten (z. B. beim Abspielen von Musik) und Sie erwarten, dass der vorherige Inhaber des Audiofokus die Wiedergabe beendet.
  • Fordern Sie den vorübergehenden Fokus (AUDIOFOCUS_GAIN_TRANSIENT) an, wenn Sie Audio nur für kurze Zeit wiedergeben möchten und erwarten, dass der vorherige Inhaber die Wiedergabe pausiert.
  • Fordern Sie mit ducking (AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) einen vorübergehenden Fokus an, um anzugeben, dass Sie Audio nur für kurze Zeit abspielen möchten und dass der vorherige Fokusinhaber weiterhin Audio abspielen kann, wenn er seine Audioausgabe „duckt“ (verringert). Beide Audioausgaben werden in den Audiostream gemischt. Ducking eignet sich besonders für Apps, die den Audiostream nur zeitweise verwenden, z. B. für hörbare Routenanweisungen.

Für die Methode requestAudioFocus() ist auch ein AudioManager.OnAudioFocusChangeListener erforderlich. Dieser Listener sollte in derselben Aktivität oder demselben Dienst erstellt werden, zu dem deine Mediensitzung gehört. Sie implementiert den Callback onAudioFocusChange(), den Ihre App empfängt, wenn eine andere App den Audiofokus erhält oder aufgibt.

Im folgenden Snippet wird der permanente Audiofokus für den Stream STREAM_MUSIC angefordert und ein OnAudioFocusChangeListener registriert, um nachfolgende Änderungen des Audiofokus zu verarbeiten. Der Change-Listener wird unter Auf eine Änderung des Audiofokus reagieren beschrieben.

Kotlin

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
}

Wenn die Wiedergabe beendet ist, rufen Sie abandonAudioFocus() auf.

Kotlin

audioManager.abandonAudioFocus(afChangeListener)

Java

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

Dadurch wird das System darüber informiert, dass Sie den Fokus nicht mehr benötigen, und die zugehörige OnAudioFocusChangeListener wird abgemeldet. Wenn Sie einen vorübergehenden Fokus angefordert haben, wird eine pausierte oder gedämpfte App benachrichtigt, dass sie die Wiedergabe fortsetzen oder die Lautstärke wiederherstellen kann.

Auf eine Änderung des Audiofokus reagieren

Wenn eine App den Audiofokus erhält, muss sie ihn freigeben können, wenn eine andere App den Audiofokus für sich anfordert. In diesem Fall erhält Ihre App einen Aufruf der Methode onAudioFocusChange() im AudioFocusChangeListener, den Sie angegeben haben, als die App requestAudioFocus() aufgerufen hat.

Der an onAudioFocusChange() übergebene Parameter focusChange gibt die Art der Änderung an. Sie entspricht dem von der App, die den Fokus erhält, verwendeten Dauerhinweis. Ihre App sollte entsprechend reagieren.

Vorübergehender Verlust des Fokus
Wenn sich der Fokus nur vorübergehend ändert (AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK oder AUDIOFOCUS_LOSS_TRANSIENT), sollte Ihre App die Wiedergabe leiser stellen (wenn Sie nicht automatisches Leiserstellen verwenden) oder pausieren, aber ansonsten den gleichen Status beibehalten.

Bei einem vorübergehenden Verlust des Audiofokus sollten Sie weiterhin Änderungen des Audiofokus beobachten und bereit sein, die normale Wiedergabe fortzusetzen, wenn Sie den Fokus wiedererlangen. Wenn die blockierende App den Fokus verliert, erhalten Sie einen Callback (AUDIOFOCUS_GAIN). An diesem Punkt können Sie die Lautstärke auf das normale Niveau zurücksetzen oder die Wiedergabe neu starten.

Permanenter Verlust des Fokus
Wenn der Audiofokus dauerhaft verloren geht (AUDIOFOCUS_LOSS), gibt eine andere App Audioinhalte wieder. Ihre App sollte die Wiedergabe sofort pausieren, da sie niemals einen AUDIOFOCUS_GAIN-Callback erhält. Um die Wiedergabe neu zu starten, muss der Nutzer eine explizite Aktion ausführen, z. B. in einer Benachrichtigung oder App-Benutzeroberfläche auf die Schaltfläche „Wiedergabe“ tippen.

Das folgende Code-Snippet zeigt, wie Sie die OnAudioFocusChangeListener-Methode und den zugehörigen onAudioFocusChange()-Callback implementieren. Beachten Sie die Verwendung von Handler, um den Stop-Callback bei einem dauerhaften Verlust des Audiofokus zu verzögern.

Kotlin

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

Der Handler verwendet eine Runnable, die so aussieht:

Kotlin

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

Java

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

Damit die verzögerte Beendigung nicht ausgelöst wird, wenn der Nutzer die Wiedergabe neu startet, rufen Sie mHandler.removeCallbacks(mDelayedStopRunnable) als Reaktion auf alle Statusänderungen auf. Rufen Sie beispielsweise removeCallbacks() im onPlay()-, onSkipToNext()-Callback usw. auf. Sie sollten diese Methode auch im onDestroy()-Callback Ihres Dienstes aufrufen, wenn Sie die von Ihrem Dienst verwendeten Ressourcen bereinigen.