Managing audio focus

Two or more Android apps can play audio to the same output stream
simultaneously. The system mixes everything together. While this is technically
impressive, it can be very aggravating to a user. To avoid every music app
playing at the same time, Android introduces the idea of audio focus.
Only one app can hold audio focus at a time.

When your app needs to output audio, it should request audio focus. When
it has focus, it can play sound. However, after you acquire audio focus you
may not be able to keep it until you’re done playing. Another app can request
focus, which preempts your hold on audio focus. If that happens your app
should pause playing or lower its volume to let users hear the new audio source
more easily.

Audio focus is cooperative. Apps are encouraged to comply with the audio
focus guidelines, but the system does not enforce the rules. If an app
wants to continue to play loudly even after losing audio focus, nothing can
prevent that. This is a bad experience and there's a good chance that users will
uninstall an app that misbehaves in this way.

A well-behaved audio app should manage audio focus according to these general
guidelines:

Call requestAudioFocus() immediately before starting to play
and verify that the call returns
AUDIOFOCUS_REQUEST_GRANTED.
If you design your app as we describe in this guide, the call to
requestAudioFocus() should be made in the onPlay() callback of
your media session.

When another app gains audio focus, stop or pause playing, or duck the volume
down.

When playback stops, abandon audio focus.

Audio focus is handled differently depending on the version of Android that
is running:

For apps that target Android 5.0 (API level 21) and later, audio apps should
use AudioAttributes to describe the type
of audio your app is playing. For example, apps that play speech should
specify CONTENT_TYPE_SPEECH.

Apps running Android 8.0 (API level 26) or greater should use the
requestAudioFocus()
method, which takes an AudioFocusRequest parameter. The
AudioFocusRequest contains information about the audio context and
capabilities of your app. The system uses this information to manage the gain
and loss of audio focus automatically.

Audio focus in Android 8.0 and later

Beginning with Android 8.0 (API level 26), when you call requestAudioFocus() you must supply an AudioFocusRequest parameter.
To release audio focus, call the method
abandonAudioFocusRequest() which also takes an AudioFocusRequest as its
argument. The same AudioFocusRequest instance should be used when requesting
and abandoning focus.

To create an AudioFocusRequest, use an
AudioFocusRequest.Builder. Since a focus request must
always specify the type of the request, the type is included in the constructor
for the builder. Use the builder's methods to set the other fields of the
request.

This field is required in every request. It takes the same values as
the durationHint used in the pre-Android 8.0 call to requestAudioFocus():
AUDIOFOCUS_GAIN, AUDIOFOCUS_GAIN_TRANSIENT,
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, or AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE.

AudioAttributes describes the use case for your app. The
system looks at them when an app gains and loses audio focus. Attributes
supersede the notion of stream type. In Android 8.0 (API level 26) and later,
stream types for any operation other than volume controls are deprecated. Use
the same attributes in the focus request that you use in your audio player (as
shown in the example following this table).

Use an AudioAttributes.Builder to specify the
attributes first, then use this method to assign the attributes to the
request.

If not specified, AudioAttributes defaults to AudioAttributes.USAGE_MEDIA.

When another app requests focus with
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, the app that has focus does not
usually receive an
onAudioFocusChange()
callback because the system can do the
ducking by itself. When you need to pause playback rather
than duck the volume, call setWillPauseWhenDucked(true) and create and set an
OnAudioFocusChangeListener, as described in automatic
ducking.

A request for audio focus can fail when the focus is locked by another app.
This method enables delayed focus gain: the ability
to asynchronously acquire focus when it becomes available.

Note that delayed focus gain only works if you also specify an
AudioManager.OnAudioFocusChangeListener
in the audio request, since your app needs to
receive the callback in order to know that focus was granted.

An OnAudioFocusChangeListener is only required if you also specify
willPauseWhenDucked(true) or setAcceptsDelayedFocusGain(true) in the request.

There are two methods for setting the listener: one with and one without a
handler argument. The handler is the thread on which the listener runs. If you
do not specify a handler, the handler associated with the main
Looper is used.

The following example shows how to use an AudioFocusRequest.Builder to build
an AudioFocusRequest and request and abandon audio focus:

Automatic ducking

In Android 8.0 (API level 26), when another app requests focus with
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK the system can duck and restore the volume
without invoking the app's onAudioFocusChange() callback.

While automatic ducking is acceptable behavior for music and video playback
apps, it isn't useful when playing spoken content, such as in an
audio book app. In this case, the app should pause instead.

If you want your app to pause when asked to duck rather than decrease its volume, create an OnAudioFocusChangeListener with
an onAudioFocusChange() callback method that implements the desired pause/resume behavior.
Call setOnAudioFocusChangeListener() to register the listener, and call
setWillPauseWhenDucked(true)
to tell the system to use your callback rather than perform automatic ducking.

Delayed focus gain

Sometimes the system cannot grant a request for audio focus because the focus is
"locked" by another app, such as during a phone call. In this case,
requestAudioFocus() returns AUDIOFOCUS_REQUEST_FAILED. When this happens,
your app should not proceed with audio playback because it did not gain
focus.

The method, setAcceptsDelayedFocusGain(true), that lets your app handle a request for focus
asynchronously. With this flag set, a request made when the focus is locked
returns AUDIOFOCUS_REQUEST_DELAYED. When the condition that locked the audio
focus no longer exists, such as when a phone call ends, the system
grants the pending focus request and calls onAudioFocusChange() to notify your
app.

In order to handle the delayed gain of focus, you must create an
OnAudioFocusChangeListener with an onAudioFocusChange() callback method that
implements the desired behavior and register the listener by calling
setOnAudioFocusChangeListener().

Audio focus pre-Android 8.0

When you call
requestAudioFocus()
you must specify a duration hint, which may
be honored by another app that is currently holding focus and playing:

Request permanent audio focus (AUDIOFOCUS_GAIN) when you plan to play audio
for the foreseeable future (for example, when playing music) and you expect the
previous holder of audio focus to stop playing.

Request transient focus (AUDIOFOCUS_GAIN_TRANSIENT) when you expect to play
audio for only a short time and you expect the previous holder to pause
playing.

Request transient focus with ducking
(AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) to indicate that you expect to play audio
for only a short time and that it's OK for the previous focus owner to keep
playing if it "ducks" (lowers) its audio output. Both audio outputs are mixed
into the audio stream. Ducking is particularly suitable for apps that use the
audio stream intermittently, such as for audible driving directions.

The requestAudioFocus() method also requires an AudioManager.OnAudioFocusChangeListener. This listener should be
created in the same activity or service that owns your media session. It
implements the callback onAudioFocusChange() that your app receives when
some other app acquires or abandons audio focus.

The following snippet requests permanent audio focus on the stream
STREAM_MUSIC and registers an OnAudioFocusChangeListener to handle
subsequent changes in audio focus. (The change listener is discussed in
Responding to an audio focus change.)

Kotlin

Java

This notifies the system that you no longer require focus and unregisters the
associated OnAudioFocusChangeListener. If you requested transient focus,
this will notify an app that paused or ducked that it may continue playing or
restore its volume.

Responding to an audio focus change

When an app acquires audio focus, it must be able to release it when another app
requests audio focus for itself. When this happens, your app
receives a call to the
onAudioFocusChange()
method in the AudioFocusChangeListener
that you specified when the app called requestAudioFocus().

The focusChange parameter passed to onAudioFocusChange() indicates the kind
of change that's happening. It corresponds
to the duration hint used by the app that's aquiring focus. Your app should
respond appropriately.

Transient loss of focus

If the focus change is transient (AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK or
AUDIOFOCUS_LOSS_TRANSIENT), your app should duck (if you are not relying
on automatic ducking) or pause playing but
otherwise maintain the same state.

During a transient loss of audio focus, you should continue to monitor changes
in audio focus and be prepared to resume normal playback when you regain the
focus. When the blocking app abandons focus, you receive a callback
(AUDIOFOCUS_GAIN). At this point, you can restore the volume to normal level
or restart playback.

Permanent loss of focus

If the audio focus loss is permanent (AUDIOFOCUS_LOSS), another app is
playing audio. Your app should pause playback immediately, as it won't ever
receive an AUDIOFOCUS_GAIN callback. To restart playback, the user
must take an explicit action, like pressing the play transport control
in a notification or app UI.

The following code snippet demonstrates how to implement the
OnAudioFocusChangeListener and its onAudioFocusChange() callback. Notice the
use of a Handler to delay the stop callback on a permanent loss of audio
focus.

Java

To ensure the delayed stop does not kick in if the user restarts playback, call
mHandler.removeCallbacks(mDelayedStopRunnable) in response to any state
changes. For example, call removeCallbacks() in your Callback's onPlay(),
onSkipToNext(), etc. You should also call this method in your service's
onDestroy() callback when cleaning up the resources used by your service.

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.