Home | History | Annotate | Download | only in managing-audio
      1 page.title=Managing Audio Focus
      2 parent.title=Managing Audio Playback
      3 parent.link=index.html
      4 
      5 trainingnavtop=true
      6 previous.title=Controlling Your App's Volume and Playback
      7 previous.link=volume-playback.html
      8 next.title=Dealing with Audio Output Hardware
      9 next.link=audio-output.html
     10 
     11 @jd:body
     12 
     13 
     14 <div id="tb-wrapper">
     15 <div id="tb">
     16 
     17 <h2>This lesson teaches you to</h2>
     18 <ol>
     19   <li><a href="#RequestFocus">Request the Audio Focus</a></li>
     20   <li><a href="#HandleFocusLoss">Handle the Loss of Audio Focus</a></li>
     21   <li><a href="#DUCK">Duck!</a></li>
     22 </ol>
     23 
     24 
     25 <h2>You should also read</h2>
     26 <ul>
     27   <li><a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a></li>
     28 </ul>
     29 
     30 </div>
     31 </div>
     32 
     33 
     34 <p>With multiple apps potentially playing audio it's important to think about how they should
     35 interact. To avoid every music app playing at the same time, Android uses audio focus to moderate
     36 audio playback&mdash;only apps that hold the audio focus should play audio.</p>
     37 
     38 <p>Before your app starts playing audio it should request&mdash;and receive&mdash;the audio focus.
     39 Likewise, it should know how to listen for a loss of audio focus and respond appropriately when that
     40 happens.</p>
     41 
     42 
     43 <h2 id="RequestFocus">Request the Audio Focus</h2>
     44 
     45 <p>Before your app starts playing any audio, it should hold the audio focus for the stream
     46 it will be using. This is done with a call to {@link android.media.AudioManager#requestAudioFocus
     47 requestAudioFocus()} which returns
     48 {@link android.media.AudioManager#AUDIOFOCUS_REQUEST_GRANTED} if your request is successful.</p>
     49 
     50 <p>You must specify which stream you're using and whether you expect to require transient or
     51 permanent audio focus. Request transient focus when you expect to play audio for only a short time
     52 (for example when playing navigation instructions). Request permanent audio focus when you
     53 plan to play audio for the foreseeable future (for example, when playing music).</p>
     54 
     55 <p>The following snippet requests permanent audio focus on the music audio stream. You should
     56 request the audio focus immediately before you begin playback, such as when the user presses
     57 play or the background music for the next game level begins.</p>
     58 
     59 <pre>
     60 AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
     61 ...
     62 
     63 // Request audio focus for playback
     64 int result = am.requestAudioFocus(afChangeListener,
     65                                  // Use the music stream.
     66                                  AudioManager.STREAM_MUSIC,
     67                                  // Request permanent focus.
     68                                  AudioManager.AUDIOFOCUS_GAIN);
     69 
     70 if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
     71     am.registerMediaButtonEventReceiver(RemoteControlReceiver);
     72     // Start playback.
     73 }
     74 </pre>
     75 
     76 <p>Once you've finished playback be sure to call {@link
     77 android.media.AudioManager#abandonAudioFocus abandonAudioFocus()}. This notifies
     78 the system that you no longer require focus and unregisters the associated {@link
     79 android.media.AudioManager.OnAudioFocusChangeListener}. In the case of abandoning transient focus,
     80 this allows any interupted app to continue playback.</p>
     81 
     82 <pre>
     83 // Abandon audio focus when playback complete
     84 am.abandonAudioFocus(afChangeListener);
     85 </pre>
     86 
     87 <p>When requesting transient audio focus you have an additional option: whether or not you want to
     88 enable "ducking." Normally, when a well-behaved audio app loses audio focus it immediately
     89 silences its playback. By requesting a transient audio focus that allows ducking you tell other
     90 audio apps that its acceptable for them to keep playing, provided they lower their volume until the
     91 focus returns to them.</p>
     92 
     93 <pre>
     94 // Request audio focus for playback
     95 int result = am.requestAudioFocus(afChangeListener,
     96                              // Use the music stream.
     97                              AudioManager.STREAM_MUSIC,
     98                              // Request permanent focus.
     99                              AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
    100 
    101 if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    102     // Start playback.
    103 }
    104 </pre>
    105 
    106 <p>Ducking is particularly suitable for apps that use the audio stream intermittently, such as for
    107 audible driving directions.</p>
    108 
    109 <p>Whenever another app requests audio focus as described above, its choice between permanent and
    110 transient (with or without support for ducking) audio focus is received by the listener you
    111 registered when requesting focus.</p>
    112 
    113 
    114 <h2 id="HandleFocusLoss">Handle the Loss of Audio Focus</h2>
    115 
    116 <p>If your app can request audio focus, it follows that it will in turn lose that focus when another
    117 app requests it. How your app responds to a loss of audio focus depends on the manner of that
    118 loss.</p>
    119 
    120 <p>The {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange
    121 onAudioFocusChange()} callback method of the audio focus change listener you registered when
    122 requesting audio focus receives a parameter that describes the focus change event. Specifically,
    123 the possible focus loss events mirror the focus request types from the previous
    124 section&mdash;permanent loss, transient loss, and transient with ducking permitted.</p>
    125 
    126 <p>Generally speaking, a transient (temporary) loss of audio focus should result in your app
    127 silencing its audio stream, but otherwise maintaining the same state. You should continue to
    128 monitor changes in audio focus and be prepared to resume playback where it was paused once youve
    129 regained the focus.</p>
    130 
    131 <p>If the audio focus loss is permanent, its assumed that another application is now being used to
    132 listen to audio and your app should effectively end itself. In practical terms, that means stopping
    133 playback, removing media button listeners&mdash;allowing the new audio player to exclusively handle
    134 those events&mdash;and abandoning your audio focus. At that point, you would expect a user action
    135 (pressing play in your app) to be required before you resume playing audio.</p>
    136 
    137 <p>In the following code snippet, we pause the playback or our media player object if the audio
    138 loss is transient and resume it when we have regained the focus. If the loss is permanent, it
    139 unregisters our media button event receiver and stops monitoring audio focus changes.<p>
    140 
    141 <pre>
    142 AudioManager.OnAudioFocusChangeListener afChangeListener =
    143     new AudioManager.OnAudioFocusChangeListener() {
    144         public void onAudioFocusChange(int focusChange) {
    145             if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT) {
    146                 // Pause playback
    147             } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
    148                 // Resume playback
    149             } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
    150                 am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
    151                 am.abandonAudioFocus(afChangeListener);
    152                 // Stop playback
    153             }
    154         }
    155     };
    156 </pre>
    157 
    158 <p>In the case of a transient loss of audio focus where ducking is permitted, rather than pausing
    159 playback, you can "duck" instead.</p>
    160 
    161 
    162 <h2 id="DUCK">Duck!</h2>
    163 
    164 <p>Ducking is the process of lowering your audio stream output volume to make transient audio from
    165 another app easier to hear without totally disrupting the audio from your own application.</p>
    166 
    167 <p>In the following code snippet lowers the volume on our media player object when we temporarily
    168 lose focus, then returns it to its previous level when we regain focus.</p>
    169 
    170 <pre>
    171 OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
    172     public void onAudioFocusChange(int focusChange) {
    173         if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
    174             // Lower the volume
    175         } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
    176             // Raise it back to normal
    177         }
    178     }
    179 };
    180 </pre>
    181 
    182 <p>A loss of audio focus is the most important broadcast to react to, but not the only one. The
    183 system broadcasts a number of intents to alert you to changes in users audio experience.
    184 The next lesson demonstrates how to monitor them to improve the users overall experience.</p>
    185