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