16d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezpage.title=Media Playback
26d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezparent.title=Multimedia and Camera 
36d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezparent.link=index.html
46d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez@jd:body
56d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
66d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    <div id="qv-wrapper">
76d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    <div id="qv">
86d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
96d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h2>In this document</h2>
106d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<ol>
116d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li><a href="#basics">The Basics</a>
126d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li><a href="#manifest">Manifest Declarations</a></li>
136d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li><a href="#mediaplayer">Using MediaPlayer</a>
146d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   <ol>
156d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      <li><a href='#preparingasync'>Asynchronous Preparation</a></li>
166d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      <li><a href='#managestate'>Managing State</a></li>
176d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      <li><a href='#releaseplayer'>Releasing the MediaPlayer</a></li>
186d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   </ol>
196d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</li>
206d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li><a href="#mpandservices">Using a Service with MediaPlayer</a>
216d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   <ol>
226d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      <li><a href="#asyncprepare">Running asynchronously</a></li>
236d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      <li><a href="#asyncerror">Handling asynchronous errors</a></li>
246d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      <li><a href="#wakelocks">Using wake locks</a></li>
256d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      <li><a href="#foregroundserv">Running as a foreground service</a></li>
266d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      <li><a href="#audiofocus">Handling audio focus</a></li>
276d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      <li><a href="#cleanup">Performing cleanup</a></li>
286d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   </ol>
296d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</li>
306d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li><a href="#noisyintent">Handling the AUDIO_BECOMING_NOISY Intent</a>
316d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li><a href="#viacontentresolver">Retrieving Media from a Content Resolver</a>
326d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</ol>
336d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
346d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h2>Key classes</h2>
356d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<ol>
366d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li>{@link android.media.MediaPlayer}</li>
376d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li>{@link android.media.AudioManager}</li>
386d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li>{@link android.media.SoundPool}</li>
396d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</ol>
406d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
416d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h2>See also</h2>
426d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<ol>
436d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li><a href="{@docRoot}guide/topics/media/jetplayer.html">JetPlayer</a></li>
446d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li><a href="{@docRoot}guide/topics/media/audio-capture.html">Audio Capture</a></li>
456d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li><a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media Formats</a></li>
466d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li><a href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a></li>
476d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</ol>
486d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
496d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</div>
506d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</div>
516d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
526d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>The Android multimedia framework includes support for playing variety of common media types, so
536d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthat you can easily integrate audio, video and images into your applications. You can play audio or
546d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezvideo from media files stored in your application's resources (raw resources), from standalone files
556d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezin the filesystem, or from a data stream arriving over a network connection, all using {@link
566d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezandroid.media.MediaPlayer} APIs.</p>
576d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
586d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>This document shows you how to write a media-playing application that interacts with the user and
596d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe system in order to obtain good performance and a pleasant user experience.</p>
606d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
616d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p class="note"><strong>Note:</strong> You can play back the audio data only to the standard output
626d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezdevice. Currently, that is the mobile device speaker or a Bluetooth headset. You cannot play sound
636d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezfiles in the conversation audio during a call.</p>
646d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
656d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h2 id="basics">The Basics</h2>
666d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>The following classes are used to play sound and video in the Android framework:</p>
676d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
686d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<dl>
696d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez  <dt>{@link android.media.MediaPlayer}</dt>
706d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez  <dd>This class is the primary API for playing sound and video.</dd>
716d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez  <dt>{@link android.media.AudioManager}</dt>
726d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez  <dd>This class manages audio sources and audio output on a device.</dd>
736d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</dl>
746d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
756d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h2 id="manifest">Manifest Declarations</h2>
766d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Before starting development on your application using MediaPlayer, make sure your manifest has
776d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe appropriate declarations to allow use of related features.</p>
786d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
796d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<ul>
806d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez  <li><strong>Internet Permission</strong> - If you are using MediaPlayer to stream network-based
816d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezcontent, your application must request network access.
826d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
836d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
846d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
856d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez  </li>
866d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez  <li><strong>Wake Lock Permission</strong> - If your player application needs to keep the screen
876d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezfrom dimming or the processor from sleeping, or uses the {@link
886d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezandroid.media.MediaPlayer#setScreenOnWhilePlaying(boolean) MediaPlayer.setScreenOnWhilePlaying()} or
896d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#setWakeMode(android.content.Context, int)
906d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezMediaPlayer.setWakeMode()} methods, you must request this permission.
916d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
926d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez&lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
936d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
946d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez  </li>
956d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</ul>
966d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
976d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h2 id="mediaplayer">Using MediaPlayer</h2>
986d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>One of the most important components of the media framework is the
996d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer MediaPlayer}
1006d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezclass. An object of this class can fetch, decode, and play both audio and video
1016d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezwith minimal setup. It supports several different media sources such as:
1026d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<ul>
1036d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   <li>Local resources</li>
1046d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   <li>Internal URIs, such as one you might obtain from a Content Resolver</li>
1056d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   <li>External URLs (streaming)</li>
1066d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</ul>
1076d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</p>
1086d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1096d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>For a list of media formats that Android supports,
1106d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezsee the <a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media
1116d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezFormats</a> document. </p>
1126d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1136d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Here is an example
1146d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezof how to play audio that's available as a local raw resource (saved in your application's
1156d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@code res/raw/} directory):</p>
1166d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1176d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
1186d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer.start(); // no need to call prepare(); create() does that for you
1196d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
1206d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1216d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>In this case, a "raw" resource is a file that the system does not
1226d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeztry to parse in any particular way. However, the content of this resource should not
1236d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezbe raw audio. It should be a properly encoded and formatted media file in one 
1246d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezof the supported formats.</p>
1256d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1266d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>And here is how you might play from a URI available locally in the system
1276d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez(that you obtained through a Content Resolver, for instance):</p>
1286d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1296d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>Uri myUri = ....; // initialize Uri here
1306d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezMediaPlayer mediaPlayer = new MediaPlayer();
1316d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
1326d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer.setDataSource(getApplicationContext(), myUri);
1336d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer.prepare();
1346d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer.start();</pre>
1356d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1366d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Playing from a remote URL via HTTP streaming looks like this:</p>
1376d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1386d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>String url = "http://........"; // your URL here
1396d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezMediaPlayer mediaPlayer = new MediaPlayer();
1406d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
1416d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer.setDataSource(url);
1426d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer.prepare(); // might take long! (for buffering, etc)
1436d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer.start();</pre>
1446d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1456d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p class="note"><strong>Note:</strong>
1466d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezIf you're passing a URL to stream an online media file, the file must be capable of
1476d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezprogressive download.</p>
1486d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1496d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p class="caution"><strong>Caution:</strong> You must either catch or pass
1506d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link java.lang.IllegalArgumentException} and {@link java.io.IOException} when using
1516d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#setDataSource setDataSource()}, because
1526d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe file you are referencing might not exist.</p>
1536d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1546d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h3 id='preparingasync'>Asynchronous Preparation</h3>
1556d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1566d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Using {@link android.media.MediaPlayer MediaPlayer} can be straightforward in
1576d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezprinciple. However, it's important to keep in mind that a few more things are
1586d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeznecessary to integrate it correctly with a typical Android application. For
1596d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezexample, the call to {@link android.media.MediaPlayer#prepare prepare()} can
1606d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeztake a long time to execute, because
1616d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezit might involve fetching and decoding media data. So, as is the case with any
1626d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezmethod that may take long to execute, you should <strong>never call it from your
1636d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezapplication's UI thread</strong>. Doing that will cause the UI to hang until the method returns,
1646d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezwhich is a very bad user experience and can cause an ANR (Application Not Responding) error. Even if
1656d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezyou expect your resource to load quickly, remember that anything that takes more than a tenth
1666d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezof a second to respond in the UI will cause a noticeable pause and will give
1676d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe user the impression that your application is slow.</p>
1686d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1696d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>To avoid hanging your UI thread, spawn another thread to
1706d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezprepare the {@link android.media.MediaPlayer} and notify the main thread when done. However, while
1716d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezyou could write the threading logic
1726d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezyourself, this pattern is so common when using {@link android.media.MediaPlayer} that the framework
1736d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezsupplies a convenient way to accomplish this task by using the
1746d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#prepareAsync prepareAsync()} method. This method
1756d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezstarts preparing the media in the background and returns immediately. When the media
1766d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezis done preparing, the {@link android.media.MediaPlayer.OnPreparedListener#onPrepared onPrepared()}
1776d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezmethod of the {@link android.media.MediaPlayer.OnPreparedListener
1786d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezMediaPlayer.OnPreparedListener}, configured through
1796d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#setOnPreparedListener setOnPreparedListener()} is called.</p>
1806d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1816d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h3 id='managestate'>Managing State</h3>
1826d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1836d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Another aspect of a {@link android.media.MediaPlayer} that you should keep in mind is
1846d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthat it's state-based. That is, the {@link android.media.MediaPlayer} has an internal state
1856d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthat you must always be aware of when writing your code, because certain operations
1866d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezare only valid when then player is in specific states. If you perform an operation while in the
1876d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezwrong state, the system may throw an exception or cause other undesireable behaviors.</p>
1886d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
1896d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>The documentation in the
1906d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer MediaPlayer} class shows a complete state diagram,
1916d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthat clarifies which methods move the {@link android.media.MediaPlayer} from one state to another.
1926d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezFor example, when you create a new {@link android.media.MediaPlayer}, it is in the <em>Idle</em>
1936d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezstate. At that point, you should initialize it by calling
1946d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#setDataSource setDataSource()}, bringing it
1956d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezto the <em>Initialized</em> state. After that, you have to prepare it using either the
1966d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#prepare prepare()} or
1976d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#prepareAsync prepareAsync()} method. When
1986d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe {@link android.media.MediaPlayer} is done preparing, it will then enter the <em>Prepared</em>
1996d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezstate, which means you can call {@link android.media.MediaPlayer#start start()}
2006d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezto make it play the media. At that point, as the diagram illustrates,
2016d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezyou can move between the <em>Started</em>, <em>Paused</em> and <em>PlaybackCompleted</em> states by
2026d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezcalling such methods as
2036d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#start start()},
2046d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#pause pause()}, and
2056d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#seekTo seekTo()},
2066d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezamongst others. When you
2076d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezcall {@link android.media.MediaPlayer#stop stop()}, however, notice that you
2086d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezcannot call {@link android.media.MediaPlayer#start start()} again until you
2096d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezprepare the {@link android.media.MediaPlayer} again.</p>
2106d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2116d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Always keep <a href='{@docRoot}images/mediaplayer_state_diagram.gif'>the state diagram</a> 
2126d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezin mind when writing code that interacts with a
2136d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer} object, because calling its methods from the wrong state is a
2146d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezcommon cause of bugs.</p>
2156d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2166d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h3 id='releaseplayer'>Releasing the MediaPlayer</h3>
2176d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2186d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>A {@link android.media.MediaPlayer MediaPlayer} can consume valuable
2196d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezsystem resources.
2206d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezTherefore, you should always take extra precautions to make sure you are not
2216d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezhanging on to a {@link android.media.MediaPlayer} instance longer than necessary. When you
2226d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezare done with it, you should always call
2236d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#release release()} to make sure any
2246d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezsystem resources allocated to it are properly released. For example, if you are
2256d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezusing a {@link android.media.MediaPlayer} and your activity receives a call to {@link
2266d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezandroid.app.Activity#onStop onStop()}, you must release the {@link android.media.MediaPlayer},
2276d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezbecause it
2286d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezmakes little sense to hold on to it while your activity is not interacting with
2296d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe user (unless you are playing media in the background, which is discussed in the next section).
2306d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezWhen your activity is resumed or restarted, of course, you need to
2316d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezcreate a new {@link android.media.MediaPlayer} and prepare it again before resuming playback.</p>
2326d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2336d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Here's how you should release and then nullify your {@link android.media.MediaPlayer}:</p>
2346d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
2356d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer.release();
2366d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmediaPlayer = null;
2376d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
2386d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2396d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>As an example, consider the problems that could happen if you
2406d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezforgot to release the {@link android.media.MediaPlayer} when your activity is stopped, but create a
2416d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeznew one when the activity starts again. As you may know, when the user changes the
2426d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezscreen orientation (or changes the device configuration in another way), 
2436d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe system handles that by restarting the activity (by default), so you might quickly
2446d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezconsume all of the system resources as the user
2456d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezrotates the device back and forth between portrait and landscape, because at each
2466d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezorientation change, you create a new {@link android.media.MediaPlayer} that you never
2476d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezrelease. (For more information about runtime restarts, see <a
2486d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezhref="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a>.)</p>
2496d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2506d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>You may be wondering what happens if you want to continue playing
2516d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez"background media" even when the user leaves your activity, much in the same
2526d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezway that the built-in Music application behaves. In this case, what you need is
2536d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeza {@link android.media.MediaPlayer MediaPlayer} controlled by a {@link android.app.Service}, as
254cd1b08e1e239269f7d0d48119505313f52d3dd5aScott Maindiscussed in <a href="#mpandservices">Using a Service with MediaPlayer</a>.</p>
2556d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2566d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h2 id="mpandservices">Using a Service with MediaPlayer</h2>
2576d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2586d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>If you want your media to play in the background even when your application
2596d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezis not onscreen&mdash;that is, you want it to continue playing while the user is
2606d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezinteracting with other applications&mdash;then you must start a
2616d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.app.Service Service} and control the
2626d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer MediaPlayer} instance from there.
2636d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezYou should be careful about this setup, because the user and the system have expectations
2646d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezabout how an application running a background service should interact with the rest of the
2656d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezsystem. If your application does not fulfil those expectations, the user may
2666d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezhave a bad experience. This section describes the main issues that you should be
2676d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezaware of and offers suggestions about how to approach them.</p>
2686d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2696d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2706d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h3 id="asyncprepare">Running asynchronously</h3>
2716d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2726d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>First of all, like an {@link android.app.Activity Activity}, all work in a
2736d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.app.Service Service} is done in a single thread by
2746d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezdefault&mdash;in fact, if you're running an activity and a service from the same application, they
2756d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezuse the same thread (the "main thread") by default. Therefore, services need to
2766d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezprocess incoming intents quickly
2776d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezand never perform lengthy computations when responding to them. If any heavy
2786d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezwork or blocking calls are expected, you must do those tasks asynchronously: either from
2796d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezanother thread you implement yourself, or using the framework's many facilities
2806d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezfor asynchronous processing.</p>
2816d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2826d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>For instance, when using a {@link android.media.MediaPlayer} from your main thread,
2836d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezyou should call {@link android.media.MediaPlayer#prepareAsync prepareAsync()} rather than
2846d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#prepare prepare()}, and implement
2856d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeza {@link android.media.MediaPlayer.OnPreparedListener MediaPlayer.OnPreparedListener}
2866d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezin order to be notified when the preparation is complete and you can start playing.
2876d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezFor example:</p>
2886d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2896d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
2906d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezpublic class MyService extends Service implements MediaPlayer.OnPreparedListener {
2916d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    private static final ACTION_PLAY = "com.example.action.PLAY";
2926d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    MediaPlayer mMediaPlayer = null;
2936d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
2946d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    public int onStartCommand(Intent intent, int flags, int startId) {
2956d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        ...
2966d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        if (intent.getAction().equals(ACTION_PLAY)) {
2976d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            mMediaPlayer = ... // initialize it here
2986d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            mMediaPlayer.setOnPreparedListener(this);
2996d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            mMediaPlayer.prepareAsync(); // prepare async to not block main thread
3006d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        }
3016d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    }
3026d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3036d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    /** Called when MediaPlayer is ready */
3046d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    public void onPrepared(MediaPlayer player) {
3056d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        player.start();
3066d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    }
3076d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez}
3086d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
3096d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3106d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3116d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h3 id="asyncerror">Handling asynchronous errors</h3>
3126d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3136d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>On synchronous operations, errors would normally
3146d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezbe signaled with an exception or an error code, but whenever you use asynchronous
3156d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezresources, you should make sure your application is notified
3166d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezof errors appropriately. In the case of a {@link android.media.MediaPlayer MediaPlayer},
3176d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezyou can accomplish this by implementing a
3186d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer.OnErrorListener MediaPlayer.OnErrorListener} and
3196d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezsetting it in your {@link android.media.MediaPlayer} instance:</p>
3206d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3216d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
3226d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezpublic class MyService extends Service implements MediaPlayer.OnErrorListener {
3236d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    MediaPlayer mMediaPlayer;
3246d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3256d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    public void initMediaPlayer() {
3266d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        // ...initialize the MediaPlayer here...
3276d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3286d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        mMediaPlayer.setOnErrorListener(this);
3296d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    }
3306d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3316d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    &#64;Override
3326d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    public boolean onError(MediaPlayer mp, int what, int extra) {
3336d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        // ... react appropriately ...
3346d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        // The MediaPlayer has moved to the Error state, must be reset!
3356d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    }
3366d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez}
3376d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
3386d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3396d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>It's important to remember that when an error occurs, the {@link android.media.MediaPlayer}
3406d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezmoves to the <em>Error</em> state (see the documentation for the
3416d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer MediaPlayer} class for the full state diagram)
3426d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezand you must reset it before you can use it again.
3436d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3446d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3456d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h3 id="wakelocks">Using wake locks</h3>
3466d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3476d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>When designing applications that play media
3486d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezin the background, the device may go to sleep
3496d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezwhile your service is running. Because the Android system tries to conserve
3506d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezbattery while the device is sleeping, the system tries to shut off any 
3516d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezof the phone's features that are
3526d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeznot necessary, including the CPU and the WiFi hardware.
3536d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezHowever, if your service is playing or streaming music, you want to prevent
3546d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe system from interfering with your playback.</p>
3556d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3566d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>In order to ensure that your service continues to run under
3576d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthose conditions, you have to use "wake locks." A wake lock is a way to signal to
3586d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe system that your application is using some feature that should
3596d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezstay available even if the phone is idle.</p>
3606d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3616d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p class="caution"><strong>Notice:</strong> You should always use wake locks sparingly and hold them
3626d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezonly for as long as truly necessary, because they significantly reduce the battery life of the
3636d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezdevice.</p>
3646d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3656d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>To ensure that the CPU continues running while your {@link android.media.MediaPlayer} is
3666d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezplaying, call the {@link android.media.MediaPlayer#setWakeMode
3676d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezsetWakeMode()} method when initializing your {@link android.media.MediaPlayer}. Once you do,
3686d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe {@link android.media.MediaPlayer} holds the specified lock while playing and releases the lock
3696d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezwhen paused or stopped:</p>
3706d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3716d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
3726d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmMediaPlayer = new MediaPlayer();
3736d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez// ... other initialization here ...
3746d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
3756d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
3766d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3776d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>However, the wake lock acquired in this example guarantees only that the CPU remains awake. If
3786d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezyou are streaming media over the
3796d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeznetwork and you are using Wi-Fi, you probably want to hold a
3806d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.net.wifi.WifiManager.WifiLock WifiLock} as
3816d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezwell, which you must acquire and release manually. So, when you start preparing the
3826d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer} with the remote URL, you should create and acquire the Wi-Fi lock.
3836d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezFor example:</p>
3846d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3856d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
3866d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezWifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
3876d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
3886d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3896d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezwifiLock.acquire();
3906d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
3916d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3926d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>When you pause or stop your media, or when you no longer need the
3936d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeznetwork, you should release the lock:</p>
3946d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3956d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
3966d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezwifiLock.release();
3976d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
3986d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
3996d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4006d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h3 id="foregroundserv">Running as a foreground service</h3>
4016d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4026d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Services are often used for performing background tasks, such as fetching emails,
4036d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezsynchronizing data, downloading content, amongst other possibilities. In these
4046d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezcases, the user is not actively aware of the service's execution, and probably
4056d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezwouldn't even notice if some of these services were interrupted and later restarted.</p>
4066d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4076d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>But consider the case of a service that is playing music. Clearly this is a service that the user
4086d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezis actively aware of and the experience would be severely affected by any interruptions.
4096d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezAdditionally, it's a service that the user will likely wish to interact with during its execution.
4106d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezIn this case, the service should run as a "foreground service." A
4116d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezforeground service holds a higher level of importance within the system&mdash;the system will
4126d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezalmost never kill the service, because it is of immediate importance to the user. When running
4136d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezin the foreground, the service also must provide a status bar notification to ensure that users are
4146d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezaware of the running service and allow them to open an activity that can interact with the
4156d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezservice.</p>
4166d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4176d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>In order to turn your service into a foreground service, you must create a
4186d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.app.Notification Notification} for the status bar and call
4196d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.app.Service#startForeground startForeground()} from the {@link
4206d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezandroid.app.Service}. For example:</p>
4216d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4226d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>String songName;
4236d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez// assign the song name to songName
4246d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezPendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0,
4256d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez                new Intent(getApplicationContext(), MainActivity.class),
4266d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez                PendingIntent.FLAG_UPDATE_CURRENT);
4276d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezNotification notification = new Notification();
4286d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeznotification.tickerText = text;
4296d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeznotification.icon = R.drawable.play0;
4306d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeznotification.flags |= Notification.FLAG_ONGOING_EVENT;
4316d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeznotification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample",
4326d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez                "Playing: " + songName, pi);
4336d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezstartForeground(NOTIFICATION_ID, notification);
4346d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
4356d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4366d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>While your service is running in the foreground, the notification you
4376d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezconfigured is visible in the notification area of the device. If the user
4386d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezselects the notification, the system invokes the {@link android.app.PendingIntent} you supplied. In
4396d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe example above, it opens an activity ({@code MainActivity}).</p>
4406d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4416d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Figure 1 shows how your notification appears to the user:</p>
4426d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4436d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<img src='images/notification1.png' />
4446d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez&nbsp;&nbsp;
4456d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<img src='images/notification2.png' />
4466d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p class="img-caption"><strong>Figure 1.</strong> Screenshots of a foreground service's
4476d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeznotification, showing the notification icon in the status bar (left) and the expanded view
4486d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez(right).</p>
4496d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4506d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>You should only hold on to the "foreground service" status while your
4516d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezservice is actually performing something the user is actively aware of. Once
4526d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthat is no longer true, you should release it by calling
4536d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.app.Service#stopForeground stopForeground()}:</p>
4546d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4556d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
4566d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezstopForeground(true);
4576d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
4586d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4596d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>For more information, see the documentation about <a
46050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainhref="{@docRoot}guide/components/services.html#Foreground">Services</a> and
4616d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p>
4626d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4636d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4646d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h3 id="audiofocus">Handling audio focus</h3>
4656d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4666d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Even though only one activity can run at any given time, Android is a
4676d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezmulti-tasking environment. This poses a particular challenge to applications
4686d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthat use audio, because there is only one audio output and there may be several
4696d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezmedia services competing for its use. Before Android 2.2, there was no built-in
4706d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezmechanism to address this issue, which could in some cases lead to a bad user
4716d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezexperience. For example, when a user is listening to
4726d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezmusic and another application needs to notify the user of something very important,
4736d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe user might not hear the notification tone due to the loud music. Starting with
4746d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezAndroid 2.2, the platform offers a way for applications to negotiate their
4756d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezuse of the device's audio output. This mechanism is called Audio Focus.</p>
4766d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4776d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>When your application needs to output audio such as music or a notification, 
4786d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezyou should always request audio focus. Once it has focus, it can use the sound output freely, but it
4796d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezshould
4806d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezalways listen for focus changes. If it is notified that it has lost the audio
4816d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezfocus, it should immediately either kill the audio or lower it to a quiet level
4826d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez(known as "ducking"&mdash;there is a flag that indicates which one is appropriate) and only resume
4836d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezloud playback after it receives focus again.</p>
4846d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4856d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Audio Focus is cooperative in nature. That is, applications are expected
4866d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez(and highly encouraged) to comply with the audio focus guidelines, but the
4876d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezrules are not enforced by the system. If an application wants to play loud
4886d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezmusic even after losing audio focus, nothing in the system will prevent that.
4896d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezHowever, the user is more likely to have a bad experience and will be more
4906d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezlikely to uninstall the misbehaving application.</p>
4916d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4926d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>To request audio focus, you must call
4936d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.AudioManager#requestAudioFocus requestAudioFocus()} from the {@link
4946d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezandroid.media.AudioManager}, as the example below demonstrates:</p>
4956d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
4966d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
4976d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezAudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
4986d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezint result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
4996d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    AudioManager.AUDIOFOCUS_GAIN);
5006d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5016d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezif (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
5026d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    // could not get audio focus.
5036d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez}
5046d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
5056d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5066d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>The first parameter to {@link android.media.AudioManager#requestAudioFocus requestAudioFocus()}
5076d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezis an {@link android.media.AudioManager.OnAudioFocusChangeListener
5086d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezAudioManager.OnAudioFocusChangeListener},
5096d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezwhose {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange
5106d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezonAudioFocusChange()} method is called whenever there is a change in audio focus. Therefore, you
5116d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezshould also implement this interface on your service and activities. For example:</p>
5126d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5136d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
5146d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezclass MyService extends Service
5156d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez                implements AudioManager.OnAudioFocusChangeListener {
5166d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    // ....
5176d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    public void onAudioFocusChange(int focusChange) {
5186d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        // Do something based on focus change...
5196d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    }
5206d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez}
5216d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
5226d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5236d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>The <code>focusChange</code> parameter tells you how the audio focus has changed, and
5246d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezcan be one of the following values (they are all constants defined in
5256d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.AudioManager AudioManager}):</p>
5266d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5276d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<ul>
5286d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li>{@link android.media.AudioManager#AUDIOFOCUS_GAIN}: You have gained the audio focus.</li>
5296d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5306d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS}: You have lost the audio focus for a
5316d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezpresumably long time.
5326d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezYou must stop all audio playback. Because you should expect not to have focus back
5336d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezfor a long time, this would be a good place to clean up your resources as much
5346d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezas possible. For example, you should release the {@link android.media.MediaPlayer}.</li>
5356d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5366d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS_TRANSIENT}: You have
5376d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandeztemporarily lost audio focus, but should receive it back shortly. You must stop
5386d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezall audio playback, but you can keep your resources because you will probably get
5396d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezfocus back shortly.</li>
5406d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5416d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}: You have temporarily
5426d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezlost audio focus,
5436d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezbut you are allowed to continue to play audio quietly (at a low volume) instead
5446d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezof killing audio completely.</li>
5456d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</ul>
5466d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5476d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Here is an example implementation:</p>
5486d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5496d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
5506d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezpublic void onAudioFocusChange(int focusChange) {
5516d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    switch (focusChange) {
5526d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        case AudioManager.AUDIOFOCUS_GAIN:
5536d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            // resume playback
5546d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            if (mMediaPlayer == null) initMediaPlayer();
5556d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();
5566d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            mMediaPlayer.setVolume(1.0f, 1.0f);
5576d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            break;
5586d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5596d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        case AudioManager.AUDIOFOCUS_LOSS:
5606d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            // Lost focus for an unbounded amount of time: stop playback and release media player
5616d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();
5626d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            mMediaPlayer.release();
5636d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            mMediaPlayer = null;
5646d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            break;
5656d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5666d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
5676d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            // Lost focus for a short time, but we have to stop
5686d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            // playback. We don't release the media player because playback
5696d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            // is likely to resume
5706d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();
5716d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            break;
5726d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5736d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
5746d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            // Lost focus for a short time, but it's ok to keep playing
5756d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            // at an attenuated level
5766d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);
5776d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            break;
5786d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    }
5796d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez}
5806d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
5816d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5826d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Keep in mind that the audio focus APIs are available only with API level 8 (Android 2.2)
5836d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezand above, so if you want to support previous
5846d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezversions of Android, you should adopt a backward compatibility strategy that
5856d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezallows you to use this feature if available, and fall back seamlessly if not.</p>
5866d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5876d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>You can achieve backward compatibility either by calling the audio focus methods by reflection
5886d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezor by implementing all the audio focus features in a separate class (say,
5896d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<code>AudioFocusHelper</code>). Here is an example of such a class:</p>
5906d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5916d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
5926d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezpublic class AudioFocusHelper implements AudioManager.OnAudioFocusChangeListener {
5936d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    AudioManager mAudioManager;
5946d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5956d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    // other fields here, you'll probably hold a reference to an interface
5966d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    // that you can use to communicate the focus changes to your Service
5976d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
5986d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    public AudioFocusHelper(Context ctx, /* other arguments here */) {
5996d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
6006d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        // ...
6016d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    }
6026d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6036d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    public boolean requestFocus() {
6046d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
6056d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            mAudioManager.requestAudioFocus(mContext, AudioManager.STREAM_MUSIC,
6066d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            AudioManager.AUDIOFOCUS_GAIN);
6076d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    }
6086d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6096d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    public boolean abandonFocus() {
6106d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
6116d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez            mAudioManager.abandonAudioFocus(this);
6126d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    }
6136d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6146d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    &#64;Override
6156d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    public void onAudioFocusChange(int focusChange) {
6166d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        // let your service know about the focus change
6176d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    }
6186d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez}
6196d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
6206d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6216d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6226d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>You can create an instance of <code>AudioFocusHelper</code> class only if you detect that
6236d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe system is running API level 8 or above. For example:</p>
6246d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6256d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
6266d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezif (android.os.Build.VERSION.SDK_INT &gt;= 8) {
6276d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(), this);
6286d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez} else {
6296d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    mAudioFocusHelper = null;
6306d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez}
6316d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
6326d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6336d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6346d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h3 id="cleanup">Performing cleanup</h3>
6356d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6366d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>As mentioned earlier, a {@link android.media.MediaPlayer} object can consume a significant
6376d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezamount of system resources, so you should keep it only for as long as you need and call
6386d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.media.MediaPlayer#release release()} when you are done with it. It's important
6396d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezto call this cleanup method explicitly rather than rely on system garbage collection because
6406d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezit might take some time before the garbage collector reclaims the {@link android.media.MediaPlayer},
6416d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezas it's only sensitive to memory needs and not to shortage of other media-related resources.
6426d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezSo, in the case when you're using a service, you should always override the
6436d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez{@link android.app.Service#onDestroy onDestroy()} method to make sure you are releasing
6446d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe {@link android.media.MediaPlayer}:</p>
6456d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6466d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
6476d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezpublic class MyService extends Service {
6486d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   MediaPlayer mMediaPlayer;
6496d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   // ...
6506d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6516d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   &#64;Override
6526d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   public void onDestroy() {
6536d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez       if (mMediaPlayer != null) mMediaPlayer.release();
6546d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   }
6556d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez}
6566d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
6576d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6586d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>You should always look for other opportunities to release your {@link android.media.MediaPlayer}
6596d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezas well, apart from releasing it when being shut down. For example, if you expect not
6606d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezto be able to play media for an extended period of time (after losing audio focus, for example),
6616d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezyou should definitely release your existing {@link android.media.MediaPlayer} and create it again
6626d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezlater. On the
6636d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezother hand, if you only expect to stop playback for a very short time, you should probably
6646d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezhold on to your {@link android.media.MediaPlayer} to avoid the overhead of creating and preparing it
6656d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezagain.</p>
6666d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6676d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6686d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6696d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h2 id="noisyintent">Handling the AUDIO_BECOMING_NOISY Intent</h2>
6706d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6716d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Many well-written applications that play audio automatically stop playback when an event
6726d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezoccurs that causes the audio to become noisy (ouput through external speakers). For instance,
6736d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthis might happen when a user is listening to music through headphones and accidentally
6746d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezdisconnects the headphones from the device. However, this behavior does not happen automatically.
6756d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezIf you don't implement this feature, audio plays out of the device's external speakers, which
6766d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezmight not be what the user wants.</p>
6776d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6786d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>You can ensure your app stops playing music in these situations by handling
6796d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezthe {@link android.media.AudioManager#ACTION_AUDIO_BECOMING_NOISY} intent, for which you can
6806d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezregister a receiver by
6816d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezadding the following to your manifest:</p>
6826d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6836d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
6846d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez&lt;receiver android:name=".MusicIntentReceiver"&gt;
6856d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   &lt;intent-filter&gt;
6866d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      &lt;action android:name="android.media.AUDIO_BECOMING_NOISY" /&gt;
6876d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   &lt;/intent-filter&gt;
6886d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez&lt;/receiver&gt;
6896d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
6906d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6916d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>This registers the <code>MusicIntentReceiver</code> class as a broadcast receiver for that
6926d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezintent. You should then implement this class:</p>
6936d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
6946d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
6956d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezpublic class MusicIntentReceiver implements android.content.BroadcastReceiver {
6966d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   &#64;Override
6976d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   public void onReceive(Context ctx, Intent intent) {
6986d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      if (intent.getAction().equals(
6996d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez                    android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
7006d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez          // signal your service to stop playback
7016d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez          // (via an Intent, for instance)
7026d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez      }
7036d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez   }
7046d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez}
7056d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
7066d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
7076d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
7086d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
7096d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
7106d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<h2 id="viacontentresolver">Retrieving Media from a Content Resolver</h2>
7116d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
7126d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>Another feature that may be useful in a media player application is the ability to
7136d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezretrieve music that the user has on the device. You can do that by querying the {@link
7146d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezandroid.content.ContentResolver} for external media:</p>
7156d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
7166d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
7176d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezContentResolver contentResolver = getContentResolver();
7186d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezUri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
7196d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezCursor cursor = contentResolver.query(uri, null, null, null, null);
7206d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezif (cursor == null) {
7216d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    // query failed, handle error.
7226d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez} else if (!cursor.moveToFirst()) {
7236d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    // no media on the device
7246d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez} else {
7256d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
7266d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
7276d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    do {
7286d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez       long thisId = cursor.getLong(idColumn);
7296d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez       String thisTitle = cursor.getString(titleColumn);
7306d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez       // ...process entry...
7316d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez    } while (cursor.moveToNext());
7326d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez}
7336d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>
7346d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
7356d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<p>To use this with the {@link android.media.MediaPlayer}, you can do this:</p>
7366d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
7376d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez<pre>
7386d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezlong id = /* retrieve it from somewhere */;
7396d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezUri contentUri = ContentUris.withAppendedId(
7406d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez        android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
7416d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
7426d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmMediaPlayer = new MediaPlayer();
7436d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
7446d78639868fba7c51aed39aa1029e4c7f86d26c9Joe FernandezmMediaPlayer.setDataSource(getApplicationContext(), contentUri);
7456d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez
7466d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez// ...prepare and start...
7476d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</pre>