Home | History | Annotate | Download | only in media
      1 page.title=Media Playback
      2 page.tags="mediaplayer","soundpool","audiomanager"
      3 @jd:body
      4 
      5     <div id="qv-wrapper">
      6     <div id="qv">
      7 
      8 <h2>In this document</h2>
      9 <ol>
     10 <li><a href="#basics">The Basics</a>
     11 <li><a href="#manifest">Manifest Declarations</a></li>
     12 <li><a href="#mediaplayer">Using MediaPlayer</a>
     13    <ol>
     14       <li><a href='#preparingasync'>Asynchronous Preparation</a></li>
     15       <li><a href='#managestate'>Managing State</a></li>
     16       <li><a href='#releaseplayer'>Releasing the MediaPlayer</a></li>
     17    </ol>
     18 </li>
     19 <li><a href="#mpandservices">Using a Service with MediaPlayer</a>
     20    <ol>
     21       <li><a href="#asyncprepare">Running asynchronously</a></li>
     22       <li><a href="#asyncerror">Handling asynchronous errors</a></li>
     23       <li><a href="#wakelocks">Using wake locks</a></li>
     24       <li><a href="#foregroundserv">Running as a foreground service</a></li>
     25       <li><a href="#audiofocus">Handling audio focus</a></li>
     26       <li><a href="#cleanup">Performing cleanup</a></li>
     27    </ol>
     28 </li>
     29 <li><a href="#noisyintent">Handling the AUDIO_BECOMING_NOISY Intent</a>
     30 <li><a href="#viacontentresolver">Retrieving Media from a Content Resolver</a>
     31 </ol>
     32 
     33 <h2>Key classes</h2>
     34 <ol>
     35 <li>{@link android.media.MediaPlayer}</li>
     36 <li>{@link android.media.AudioManager}</li>
     37 <li>{@link android.media.SoundPool}</li>
     38 </ol>
     39 
     40 <h2>See also</h2>
     41 <ol>
     42 <li><a href="{@docRoot}guide/topics/media/jetplayer.html">JetPlayer</a></li>
     43 <li><a href="{@docRoot}guide/topics/media/audio-capture.html">Audio Capture</a></li>
     44 <li><a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media Formats</a></li>
     45 <li><a href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a></li>
     46 </ol>
     47 
     48 </div>
     49 </div>
     50 
     51 <p>The Android multimedia framework includes support for playing variety of common media types, so
     52 that you can easily integrate audio, video and images into your applications. You can play audio or
     53 video from media files stored in your application's resources (raw resources), from standalone files
     54 in the filesystem, or from a data stream arriving over a network connection, all using {@link
     55 android.media.MediaPlayer} APIs.</p>
     56 
     57 <p>This document shows you how to write a media-playing application that interacts with the user and
     58 the system in order to obtain good performance and a pleasant user experience.</p>
     59 
     60 <p class="note"><strong>Note:</strong> You can play back the audio data only to the standard output
     61 device. Currently, that is the mobile device speaker or a Bluetooth headset. You cannot play sound
     62 files in the conversation audio during a call.</p>
     63 
     64 <h2 id="basics">The Basics</h2>
     65 <p>The following classes are used to play sound and video in the Android framework:</p>
     66 
     67 <dl>
     68   <dt>{@link android.media.MediaPlayer}</dt>
     69   <dd>This class is the primary API for playing sound and video.</dd>
     70   <dt>{@link android.media.AudioManager}</dt>
     71   <dd>This class manages audio sources and audio output on a device.</dd>
     72 </dl>
     73 
     74 <h2 id="manifest">Manifest Declarations</h2>
     75 <p>Before starting development on your application using MediaPlayer, make sure your manifest has
     76 the appropriate declarations to allow use of related features.</p>
     77 
     78 <ul>
     79   <li><strong>Internet Permission</strong> - If you are using MediaPlayer to stream network-based
     80 content, your application must request network access.
     81 <pre>
     82 &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
     83 </pre>
     84   </li>
     85   <li><strong>Wake Lock Permission</strong> - If your player application needs to keep the screen
     86 from dimming or the processor from sleeping, or uses the {@link
     87 android.media.MediaPlayer#setScreenOnWhilePlaying(boolean) MediaPlayer.setScreenOnWhilePlaying()} or
     88 {@link android.media.MediaPlayer#setWakeMode(android.content.Context, int)
     89 MediaPlayer.setWakeMode()} methods, you must request this permission.
     90 <pre>
     91 &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
     92 </pre>
     93   </li>
     94 </ul>
     95 
     96 <h2 id="mediaplayer">Using MediaPlayer</h2>
     97 <p>One of the most important components of the media framework is the
     98 {@link android.media.MediaPlayer MediaPlayer}
     99 class. An object of this class can fetch, decode, and play both audio and video
    100 with minimal setup. It supports several different media sources such as:
    101 <ul>
    102    <li>Local resources</li>
    103    <li>Internal URIs, such as one you might obtain from a Content Resolver</li>
    104    <li>External URLs (streaming)</li>
    105 </ul>
    106 </p>
    107 
    108 <p>For a list of media formats that Android supports,
    109 see the <a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media
    110 Formats</a> document. </p>
    111 
    112 <p>Here is an example
    113 of how to play audio that's available as a local raw resource (saved in your application's
    114 {@code res/raw/} directory):</p>
    115 
    116 <pre>MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
    117 mediaPlayer.start(); // no need to call prepare(); create() does that for you
    118 </pre>
    119 
    120 <p>In this case, a "raw" resource is a file that the system does not
    121 try to parse in any particular way. However, the content of this resource should not
    122 be raw audio. It should be a properly encoded and formatted media file in one 
    123 of the supported formats.</p>
    124 
    125 <p>And here is how you might play from a URI available locally in the system
    126 (that you obtained through a Content Resolver, for instance):</p>
    127 
    128 <pre>Uri myUri = ....; // initialize Uri here
    129 MediaPlayer mediaPlayer = new MediaPlayer();
    130 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    131 mediaPlayer.setDataSource(getApplicationContext(), myUri);
    132 mediaPlayer.prepare();
    133 mediaPlayer.start();</pre>
    134 
    135 <p>Playing from a remote URL via HTTP streaming looks like this:</p>
    136 
    137 <pre>String url = "http://........"; // your URL here
    138 MediaPlayer mediaPlayer = new MediaPlayer();
    139 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    140 mediaPlayer.setDataSource(url);
    141 mediaPlayer.prepare(); // might take long! (for buffering, etc)
    142 mediaPlayer.start();</pre>
    143 
    144 <p class="note"><strong>Note:</strong>
    145 If you're passing a URL to stream an online media file, the file must be capable of
    146 progressive download.</p>
    147 
    148 <p class="caution"><strong>Caution:</strong> You must either catch or pass
    149 {@link java.lang.IllegalArgumentException} and {@link java.io.IOException} when using
    150 {@link android.media.MediaPlayer#setDataSource setDataSource()}, because
    151 the file you are referencing might not exist.</p>
    152 
    153 <h3 id='preparingasync'>Asynchronous Preparation</h3>
    154 
    155 <p>Using {@link android.media.MediaPlayer MediaPlayer} can be straightforward in
    156 principle. However, it's important to keep in mind that a few more things are
    157 necessary to integrate it correctly with a typical Android application. For
    158 example, the call to {@link android.media.MediaPlayer#prepare prepare()} can
    159 take a long time to execute, because
    160 it might involve fetching and decoding media data. So, as is the case with any
    161 method that may take long to execute, you should <strong>never call it from your
    162 application's UI thread</strong>. Doing that will cause the UI to hang until the method returns,
    163 which is a very bad user experience and can cause an ANR (Application Not Responding) error. Even if
    164 you expect your resource to load quickly, remember that anything that takes more than a tenth
    165 of a second to respond in the UI will cause a noticeable pause and will give
    166 the user the impression that your application is slow.</p>
    167 
    168 <p>To avoid hanging your UI thread, spawn another thread to
    169 prepare the {@link android.media.MediaPlayer} and notify the main thread when done. However, while
    170 you could write the threading logic
    171 yourself, this pattern is so common when using {@link android.media.MediaPlayer} that the framework
    172 supplies a convenient way to accomplish this task by using the
    173 {@link android.media.MediaPlayer#prepareAsync prepareAsync()} method. This method
    174 starts preparing the media in the background and returns immediately. When the media
    175 is done preparing, the {@link android.media.MediaPlayer.OnPreparedListener#onPrepared onPrepared()}
    176 method of the {@link android.media.MediaPlayer.OnPreparedListener
    177 MediaPlayer.OnPreparedListener}, configured through
    178 {@link android.media.MediaPlayer#setOnPreparedListener setOnPreparedListener()} is called.</p>
    179 
    180 <h3 id='managestate'>Managing State</h3>
    181 
    182 <p>Another aspect of a {@link android.media.MediaPlayer} that you should keep in mind is
    183 that it's state-based. That is, the {@link android.media.MediaPlayer} has an internal state
    184 that you must always be aware of when writing your code, because certain operations
    185 are only valid when then player is in specific states. If you perform an operation while in the
    186 wrong state, the system may throw an exception or cause other undesireable behaviors.</p>
    187 
    188 <p>The documentation in the
    189 {@link android.media.MediaPlayer MediaPlayer} class shows a complete state diagram,
    190 that clarifies which methods move the {@link android.media.MediaPlayer} from one state to another.
    191 For example, when you create a new {@link android.media.MediaPlayer}, it is in the <em>Idle</em>
    192 state. At that point, you should initialize it by calling
    193 {@link android.media.MediaPlayer#setDataSource setDataSource()}, bringing it
    194 to the <em>Initialized</em> state. After that, you have to prepare it using either the
    195 {@link android.media.MediaPlayer#prepare prepare()} or
    196 {@link android.media.MediaPlayer#prepareAsync prepareAsync()} method. When
    197 the {@link android.media.MediaPlayer} is done preparing, it will then enter the <em>Prepared</em>
    198 state, which means you can call {@link android.media.MediaPlayer#start start()}
    199 to make it play the media. At that point, as the diagram illustrates,
    200 you can move between the <em>Started</em>, <em>Paused</em> and <em>PlaybackCompleted</em> states by
    201 calling such methods as
    202 {@link android.media.MediaPlayer#start start()},
    203 {@link android.media.MediaPlayer#pause pause()}, and
    204 {@link android.media.MediaPlayer#seekTo seekTo()},
    205 amongst others. When you
    206 call {@link android.media.MediaPlayer#stop stop()}, however, notice that you
    207 cannot call {@link android.media.MediaPlayer#start start()} again until you
    208 prepare the {@link android.media.MediaPlayer} again.</p>
    209 
    210 <p>Always keep <a href='{@docRoot}images/mediaplayer_state_diagram.gif'>the state diagram</a> 
    211 in mind when writing code that interacts with a
    212 {@link android.media.MediaPlayer} object, because calling its methods from the wrong state is a
    213 common cause of bugs.</p>
    214 
    215 <h3 id='releaseplayer'>Releasing the MediaPlayer</h3>
    216 
    217 <p>A {@link android.media.MediaPlayer MediaPlayer} can consume valuable
    218 system resources.
    219 Therefore, you should always take extra precautions to make sure you are not
    220 hanging on to a {@link android.media.MediaPlayer} instance longer than necessary. When you
    221 are done with it, you should always call
    222 {@link android.media.MediaPlayer#release release()} to make sure any
    223 system resources allocated to it are properly released. For example, if you are
    224 using a {@link android.media.MediaPlayer} and your activity receives a call to {@link
    225 android.app.Activity#onStop onStop()}, you must release the {@link android.media.MediaPlayer},
    226 because it
    227 makes little sense to hold on to it while your activity is not interacting with
    228 the user (unless you are playing media in the background, which is discussed in the next section).
    229 When your activity is resumed or restarted, of course, you need to
    230 create a new {@link android.media.MediaPlayer} and prepare it again before resuming playback.</p>
    231 
    232 <p>Here's how you should release and then nullify your {@link android.media.MediaPlayer}:</p>
    233 <pre>
    234 mediaPlayer.release();
    235 mediaPlayer = null;
    236 </pre>
    237 
    238 <p>As an example, consider the problems that could happen if you
    239 forgot to release the {@link android.media.MediaPlayer} when your activity is stopped, but create a
    240 new one when the activity starts again. As you may know, when the user changes the
    241 screen orientation (or changes the device configuration in another way), 
    242 the system handles that by restarting the activity (by default), so you might quickly
    243 consume all of the system resources as the user
    244 rotates the device back and forth between portrait and landscape, because at each
    245 orientation change, you create a new {@link android.media.MediaPlayer} that you never
    246 release. (For more information about runtime restarts, see <a
    247 href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a>.)</p>
    248 
    249 <p>You may be wondering what happens if you want to continue playing
    250 "background media" even when the user leaves your activity, much in the same
    251 way that the built-in Music application behaves. In this case, what you need is
    252 a {@link android.media.MediaPlayer MediaPlayer} controlled by a {@link android.app.Service}, as
    253 discussed in <a href="#mpandservices">Using a Service with MediaPlayer</a>.</p>
    254 
    255 <h2 id="mpandservices">Using a Service with MediaPlayer</h2>
    256 
    257 <p>If you want your media to play in the background even when your application
    258 is not onscreen&mdash;that is, you want it to continue playing while the user is
    259 interacting with other applications&mdash;then you must start a
    260 {@link android.app.Service Service} and control the
    261 {@link android.media.MediaPlayer MediaPlayer} instance from there.
    262 You should be careful about this setup, because the user and the system have expectations
    263 about how an application running a background service should interact with the rest of the
    264 system. If your application does not fulfil those expectations, the user may
    265 have a bad experience. This section describes the main issues that you should be
    266 aware of and offers suggestions about how to approach them.</p>
    267 
    268 
    269 <h3 id="asyncprepare">Running asynchronously</h3>
    270 
    271 <p>First of all, like an {@link android.app.Activity Activity}, all work in a
    272 {@link android.app.Service Service} is done in a single thread by
    273 default&mdash;in fact, if you're running an activity and a service from the same application, they
    274 use the same thread (the "main thread") by default. Therefore, services need to
    275 process incoming intents quickly
    276 and never perform lengthy computations when responding to them. If any heavy
    277 work or blocking calls are expected, you must do those tasks asynchronously: either from
    278 another thread you implement yourself, or using the framework's many facilities
    279 for asynchronous processing.</p>
    280 
    281 <p>For instance, when using a {@link android.media.MediaPlayer} from your main thread,
    282 you should call {@link android.media.MediaPlayer#prepareAsync prepareAsync()} rather than
    283 {@link android.media.MediaPlayer#prepare prepare()}, and implement
    284 a {@link android.media.MediaPlayer.OnPreparedListener MediaPlayer.OnPreparedListener}
    285 in order to be notified when the preparation is complete and you can start playing.
    286 For example:</p>
    287 
    288 <pre>
    289 public class MyService extends Service implements MediaPlayer.OnPreparedListener {
    290     private static final ACTION_PLAY = "com.example.action.PLAY";
    291     MediaPlayer mMediaPlayer = null;
    292 
    293     public int onStartCommand(Intent intent, int flags, int startId) {
    294         ...
    295         if (intent.getAction().equals(ACTION_PLAY)) {
    296             mMediaPlayer = ... // initialize it here
    297             mMediaPlayer.setOnPreparedListener(this);
    298             mMediaPlayer.prepareAsync(); // prepare async to not block main thread
    299         }
    300     }
    301 
    302     /** Called when MediaPlayer is ready */
    303     public void onPrepared(MediaPlayer player) {
    304       player.start();
    305     }
    306 }
    307 </pre>
    308 
    309 
    310 <h3 id="asyncerror">Handling asynchronous errors</h3>
    311 
    312 <p>On synchronous operations, errors would normally
    313 be signaled with an exception or an error code, but whenever you use asynchronous
    314 resources, you should make sure your application is notified
    315 of errors appropriately. In the case of a {@link android.media.MediaPlayer MediaPlayer},
    316 you can accomplish this by implementing a
    317 {@link android.media.MediaPlayer.OnErrorListener MediaPlayer.OnErrorListener} and
    318 setting it in your {@link android.media.MediaPlayer} instance:</p>
    319 
    320 <pre>
    321 public class MyService extends Service implements MediaPlayer.OnErrorListener {
    322     MediaPlayer mMediaPlayer;
    323 
    324     public void initMediaPlayer() {
    325         // ...initialize the MediaPlayer here...
    326 
    327         mMediaPlayer.setOnErrorListener(this);
    328     }
    329 
    330     &#64;Override
    331     public boolean onError(MediaPlayer mp, int what, int extra) {
    332         // ... react appropriately ...
    333         // The MediaPlayer has moved to the Error state, must be reset!
    334     }
    335 }
    336 </pre>
    337 
    338 <p>It's important to remember that when an error occurs, the {@link android.media.MediaPlayer}
    339 moves to the <em>Error</em> state (see the documentation for the
    340 {@link android.media.MediaPlayer MediaPlayer} class for the full state diagram)
    341 and you must reset it before you can use it again.
    342 
    343 
    344 <h3 id="wakelocks">Using wake locks</h3>
    345 
    346 <p>When designing applications that play media
    347 in the background, the device may go to sleep
    348 while your service is running. Because the Android system tries to conserve
    349 battery while the device is sleeping, the system tries to shut off any 
    350 of the phone's features that are
    351 not necessary, including the CPU and the WiFi hardware.
    352 However, if your service is playing or streaming music, you want to prevent
    353 the system from interfering with your playback.</p>
    354 
    355 <p>In order to ensure that your service continues to run under
    356 those conditions, you have to use "wake locks." A wake lock is a way to signal to
    357 the system that your application is using some feature that should
    358 stay available even if the phone is idle.</p>
    359 
    360 <p class="caution"><strong>Notice:</strong> You should always use wake locks sparingly and hold them
    361 only for as long as truly necessary, because they significantly reduce the battery life of the
    362 device.</p>
    363 
    364 <p>To ensure that the CPU continues running while your {@link android.media.MediaPlayer} is
    365 playing, call the {@link android.media.MediaPlayer#setWakeMode
    366 setWakeMode()} method when initializing your {@link android.media.MediaPlayer}. Once you do,
    367 the {@link android.media.MediaPlayer} holds the specified lock while playing and releases the lock
    368 when paused or stopped:</p>
    369 
    370 <pre>
    371 mMediaPlayer = new MediaPlayer();
    372 // ... other initialization here ...
    373 mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
    374 </pre>
    375 
    376 <p>However, the wake lock acquired in this example guarantees only that the CPU remains awake. If
    377 you are streaming media over the
    378 network and you are using Wi-Fi, you probably want to hold a
    379 {@link android.net.wifi.WifiManager.WifiLock WifiLock} as
    380 well, which you must acquire and release manually. So, when you start preparing the
    381 {@link android.media.MediaPlayer} with the remote URL, you should create and acquire the Wi-Fi lock.
    382 For example:</p>
    383 
    384 <pre>
    385 WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
    386     .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
    387 
    388 wifiLock.acquire();
    389 </pre>
    390 
    391 <p>When you pause or stop your media, or when you no longer need the
    392 network, you should release the lock:</p>
    393 
    394 <pre>
    395 wifiLock.release();
    396 </pre>
    397 
    398 
    399 <h3 id="foregroundserv">Running as a foreground service</h3>
    400 
    401 <p>Services are often used for performing background tasks, such as fetching emails,
    402 synchronizing data, downloading content, amongst other possibilities. In these
    403 cases, the user is not actively aware of the service's execution, and probably
    404 wouldn't even notice if some of these services were interrupted and later restarted.</p>
    405 
    406 <p>But consider the case of a service that is playing music. Clearly this is a service that the user
    407 is actively aware of and the experience would be severely affected by any interruptions.
    408 Additionally, it's a service that the user will likely wish to interact with during its execution.
    409 In this case, the service should run as a "foreground service." A
    410 foreground service holds a higher level of importance within the system&mdash;the system will
    411 almost never kill the service, because it is of immediate importance to the user. When running
    412 in the foreground, the service also must provide a status bar notification to ensure that users are
    413 aware of the running service and allow them to open an activity that can interact with the
    414 service.</p>
    415 
    416 <p>In order to turn your service into a foreground service, you must create a
    417 {@link android.app.Notification Notification} for the status bar and call
    418 {@link android.app.Service#startForeground startForeground()} from the {@link
    419 android.app.Service}. For example:</p>
    420 
    421 <pre>String songName;
    422 // assign the song name to songName
    423 PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0,
    424         new Intent(getApplicationContext(), MainActivity.class),
    425         PendingIntent.FLAG_UPDATE_CURRENT);
    426 Notification notification = new Notification();
    427 notification.tickerText = text;
    428 notification.icon = R.drawable.play0;
    429 notification.flags |= Notification.FLAG_ONGOING_EVENT;
    430 notification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample",
    431         "Playing: " + songName, pi);
    432 startForeground(NOTIFICATION_ID, notification);
    433 </pre>
    434 
    435 <p>While your service is running in the foreground, the notification you
    436 configured is visible in the notification area of the device. If the user
    437 selects the notification, the system invokes the {@link android.app.PendingIntent} you supplied. In
    438 the example above, it opens an activity ({@code MainActivity}).</p>
    439 
    440 <p>Figure 1 shows how your notification appears to the user:</p>
    441 
    442 <img src='images/notification1.png' />
    443 &nbsp;&nbsp;
    444 <img src='images/notification2.png' />
    445 <p class="img-caption"><strong>Figure 1.</strong> Screenshots of a foreground service's
    446 notification, showing the notification icon in the status bar (left) and the expanded view
    447 (right).</p>
    448 
    449 <p>You should only hold on to the "foreground service" status while your
    450 service is actually performing something the user is actively aware of. Once
    451 that is no longer true, you should release it by calling
    452 {@link android.app.Service#stopForeground stopForeground()}:</p>
    453 
    454 <pre>
    455 stopForeground(true);
    456 </pre>
    457 
    458 <p>For more information, see the documentation about <a
    459 href="{@docRoot}guide/components/services.html#Foreground">Services</a> and
    460 <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p>
    461 
    462 
    463 <h3 id="audiofocus">Handling audio focus</h3>
    464 
    465 <p>Even though only one activity can run at any given time, Android is a
    466 multi-tasking environment. This poses a particular challenge to applications
    467 that use audio, because there is only one audio output and there may be several
    468 media services competing for its use. Before Android 2.2, there was no built-in
    469 mechanism to address this issue, which could in some cases lead to a bad user
    470 experience. For example, when a user is listening to
    471 music and another application needs to notify the user of something very important,
    472 the user might not hear the notification tone due to the loud music. Starting with
    473 Android 2.2, the platform offers a way for applications to negotiate their
    474 use of the device's audio output. This mechanism is called Audio Focus.</p>
    475 
    476 <p>When your application needs to output audio such as music or a notification, 
    477 you should always request audio focus. Once it has focus, it can use the sound output freely, but it
    478 should
    479 always listen for focus changes. If it is notified that it has lost the audio
    480 focus, it should immediately either kill the audio or lower it to a quiet level
    481 (known as "ducking"&mdash;there is a flag that indicates which one is appropriate) and only resume
    482 loud playback after it receives focus again.</p>
    483 
    484 <p>Audio Focus is cooperative in nature. That is, applications are expected
    485 (and highly encouraged) to comply with the audio focus guidelines, but the
    486 rules are not enforced by the system. If an application wants to play loud
    487 music even after losing audio focus, nothing in the system will prevent that.
    488 However, the user is more likely to have a bad experience and will be more
    489 likely to uninstall the misbehaving application.</p>
    490 
    491 <p>To request audio focus, you must call
    492 {@link android.media.AudioManager#requestAudioFocus requestAudioFocus()} from the {@link
    493 android.media.AudioManager}, as the example below demonstrates:</p>
    494 
    495 <pre>
    496 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    497 int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
    498     AudioManager.AUDIOFOCUS_GAIN);
    499 
    500 if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    501     // could not get audio focus.
    502 }
    503 </pre>
    504 
    505 <p>The first parameter to {@link android.media.AudioManager#requestAudioFocus requestAudioFocus()}
    506 is an {@link android.media.AudioManager.OnAudioFocusChangeListener
    507 AudioManager.OnAudioFocusChangeListener},
    508 whose {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange
    509 onAudioFocusChange()} method is called whenever there is a change in audio focus. Therefore, you
    510 should also implement this interface on your service and activities. For example:</p>
    511 
    512 <pre>
    513 class MyService extends Service
    514                 implements AudioManager.OnAudioFocusChangeListener {
    515     // ....
    516     public void onAudioFocusChange(int focusChange) {
    517         // Do something based on focus change...
    518     }
    519 }
    520 </pre>
    521 
    522 <p>The <code>focusChange</code> parameter tells you how the audio focus has changed, and
    523 can be one of the following values (they are all constants defined in
    524 {@link android.media.AudioManager AudioManager}):</p>
    525 
    526 <ul>
    527 <li>{@link android.media.AudioManager#AUDIOFOCUS_GAIN}: You have gained the audio focus.</li>
    528 
    529 <li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS}: You have lost the audio focus for a
    530 presumably long time.
    531 You must stop all audio playback. Because you should expect not to have focus back
    532 for a long time, this would be a good place to clean up your resources as much
    533 as possible. For example, you should release the {@link android.media.MediaPlayer}.</li>
    534 
    535 <li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS_TRANSIENT}: You have
    536 temporarily lost audio focus, but should receive it back shortly. You must stop
    537 all audio playback, but you can keep your resources because you will probably get
    538 focus back shortly.</li>
    539 
    540 <li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}: You have temporarily
    541 lost audio focus,
    542 but you are allowed to continue to play audio quietly (at a low volume) instead
    543 of killing audio completely.</li>
    544 </ul>
    545 
    546 <p>Here is an example implementation:</p>
    547 
    548 <pre>
    549 public void onAudioFocusChange(int focusChange) {
    550     switch (focusChange) {
    551         case AudioManager.AUDIOFOCUS_GAIN:
    552             // resume playback
    553             if (mMediaPlayer == null) initMediaPlayer();
    554             else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();
    555             mMediaPlayer.setVolume(1.0f, 1.0f);
    556             break;
    557 
    558         case AudioManager.AUDIOFOCUS_LOSS:
    559             // Lost focus for an unbounded amount of time: stop playback and release media player
    560             if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();
    561             mMediaPlayer.release();
    562             mMediaPlayer = null;
    563             break;
    564 
    565         case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
    566             // Lost focus for a short time, but we have to stop
    567             // playback. We don't release the media player because playback
    568             // is likely to resume
    569             if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();
    570             break;
    571 
    572         case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
    573             // Lost focus for a short time, but it's ok to keep playing
    574             // at an attenuated level
    575             if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);
    576             break;
    577     }
    578 }
    579 </pre>
    580 
    581 <p>Keep in mind that the audio focus APIs are available only with API level 8 (Android 2.2)
    582 and above, so if you want to support previous
    583 versions of Android, you should adopt a backward compatibility strategy that
    584 allows you to use this feature if available, and fall back seamlessly if not.</p>
    585 
    586 <p>You can achieve backward compatibility either by calling the audio focus methods by reflection
    587 or by implementing all the audio focus features in a separate class (say,
    588 <code>AudioFocusHelper</code>). Here is an example of such a class:</p>
    589 
    590 <pre>
    591 public class AudioFocusHelper implements AudioManager.OnAudioFocusChangeListener {
    592     AudioManager mAudioManager;
    593 
    594     // other fields here, you'll probably hold a reference to an interface
    595     // that you can use to communicate the focus changes to your Service
    596 
    597     public AudioFocusHelper(Context ctx, /* other arguments here */) {
    598         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
    599         // ...
    600     }
    601 
    602     public boolean requestFocus() {
    603         return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
    604             mAudioManager.requestAudioFocus(mContext, AudioManager.STREAM_MUSIC,
    605             AudioManager.AUDIOFOCUS_GAIN);
    606     }
    607 
    608     public boolean abandonFocus() {
    609         return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
    610             mAudioManager.abandonAudioFocus(this);
    611     }
    612 
    613     &#64;Override
    614     public void onAudioFocusChange(int focusChange) {
    615         // let your service know about the focus change
    616     }
    617 }
    618 </pre>
    619 
    620 
    621 <p>You can create an instance of <code>AudioFocusHelper</code> class only if you detect that
    622 the system is running API level 8 or above. For example:</p>
    623 
    624 <pre>
    625 if (android.os.Build.VERSION.SDK_INT &gt;= 8) {
    626     mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(), this);
    627 } else {
    628     mAudioFocusHelper = null;
    629 }
    630 </pre>
    631 
    632 
    633 <h3 id="cleanup">Performing cleanup</h3>
    634 
    635 <p>As mentioned earlier, a {@link android.media.MediaPlayer} object can consume a significant
    636 amount of system resources, so you should keep it only for as long as you need and call
    637 {@link android.media.MediaPlayer#release release()} when you are done with it. It's important
    638 to call this cleanup method explicitly rather than rely on system garbage collection because
    639 it might take some time before the garbage collector reclaims the {@link android.media.MediaPlayer},
    640 as it's only sensitive to memory needs and not to shortage of other media-related resources.
    641 So, in the case when you're using a service, you should always override the
    642 {@link android.app.Service#onDestroy onDestroy()} method to make sure you are releasing
    643 the {@link android.media.MediaPlayer}:</p>
    644 
    645 <pre>
    646 public class MyService extends Service {
    647    MediaPlayer mMediaPlayer;
    648    // ...
    649 
    650    &#64;Override
    651    public void onDestroy() {
    652        if (mMediaPlayer != null) mMediaPlayer.release();
    653    }
    654 }
    655 </pre>
    656 
    657 <p>You should always look for other opportunities to release your {@link android.media.MediaPlayer}
    658 as well, apart from releasing it when being shut down. For example, if you expect not
    659 to be able to play media for an extended period of time (after losing audio focus, for example),
    660 you should definitely release your existing {@link android.media.MediaPlayer} and create it again
    661 later. On the
    662 other hand, if you only expect to stop playback for a very short time, you should probably
    663 hold on to your {@link android.media.MediaPlayer} to avoid the overhead of creating and preparing it
    664 again.</p>
    665 
    666 
    667 
    668 <h2 id="noisyintent">Handling the AUDIO_BECOMING_NOISY Intent</h2>
    669 
    670 <p>Many well-written applications that play audio automatically stop playback when an event
    671 occurs that causes the audio to become noisy (ouput through external speakers). For instance,
    672 this might happen when a user is listening to music through headphones and accidentally
    673 disconnects the headphones from the device. However, this behavior does not happen automatically.
    674 If you don't implement this feature, audio plays out of the device's external speakers, which
    675 might not be what the user wants.</p>
    676 
    677 <p>You can ensure your app stops playing music in these situations by handling
    678 the {@link android.media.AudioManager#ACTION_AUDIO_BECOMING_NOISY} intent, for which you can
    679 register a receiver by
    680 adding the following to your manifest:</p>
    681 
    682 <pre>
    683 &lt;receiver android:name=".MusicIntentReceiver"&gt;
    684    &lt;intent-filter&gt;
    685       &lt;action android:name="android.media.AUDIO_BECOMING_NOISY" /&gt;
    686    &lt;/intent-filter&gt;
    687 &lt;/receiver&gt;
    688 </pre>
    689 
    690 <p>This registers the <code>MusicIntentReceiver</code> class as a broadcast receiver for that
    691 intent. You should then implement this class:</p>
    692 
    693 <pre>
    694 public class MusicIntentReceiver implements android.content.BroadcastReceiver {
    695    &#64;Override
    696    public void onReceive(Context ctx, Intent intent) {
    697       if (intent.getAction().equals(
    698                     android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
    699           // signal your service to stop playback
    700           // (via an Intent, for instance)
    701       }
    702    }
    703 }
    704 </pre>
    705 
    706 
    707 
    708 
    709 <h2 id="viacontentresolver">Retrieving Media from a Content Resolver</h2>
    710 
    711 <p>Another feature that may be useful in a media player application is the ability to
    712 retrieve music that the user has on the device. You can do that by querying the {@link
    713 android.content.ContentResolver} for external media:</p>
    714 
    715 <pre>
    716 ContentResolver contentResolver = getContentResolver();
    717 Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    718 Cursor cursor = contentResolver.query(uri, null, null, null, null);
    719 if (cursor == null) {
    720     // query failed, handle error.
    721 } else if (!cursor.moveToFirst()) {
    722     // no media on the device
    723 } else {
    724     int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
    725     int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
    726     do {
    727        long thisId = cursor.getLong(idColumn);
    728        String thisTitle = cursor.getString(titleColumn);
    729        // ...process entry...
    730     } while (cursor.moveToNext());
    731 }
    732 </pre>
    733 
    734 <p>To use this with the {@link android.media.MediaPlayer}, you can do this:</p>
    735 
    736 <pre>
    737 long id = /* retrieve it from somewhere */;
    738 Uri contentUri = ContentUris.withAppendedId(
    739         android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
    740 
    741 mMediaPlayer = new MediaPlayer();
    742 mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    743 mMediaPlayer.setDataSource(getApplicationContext(), contentUri);
    744 
    745 // ...prepare and start...
    746 </pre>