184 lines
7.8 KiB
Plaintext
184 lines
7.8 KiB
Plaintext
page.title=Managing Audio Focus
|
||
parent.title=Managing Audio Playback
|
||
parent.link=index.html
|
||
|
||
trainingnavtop=true
|
||
previous.title=Controlling Your App's Volume and Playback
|
||
previous.link=volume-playback.html
|
||
next.title=Dealing with Audio Output Hardware
|
||
next.link=audio-output.html
|
||
|
||
@jd:body
|
||
|
||
|
||
<div id="tb-wrapper">
|
||
<div id="tb">
|
||
|
||
<h2>This lesson teaches you to</h2>
|
||
<ol>
|
||
<li><a href="#RequestFocus">Request the Audio Focus</a></li>
|
||
<li><a href="#HandleFocusLoss">Handle the Loss of Audio Focus</a></li>
|
||
<li><a href="#DUCK">Duck!</a></li>
|
||
</ol>
|
||
|
||
|
||
<h2>You should also read</h2>
|
||
<ul>
|
||
<li><a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a></li>
|
||
</ul>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<p>With multiple apps potentially playing audio it's important to think about how they should
|
||
interact. To avoid every music app playing at the same time, Android uses audio focus to moderate
|
||
audio playback—only apps that hold the audio focus should play audio.</p>
|
||
|
||
<p>Before your app starts playing audio it should request—and receive—the audio focus.
|
||
Likewise, it should know how to listen for a loss of audio focus and respond appropriately when that
|
||
happens.</p>
|
||
|
||
|
||
<h2 id="RequestFocus">Request the Audio Focus</h2>
|
||
|
||
<p>Before your app starts playing any audio, it should hold the audio focus for the stream
|
||
it will be using. This is done with a call to {@link android.media.AudioManager#requestAudioFocus
|
||
requestAudioFocus()} which returns
|
||
{@link android.media.AudioManager#AUDIOFOCUS_REQUEST_GRANTED} if your request is successful.</p>
|
||
|
||
<p>You must specify which stream you're using and whether you expect to require transient or
|
||
permanent audio focus. Request transient focus when you expect to play audio for only a short time
|
||
(for example when playing navigation instructions). Request permanent audio focus when you
|
||
plan to play audio for the foreseeable future (for example, when playing music).</p>
|
||
|
||
<p>The following snippet requests permanent audio focus on the music audio stream. You should
|
||
request the audio focus immediately before you begin playback, such as when the user presses
|
||
play or the background music for the next game level begins.</p>
|
||
|
||
<pre>
|
||
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
|
||
...
|
||
|
||
// Request audio focus for playback
|
||
int result = am.requestAudioFocus(afChangeListener,
|
||
// Use the music stream.
|
||
AudioManager.STREAM_MUSIC,
|
||
// Request permanent focus.
|
||
AudioManager.AUDIOFOCUS_GAIN);
|
||
|
||
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
|
||
// Start playback.
|
||
}
|
||
</pre>
|
||
|
||
<p>Once you've finished playback be sure to call {@link
|
||
android.media.AudioManager#abandonAudioFocus abandonAudioFocus()}. This notifies
|
||
the system that you no longer require focus and unregisters the associated {@link
|
||
android.media.AudioManager.OnAudioFocusChangeListener}. In the case of abandoning transient focus,
|
||
this allows any interupted app to continue playback.</p>
|
||
|
||
<pre>
|
||
// Abandon audio focus when playback complete
|
||
am.abandonAudioFocus(afChangeListener);
|
||
</pre>
|
||
|
||
<p>When requesting transient audio focus you have an additional option: whether or not you want to
|
||
enable "ducking." Normally, when a well-behaved audio app loses audio focus it immediately
|
||
silences its playback. By requesting a transient audio focus that allows ducking you tell other
|
||
audio apps that it’s acceptable for them to keep playing, provided they lower their volume until the
|
||
focus returns to them.</p>
|
||
|
||
<pre>
|
||
// Request audio focus for playback
|
||
int result = am.requestAudioFocus(afChangeListener,
|
||
// Use the music stream.
|
||
AudioManager.STREAM_MUSIC,
|
||
// Request permanent focus.
|
||
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
|
||
|
||
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||
// Start playback.
|
||
}
|
||
</pre>
|
||
|
||
<p>Ducking is particularly suitable for apps that use the audio stream intermittently, such as for
|
||
audible driving directions.</p>
|
||
|
||
<p>Whenever another app requests audio focus as described above, its choice between permanent and
|
||
transient (with or without support for ducking) audio focus is received by the listener you
|
||
registered when requesting focus.</p>
|
||
|
||
|
||
<h2 id="HandleFocusLoss">Handle the Loss of Audio Focus</h2>
|
||
|
||
<p>If your app can request audio focus, it follows that it will in turn lose that focus when another
|
||
app requests it. How your app responds to a loss of audio focus depends on the manner of that
|
||
loss.</p>
|
||
|
||
<p>The {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange
|
||
onAudioFocusChange()} callback method of they audio focus change listener you registered when
|
||
requesting audio focus receives a parameter that describes the focus change event. Specifically,
|
||
the possible focus loss events mirror the focus request types from the previous
|
||
section—permanent loss, transient loss, and transient with ducking permitted.</p>
|
||
|
||
<p>Generally speaking, a transient (temporary) loss of audio focus should result in your app
|
||
silencing it’s audio stream, but otherwise maintaining the same state. You should continue to
|
||
monitor changes in audio focus and be prepared to resume playback where it was paused once you’ve
|
||
regained the focus.</p>
|
||
|
||
<p>If the audio focus loss is permanent, it’s assumed that another application is now being used to
|
||
listen to audio and your app should effectively end itself. In practical terms, that means stopping
|
||
playback, removing media button listeners—allowing the new audio player to exclusively handle
|
||
those events—and abandoning your audio focus. At that point, you would expect a user action
|
||
(pressing play in your app) to be required before you resume playing audio.</p>
|
||
|
||
<p>In the following code snippet, we pause the playback or our media player object if the audio
|
||
loss is transient and resume it when we have regained the focus. If the loss is permanent, it
|
||
unregisters our media button event receiver and stops monitoring audio focus changes.<p>
|
||
|
||
<pre>
|
||
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
|
||
public void onAudioFocusChange(int focusChange) {
|
||
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT
|
||
// Pause playback
|
||
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
|
||
// Resume playback
|
||
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
|
||
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
|
||
am.abandonAudioFocus(afChangeListener);
|
||
// Stop playback
|
||
}
|
||
}
|
||
};
|
||
</pre>
|
||
|
||
<p>In the case of a transient loss of audio focus where ducking is permitted, rather than pausing
|
||
playback, you can "duck" instead.</p>
|
||
|
||
|
||
<h2 id="DUCK">Duck!</h2>
|
||
|
||
<p>Ducking is the process of lowering your audio stream output volume to make transient audio from
|
||
another app easier to hear without totally disrupting the audio from your own application.</p>
|
||
|
||
<p>In the following code snippet lowers the volume on our media player object when we temporarily
|
||
lose focus, then returns it to its previous level when we regain focus.</p>
|
||
|
||
<pre>
|
||
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
|
||
public void onAudioFocusChange(int focusChange) {
|
||
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
|
||
// Lower the volume
|
||
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
|
||
// Raise it back to normal
|
||
}
|
||
}
|
||
};
|
||
</pre>
|
||
|
||
<p>A loss of audio focus is the most important broadcast to react to, but not the only one. The
|
||
system broadcasts a number of intents to alert you to changes in user’s audio experience.
|
||
The next lesson demonstrates how to monitor them to improve the user’s overall experience.</p>
|