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<uses-permission android:name="android.permission.INTERNET" /> 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<uses-permission android:name="android.permission.WAKE_LOCK" /> 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—that is, you want it to continue playing while the user is 2606d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandezinteracting with other applications—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—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 @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—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 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"—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 @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 >= 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 @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<receiver android:name=".MusicIntentReceiver"> 6856d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez <intent-filter> 6866d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez <action android:name="android.media.AUDIO_BECOMING_NOISY" /> 6876d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez </intent-filter> 6886d78639868fba7c51aed39aa1029e4c7f86d26c9Joe Fernandez</receiver> 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 @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>