`
xsuo
  • 浏览: 123346 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

MusicDroid - Audio Player Part I

阅读更多

MusicDroid - Audio Player Part I

SDK Version:
M3
<!-- google_ad_section_start --><!--paging_filter-->

<!--break-->Introduction

As you can imagine a popular way to load music onto a cell phone will be via removable storage, such as an SD card. In part 1 of our media player tutorial we will build a simple media player that will allow the user to select a song from the SD card and play it.

Click here if you would like to download the source for this tutorial.

Note: there is a known issue with the Emulator where the mixer will cut in and out on some systems resulting in very choppy audio, hopefully this will be addressed in the next SDK release.

Layouts

This project only consists of one Activity, a ListActivity. So, for a ListActivity we need a ListView for the actual list, and another view that will be used for each item in the list. You can get fancy, but for this example we will just use a TextView to display the name of each file.

First, here is our ListView (songlist.xml):

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent">
  6. <ListView id="@id/android:list"
  7. android:layout_width="fill_parent"
  8. android:layout_height="fill_parent"
  9. android:layout_weight="1"
  10. android:drawSelectorOnTop="false"/>
  11. <TextView id="@id/android:empty"
  12. android:layout_width="fill_parent"
  13. android:layout_height="fill_parent"
  14. android:text="No songs found on SD Card."/>
  15. </LinearLayout>

Very standard ListView. The TextView entry will display when there are no items in the ListView because it's using the built-in id of "@id/android:empty".

And for each file here is the TextView to be used (song_item.xml):

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <TextView id="@+id/text1" xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="wrap_content"
  4. android:layout_height="wrap_content"/>

Again, very basic, shouldn't be anything you haven't seen before.

You may be thinking, why does the screenshot above show a black ListView, when nothing in these layouts mentions color? Well, that is determined by the "theme" in the AndroidManifest.xml. In the "application" element you can define the theme by adding "android:theme="@android:style/Theme.Dark"".

The ListActivity

We now must work on our ListActivity which we will call MusicDroid. Here is the declaration of this class and it's onCreate() function:

  1. public class MusicDroid extends ListActivity {
  2. private static final String MEDIA_PATH = new String("/sdcard/");
  3. private List<String> songs = new ArrayList<String>();
  4. private MediaPlayer mp = new MediaPlayer();
  5. private int currentPosition = 0;
  6. @Override
  7. public void onCreate(Bundle icicle) {
  8. super.onCreate(icicle);
  9. setContentView(R.layout.songlist);
  10. updateSongList();
  11. }

First we set up some private member variables to be used by this Activity. The first one is MEDIA_PATH, and we set it to "/sdcard" because that is the location of the SD card. Next comes a List of Strings that will hold the filename for each song on the list. And of course we need a MediaPlayer object, which we call mp. The final one up there is currentPosition, which we will use to store the index of the song currently playing.

The onCreate() function is pretty basic, we set our view to be the songlist view that we created above and call the function updateSongList(), here is that function:

  1. public void updateSongList() {
  2. File home = new File(MEDIA_PATH);
  3. if (home.listFiles(new Mp3Filter()).length > 0) {
  4. for (File file : home.listFiles(new Mp3Filter())) {
  5. songs.add(file.getName());
  6. }
  7. ArrayAdapter<String> songList = new ArrayAdapter<String>(this,
  8. R.layout.song_item, songs);
  9. setListAdapter(songList);
  10. }
  11. }

Here we create a File Object called "home" which points to "/sdcard". We loop through the files returned by home.ListFiles(), adding each file to our List object "songs". Once we have this list filled we create an ArrayAdapter passing in the songs list and then set it to be our ListActivity's ListAdapter on line 47. This will populate our ListView.

You may have noticed the object above called "Mp3Filter". This is an object that implements FilenameFilter. This object is used to filter out what files should be returned, this is done by implementing the accept(File, String) function. Here is the object that we can use to filter so that listFiles() only returns MP3 files:

  1. class Mp3Filter implements FilenameFilter {
  2. public boolean accept(File dir, String name) {
  3. return (name.endsWith(".mp3"));
  4. }
  5. }

Now we should be able to build a list of all the MP3 files in /sdcard. So now we just need to be able to select a song and play it. Fist things first, let's override onListItemClick() so we will be notified when a song is clicked on:

  1. @Override
  2. protected void onListItemClick(ListView l, View v, int position, long id) {
  3. currentPosition = position;
  4. playSong(MEDIA_PATH + songs.get(position));
  5. }

Pretty basic function here. We set currentPosition to hold the index of the position that was clicked on and then pass in the path of the song to playSong(String), so lets take a look at what's happening in playSong(String):

  1. private void playSong(String songPath) {
  2. try {
  3. mp.reset();
  4. mp.setDataSource(songPath);
  5. mp.prepare();
  6. mp.start();
  7. // Setup listener so next song starts automatically
  8. mp.setOnCompletionListener(new OnCompletionListener() {
  9. public void onCompletion(MediaPlayer arg0) {
  10. nextSong();
  11. }
  12. });
  13. } catch (IOException e) {
  14. Log.v(getString(R.string.app_name), e.getMessage());
  15. }
  16. }

The MediaPlayer object makes things really easy for us here. First we call mp.reset(), which will reset the MediaPlayer to its normal state. This is required if you were playing a song and want to change the data source. The reset() function will also stop whatever is playing, so if a song is playing and then you select another it will stop that one before starting the next song.

We then pass in the path to the song to mp.setDataSource(String) and call prepare() and start(). At this point the MediaPlayer will start playing your song.

Next job is to setup an OnCompletionListener starting on line 66. The function onCompletion(MediaPlayer) will be called when the song is over. All we do there is call the function nextSong() from our Activity. Here is nextSong():

  1. private void nextSong() {
  2. if (++currentPosition >= songs.size()) {
  3. // Last song, just reset currentPosition
  4. currentPosition = 0;
  5. } else {
  6. // Play next song
  7. playSong(MEDIA_PATH + songs.get(currentPosition));
  8. }
  9. }

Here we check to make sure this isn't the last song on the list, if it is we won't do anything, if not we'll play the next song using the playSong(String) function.

So that's it for the code, on the next page we'll figure out how to get this thing running...

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics