Android Building Audio Player Tutorial

Embed Size (px)

Citation preview

  • 8/2/2019 Android Building Audio Player Tutorial

    1/33

    Su tm v convert bi TVDT

    Android Building Audio Player Tutorial

    In this tutorial i am going to discuss building a simple audio player with basic controls like play,

    pause, forward, backward, next, previous, playlist and seekbar. This app basically will read all audio

    files(.mp3) from sdcard and plays selected song. For this tutorial i am referencing MediaPlayer and

    go through it if you need any documentation about usage.

    Android MediaPlayer Class

    Android SDK is providing MediaPlayer Class to access android in built mediaplayer services like

    playing audio, video etc., In this tutorial i am using following functions of this class to control audio

    player.

    MediaPlayer mp = newMediaPlayer();

    // Set data source -setDataSource("/sdcard/path_to_song");

    // Play audiomp.start();

    // Pause audiomp.pause();

    // Reset mediaplayermp.reset();

    // Get song length duration - in millisecondsmp.getDuration();

    // Get current duration - in millisecondsmp.getCurrentDuration();

    // Move song to particular second - used for Forward or Backwardmp.seekTo(positon); // position in milliseconds

    // Check if song is playing or notmp.isPlaying(); // returns true or false

  • 8/2/2019 Android Building Audio Player Tutorial

    2/33

    Su tm v convert bi TVDT

    1. Designing the Audio Player Layout

    Design your audio player using some graphic designing softwares like photoshop. I used photoshop

    to design this app layout. If you are not aware of designing just download the required images from

    the internet. Following is a screenshot of the audio player which we are going to build in this tutorial.(You can find this layout PSD in the download code)

  • 8/2/2019 Android Building Audio Player Tutorial

    3/33

    Su tm v convert bi TVDT

    2. Preparing Required Icons and Images

    Once you are done with your app layout design, prepare the required icons and background images

    for the audio player application. Prepare your icons in different states like default, focused and

    pressed and place them all in your drawable folder.

  • 8/2/2019 Android Building Audio Player Tutorial

    4/33

    Su tm v convert bi TVDT

    3. Writing XML layouts for ICON states(default/hover/pressed)

    After saving all the icons with different states, we need to write xml drawable for each icon. Following

    is a sample for play button. Save this file under drawable folder.

    btn_play.xml

    Note: You need to write xml drawable for each icon you used for the player

    (likebtn_pause.xml, btn_next.xml etc,.)

    4. Writing XML design for SeekBar

    In this tutorial i used customized SeekBar to show song progress. You can design the style of default

    SeekBar using xml styles. In your drawable folder create to xml files and type the following code.

    Changing SeekBar background:

    seekbar_progress_bg.xml

    http://schemas.android.com/apk/res/androidhttp://schemas.android.com/apk/res/androidhttp://schemas.android.com/apk/res/androidhttp://schemas.android.com/apk/res/androidhttp://schemas.android.com/apk/res/androidhttp://schemas.android.com/apk/res/androidhttp://schemas.android.com/apk/res/androidhttp://schemas.android.com/apk/res/androidhttp://schemas.android.com/apk/res/android
  • 8/2/2019 Android Building Audio Player Tutorial

    5/33

    Su tm v convert bi TVDT

    Changing SeekBar Progress:

    seekbar_progress.xml

    Actual seekbar which uses above xml files:

    5. Writing XML for Player Layout

    So far we created separate xml layout for all the icons, seekbar. Now we need to combine

    everything into single layout. Create a new file called player.xml under layout folder and paste the

    following code.

    http://schemas.android.com/apk/res/androidhttp://schemas.android.com/apk/res/androidhttp://schemas.android.com/apk/res/android
  • 8/2/2019 Android Building Audio Player Tutorial

    6/33

    Su tm v convert bi TVDT

    player.xml

  • 8/2/2019 Android Building Audio Player Tutorial

    7/33

    Su tm v convert bi TVDT

    android:id="@+id/player_footer_bg" android:layout_width="fill_parent" android:layout_height="100dp"android:layout_alignParentBottom="true" android:background="@layout/bg_player_footer" android:gravity="center">

  • 8/2/2019 Android Building Audio Player Tutorial

    8/33

    Su tm v convert bi TVDT

    android:id="@+id/songProgressBar" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginRight="20dp" android:layout_marginLeft="20dp" android:layout_marginBottom="20dp" android:layout_above="@id/player_footer_bg" android:thumb="@drawable/seek_handler" android:progressDrawable="@drawable/seekbar_progress" android:paddingLeft="6dp"android:paddingRight="6dp"/>

  • 8/2/2019 Android Building Audio Player Tutorial

    9/33

    Su tm v convert bi TVDT

    The above xml will give following output layout.

    6. Writing XML for PlayList ListView

    Playlist is displayed using a listview. If you are not aware of listview go through thisAndroid ListView

    Tutorialand get an idea of listview layout.

    http://www.androidhive.info/2011/10/android-listview-tutorial/http://www.androidhive.info/2011/10/android-listview-tutorial/http://www.androidhive.info/2011/10/android-listview-tutorial/http://www.androidhive.info/2011/10/android-listview-tutorial/http://www.androidhive.info/2011/10/android-listview-tutorial/http://www.androidhive.info/2011/10/android-listview-tutorial/
  • 8/2/2019 Android Building Audio Player Tutorial

    10/33

    Su tm v convert bi TVDT

    Create an xml file under drawable folder and name it as list_selector.xml and type followingcode. This xml is used for gradient background for list item.

    list_selector.xml

    Create a new xml file under layout layout folder and name it as playlist.xml and type the

    following code. This xml file is for listview.

    playlist.xml

    Also create a new xml file under layout folder for single List Item. Name fileasplaylist_item.xml and type following code. This xml file is for single list item which holds song

    title.

    playlist_item.xml

  • 8/2/2019 Android Building Audio Player Tutorial

    11/33

    Su tm v convert bi TVDT

    android:id="@+id/songTitle"android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="16dp"android:padding="10dp"android:color="#f3f3f3"/>

    By using above layout we can achieve following list view by loading data into it.

    7. Writing Class for reading MP3 files fromSDcard

    So far we are done with static layouts for the player. Now the actual code starts.

    Create a new class file and name it as SongsManager.java. This class will read all the files from

    device sdcard and filters the files which are having .mp3 extension.

  • 8/2/2019 Android Building Audio Player Tutorial

    12/33

    Su tm v convert bi TVDT

    SongsManager.mp3packagecom.androidhive.musicplayer;

    importjava.io.File;importjava.io.FilenameFilter;importjava.util.ArrayList;

    importjava.util.HashMap;

    publicclassSongsManager {// SDCard PathfinalString MEDIA_PATH = newString("/sdcard/");privateArrayList songsList = newArrayList();

    // ConstructorpublicSongsManager(){

    }

    /*** Function to read all mp3 files from sdcard* and store the details in ArrayList* */publicArrayList getPlayList(){

    File home = newFile(MEDIA_PATH);

    if(home.listFiles(newFileExtensionFilter()).length > 0) {for(File file : home.listFiles(newFileExtensionFilter())) {

    HashMap song = newHashMap();song.put("songTitle", file.getName().substring(0,

    (file.getName().length() - 4)));song.put("songPath", file.getPath());

    // Adding each song to SongListsongsList.add(song);

    }}// return songs list arrayreturnsongsList;

    }

    /*** Class to filter files which are having .mp3 extension* */classFileExtensionFilter implementsFilenameFilter {

    publicbooleanaccept(File dir, String name) {return(name.endsWith(".mp3") || name.endsWith(".MP3"));}

    }}

  • 8/2/2019 Android Building Audio Player Tutorial

    13/33

    Su tm v convert bi TVDT

    8. Writing Class for PlayList ListView

    Create a new Activity class for playlist listview. Name the file as PlayListActivity.java This class will

    display list of songs in list layout by using SongsManager.java class

    PlayListActivity.javapackagecom.androidhive.musicplayer;

    importjava.util.ArrayList;importjava.util.HashMap;

    importandroid.app.ListActivity;importandroid.content.Intent;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.AdapterView;importandroid.widget.AdapterView.OnItemClickListener;

    importandroid.widget.ListAdapter;importandroid.widget.ListView;importandroid.widget.SimpleAdapter;

    publicclassPlayListActivity extendsListActivity {// Songs listpublicArrayList songsList = newArrayList();

    @OverridepublicvoidonCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState); setContentView(R.layout.playlist);

    ArrayList songsListData = newArrayList();

    SongsManager plm = newSongsManager();// get all songs from sdcardthis.songsList = plm.getPlayList();

    // looping through playlistfor(inti = 0; i < songsList.size(); i++) {

    // creating new HashMapHashMap song = songsList.get(i);

    // adding HashList to ArrayListsongsListData.add(song);

    }

    // Adding menuItems to ListViewListAdapter adapter = newSimpleAdapter(this, songsListData,

    R.layout.playlist_item, newString[] { "songTitle"}, newint[] {R.id.songTitle });

  • 8/2/2019 Android Building Audio Player Tutorial

    14/33

    Su tm v convert bi TVDT

    setListAdapter(adapter);

    // selecting single ListView itemListView lv = getListView();// listening to single listitem clicklv.setOnItemClickListener(newOnItemClickListener() {

    @OverridepublicvoidonItemClick(AdapterView parent, View view,

    intposition, longid) {// getting listitem indexintsongIndex = position;

    // Starting new intentIntent in = newIntent(getApplicationContext(),

    AndroidBuildingMusicPlayerActivity.class); // Sending songIndex to PlayerActivityin.putExtra("songIndex", songIndex);setResult(100, in);

    // Closing PlayListViewfinish();}

    });}

    }

    9. Helper Class functions

    Create a new class called Utilities.java for handling extra work like converting time to progress

    percentage and vice-versa. Also it has function to convert millisecond to a timer string which will

    displayed on the seekbar of the player.

    Utilities.javapackagecom.androidhive.musicplayer;

    publicclassUtilities {

    /*** Function to convert milliseconds time to* Timer Format* Hours:Minutes:Seconds* */publicString milliSecondsToTimer(longmilliseconds){

    String finalTimerString = "";String secondsString = "";

    // Convert total duration into timeinthours = (int)( milliseconds / (1000*60*60));intminutes = (int)(milliseconds % (1000*60*60)) / (1000*60);intseconds = (int) ((milliseconds % (1000*60*60)) % (1000*60)

  • 8/2/2019 Android Building Audio Player Tutorial

    15/33

    Su tm v convert bi TVDT

    / 1000);// Add hours if thereif(hours > 0){

    finalTimerString = hours + ":";}

    // Prepending 0 to seconds if it is one digitif(seconds < 10){secondsString = "0"+ seconds;

    }else{secondsString = ""+ seconds;}

    finalTimerString = finalTimerString + minutes + ":"+secondsString;

    // return timer stringreturnfinalTimerString;

    }

    /*** Function to get Progress percentage* @param currentDuration* @param totalDuration* */publicintgetProgressPercentage(longcurrentDuration, long

    totalDuration){Double percentage = (double) 0;

    longcurrentSeconds = (int) (currentDuration / 1000);longtotalSeconds = (int) (totalDuration / 1000);

    // calculating percentage

    percentage =(((double)currentSeconds)/totalSeconds)*100;

    // return percentagereturnpercentage.intValue();

    }

    /*** Function to change progress to timer* @param progress -* @param totalDuration* returns current duration in milliseconds* */publicintprogressToTimer(intprogress, inttotalDuration) {

    intcurrentDuration = 0;totalDuration = (int) (totalDuration / 1000);currentDuration = (int) ((((double)progress) / 100) *

    totalDuration);

    // return current duration in millisecondsreturncurrentDuration * 1000;

    }}

  • 8/2/2019 Android Building Audio Player Tutorial

    16/33

    Su tm v convert bi TVDT

    7. Writing Classes needed for Audio Player

    Open your main activity class which deals with main player interface and make the

    classimplements from OnCompletionListener, SeekBar.OnSeekBarChangeListener.

    In this case my main activity name is AndroidBuildingMusicPlayerActivity.

    AndroidBuildingMusicPlayerActivity.javapublicclassAndroidBuildingMusicPlayerActivity extendsActivity

    implementsOnCompletionListener, SeekBar.OnSeekBarChangeListener {

    Now declare all variable needed for this audio player class.

    AndroidBuildingMusicPlayerActivity.javapublicclassAndroidBuildingMusicPlayerActivity extendsActivity

    implementsOnCompletionListener, SeekBar.OnSeekBarChangeListener {

    privateImageButton btnPlay;privateImageButton btnForward;privateImageButton btnBackward;privateImageButton btnNext;privateImageButton btnPrevious;privateImageButton btnPlaylist;privateImageButton btnRepeat;privateImageButton btnShuffle;privateSeekBar songProgressBar;privateTextView songTitleLabel;privateTextView songCurrentDurationLabel;

    privateTextView songTotalDurationLabel;// Media Player

    private MediaPlayer mp;// Handler to update UI timer, progress bar etc,.privateHandler mHandler = newHandler();;privateSongsManager songManager;privateUtilities utils;privateintseekForwardTime = 5000; // 5000 millisecondsprivateintseekBackwardTime = 5000; // 5000 millisecondsprivateintcurrentSongIndex = 0;privatebooleanisShuffle = false;privatebooleanisRepeat = false;privateArrayList songsList = newArrayList();

    Now reference all buttons, images from xml layout to class.

    AndroidBuildingMusicPlayerActivity.java// All player buttons

    btnPlay = (ImageButton) findViewById(R.id.btnPlay);btnForward = (ImageButton) findViewById(R.id.btnForward);btnBackward = (ImageButton) findViewById(R.id.btnBackward);

  • 8/2/2019 Android Building Audio Player Tutorial

    17/33

    Su tm v convert bi TVDT

    btnNext = (ImageButton) findViewById(R.id.btnNext);btnPrevious = (ImageButton) findViewById(R.id.btnPrevious);btnPlaylist = (ImageButton) findViewById(R.id.btnPlaylist);btnRepeat = (ImageButton) findViewById(R.id.btnRepeat);btnShuffle = (ImageButton) findViewById(R.id.btnShuffle);songProgressBar = (SeekBar) findViewById(R.id.songProgressBar);songTitleLabel = (TextView) findViewById(R.id.songTitle);songCurrentDurationLabel = (TextView)

    findViewById(R.id.songCurrentDurationLabel); songTotalDurationLabel = (TextView)

    findViewById(R.id.songTotalDurationLabel);

    // Mediaplayermp = newMediaPlayer();songManager = newSongsManager();utils = newUtilities();

    // ListenerssongProgressBar.setOnSeekBarChangeListener(this); // Importantmp.setOnCompletionListener(this); // Important

    // Getting all songs listsongsList = songManager.getPlayList();

    Launching PlayList

    Write click event listener to playlist button. On clicking playlist button we need to

    launchPlayListAcitivity.java and from listview on selecting a particular song we need

    getsongIndex.

    AndroidBuildingMusicPlayerActivity.java/**

    * Button Click event for Play list click event* Launches list activity which displays list of songs* */btnPlaylist.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    Intent i = newIntent(getApplicationContext(),PlayListActivity.class);

    startActivityForResult(i, 100);}

    });

    To receive the selected songIndex add following fucntion. (Make sure that you added this function

    outside of onCreate method)

  • 8/2/2019 Android Building Audio Player Tutorial

    18/33

    Su tm v convert bi TVDT

    AndroidBuildingMusicPlayerActivity.java/**

    * Receiving song index from playlist view* and play the song* */@Override

    protectedvoidonActivityResult(intrequestCode,intresultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if(resultCode == 100){

    currentSongIndex = data.getExtras().getInt("songIndex");// play selected songplaySong(currentSongIndex);

    }

    }

    Playing Song

    Add the following function to your class. This function accepts songIndex as param and plays it.

    Also when start playing a song it switches the play button to pause button state.

    AndroidBuildingMusicPlayerActivity.java/**

    * Function to play a song* @param songIndex - index of song* */

    publicvoid playSong(intsongIndex){// Play songtry{

    mp.reset();mp.setDataSource(songsList.get(songIndex).get("songPath")); mp.prepare();mp.start();// Displaying Song titleString songTitle = songsList.get(songIndex).get("songTitle");songTitleLabel.setText(songTitle);

    // Changing Button Image to pause imagebtnPlay.setImageResource(R.drawable.btn_pause);

    // set Progress bar valuessongProgressBar.setProgress(0); songProgressBar.setMax(100);

    // Updating progress barupdateProgressBar();

    } catch(IllegalArgumentException e) {e.printStackTrace();

    } catch(IllegalStateException e) {

  • 8/2/2019 Android Building Audio Player Tutorial

    19/33

    Su tm v convert bi TVDT

    e.printStackTrace();} catch(IOException e) {

    e.printStackTrace();}

    }

    Forward / Backward button click events

    Add event listeners to Forward and Backward buttons which forwards or backwards song by

    specified seconds.

    Forward button click event moves song to specified number of seconds forward

    AndroidBuildingMusicPlayerActivity.java

    /** * Forward button click event* Forwards song specified seconds* */btnForward.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    // get current song positionintcurrentPosition = mp.getCurrentPosition();// check if seekForward time is lesser than song durationif(currentPosition + seekForwardTime

  • 8/2/2019 Android Building Audio Player Tutorial

    20/33

    Su tm v convert bi TVDT

    if(currentPosition - seekBackwardTime >= 0){// forward songmp.seekTo(currentPosition - seekBackwardTime);

    }else{// backward to starting positionmp.seekTo(0);

    }

    }});

    Next / Back button click events

    Add click listeners to next and back buttons.

    Next button click event

    which plays next song from the playlist if presents else plays first song

    AndroidBuildingMusicPlayerActivity.java/**

    * Next button click event* Plays next song by taking currentSongIndex + 1* */btnNext.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    // check if next song is there or not if(currentSongIndex < (songsList.size() - 1)){

    playSong(currentSongIndex + 1);currentSongIndex = currentSongIndex + 1;

    }else{// play first songplaySong(0);currentSongIndex = 0;

    }

    }});

    Back button click event which plays previous song if presents or plays last song

    AndroidBuildingMusicPlayerActivity.java/**

    * Back button click event* Plays previous song by currentSongIndex - 1* */btnPrevious.setOnClickListener(new View.OnClickListener() {

    @Override

  • 8/2/2019 Android Building Audio Player Tutorial

    21/33

    Su tm v convert bi TVDT

    publicvoidonClick(View arg0) {if(currentSongIndex > 0){

    playSong(currentSongIndex - 1);currentSongIndex = currentSongIndex - 1;

    }else{// play last songplaySong(songsList.size() - 1);currentSongIndex = songsList.size() - 1;

    }

    }});

    Updating SeekBar progress and Timer

    To update progress bar timer i implemented a background thread which runs in background using a

    Handler. If you new to Handler follow this doc.Updating the UI from a Timer

    AndroidBuildingMusicPlayerActivity.java/**

    * Update timer on seekbar* */publicvoidupdateProgressBar() {

    mHandler.postDelayed(mUpdateTimeTask, 100);}

    /*** Background Runnable thread

    * */privateRunnable mUpdateTimeTask = newRunnable() {

    publicvoidrun() {longtotalDuration = mp.getDuration();longcurrentDuration = mp.getCurrentPosition();

    // Displaying Total Duration timesongTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDura// Displaying time completed playingsongCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(current

    // Updating progress barintprogress = (int)(utils.getProgressPercentage(currentDuration,

    totalDuration));//Log.d("Progress", ""+progress);songProgressBar.setProgress(progress);

    // Running this thread after 100 millisecondsmHandler.postDelayed(this, 100);

    }};

    http://developer.android.com/resources/articles/timed-ui-updates.htmlhttp://developer.android.com/resources/articles/timed-ui-updates.htmlhttp://developer.android.com/resources/articles/timed-ui-updates.htmlhttp://developer.android.com/resources/articles/timed-ui-updates.html
  • 8/2/2019 Android Building Audio Player Tutorial

    22/33

    Su tm v convert bi TVDT

    /**** */@OverridepublicvoidonProgressChanged(SeekBar seekBar, intprogress, booleanfromTouch) {

    }

    /*** When user starts moving the progress handler* */@OverridepublicvoidonStartTrackingTouch(SeekBar seekBar) {

    // remove message Handler from updating progress barmHandler.removeCallbacks(mUpdateTimeTask);

    }

    /*** When user stops moving the progress hanlder

    * */@OverridepublicvoidonStopTrackingTouch(SeekBar seekBar) {

    mHandler.removeCallbacks(mUpdateTimeTask); inttotalDuration = mp.getDuration();intcurrentPosition = utils.progressToTimer(seekBar.getProgress(), totalDura

    // forward or backward to certain secondsmp.seekTo(currentPosition);

    // update timer progress againupdateProgressBar();

    }

    Repeat button click event

    On clicking repeat button we need to set isRepeat to true and vice-versa. Also we need to change

    image source of repeat button to focused state.

    AndroidBuildingMusicPlayerActivity.java/**

    * Button Click event for Repeat button

    * Enables repeat flag to true* */btnRepeat.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    if(isRepeat){isRepeat = false;Toast.makeText(getApplicationContext(), "Repeat is OFF",

  • 8/2/2019 Android Building Audio Player Tutorial

    23/33

    Su tm v convert bi TVDT

    Toast.LENGTH_SHORT).show();btnRepeat.setImageResource(R.drawable.btn_repeat);

    }else{// make repeat to trueisRepeat = true;Toast.makeText(getApplicationContext(), "Repeat is ON",

    Toast.LENGTH_SHORT).show();// make shuffle to falseisShuffle = false;btnRepeat.setImageResource(R.drawable.btn_repeat_focused); btnShuffle.setImageResource(R.drawable.btn_shuffle);

    }}

    });

    Shuffle button click event

    On clicking shuffle button we need to set isShuffle to true and vice-versa. Also we need to change

    image source of shuffle button to focused state.

    AndroidBuildingMusicPlayerActivity.java/**

    * Button Click event for Shuffle button* Enables shuffle flag to true* */btnShuffle.setOnClickListener(new View.OnClickListener() {

    @Override

    publicvoidonClick(View arg0) {if(isShuffle){isShuffle = false;Toast.makeText(getApplicationContext(), "Shuffle is OFF",

    Toast.LENGTH_SHORT).show();btnShuffle.setImageResource(R.drawable.btn_shuffle);

    }else{// make repeat to trueisShuffle= true;Toast.makeText(getApplicationContext(), "Shuffle is ON",

    Toast.LENGTH_SHORT).show();// make shuffle to falseisRepeat = false;btnShuffle.setImageResource(R.drawable.btn_shuffle_focused); btnRepeat.setImageResource(R.drawable.btn_repeat);

    }}

    });

    Implementing song onCompletion Listener

  • 8/2/2019 Android Building Audio Player Tutorial

    24/33

    Su tm v convert bi TVDT

    It is important to implement this listener which will notify you once the song is completed playing. In

    this method we need to play next song automatically depending on repeat andshuffle conditions.

    AndroidBuildingMusicPlayerActivity.java/**

    * On Song Playing completed* if repeat is ON play same song again* if shuffle is ON play random song* */@OverridepublicvoidonCompletion(MediaPlayer arg0) {

    // check for repeat is ON or OFFif(isRepeat){

    // repeat is on play same song againplaySong(currentSongIndex);

    } elseif(isShuffle){// shuffle is on - play a random songRandom rand = newRandom();currentSongIndex = rand.nextInt((songsList.size() - 1) - 0+

    1) + 0;playSong(currentSongIndex);

    } else{// no repeat or shuffle ON - play next songif(currentSongIndex < (songsList.size() - 1)){

    playSong(currentSongIndex + 1);currentSongIndex = currentSongIndex + 1;

    }else{// play first songplaySong(0);currentSongIndex = 0;

    }

    }}

    Update your AndroidManifest.xml

    Update your AndroidManifest.xml to following code.

    Addandroid:configChanges=keyboardHidden|orientation to your main activity node.

    AndroidManifest.xml

  • 8/2/2019 Android Building Audio Player Tutorial

    25/33

    Su tm v convert bi TVDT

    android:icon="@drawable/ic_launcher" android:label="@string/app_name" >

    Final Code

    Following is complete code for the AndroidBuildingMusicPlayerActivity.javaclass.

    AndroidBuildingMusicPlayerActivity.javapackagecom.androidhive.musicplayer;

    importjava.io.IOException;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.Random;

    importandroid.app.Activity;importandroid.content.Intent;importandroid.media.MediaPlayer;importandroid.media.MediaPlayer.OnCompletionListener; importandroid.os.Bundle;importandroid.os.Handler;importandroid.view.View;importandroid.widget.ImageButton;

    importandroid.widget.SeekBar;importandroid.widget.TextView;importandroid.widget.Toast;

    publicclassAndroidBuildingMusicPlayerActivity extendsActivity implementsOnCompletiSeekBar.OnSeekBarChangeListener {

    privateImageButton btnPlay;privateImageButton btnForward;

  • 8/2/2019 Android Building Audio Player Tutorial

    26/33

    Su tm v convert bi TVDT

    privateImageButton btnBackward;privateImageButton btnNext;privateImageButton btnPrevious;privateImageButton btnPlaylist;privateImageButton btnRepeat;privateImageButton btnShuffle;privateSeekBar songProgressBar;privateTextView songTitleLabel;privateTextView songCurrentDurationLabel;privateTextView songTotalDurationLabel;// Media Player

    private MediaPlayer mp;// Handler to update UI timer, progress bar etc,.privateHandler mHandler = newHandler();;privateSongsManager songManager;privateUtilities utils;privateintseekForwardTime = 5000; // 5000 millisecondsprivateintseekBackwardTime = 5000; // 5000 millisecondsprivateintcurrentSongIndex = 0;privatebooleanisShuffle = false;

    privatebooleanisRepeat = false;privateArrayList songsList = newArrayList

  • 8/2/2019 Android Building Audio Player Tutorial

    27/33

    Su tm v convert bi TVDT

    playSong(0);

    /*** Play button click event* plays a song and changes button to pause image* pauses a song and changes button to play image

    * */btnPlay.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    // check for already playingif(mp.isPlaying()){

    if(mp!=null){mp.pause();// Changing button image to play buttonbtnPlay.setImageResource(R.drawable.btn_play);

    }}else{

    // Resume songif(mp!=null){

    mp.start();// Changing button image to pause buttonbtnPlay.setImageResource(R.drawable.btn_pause);

    }}

    }});

    /*** Forward button click event* Forwards song specified seconds* */btnForward.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    // get current song positionintcurrentPosition = mp.getCurrentPosition();// check if seekForward time is lesser than song durationif(currentPosition + seekForwardTime

  • 8/2/2019 Android Building Audio Player Tutorial

    28/33

    Su tm v convert bi TVDT

    btnBackward.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    // get current song positionintcurrentPosition = mp.getCurrentPosition();

    // check if seekBackward time is greater than 0 secif(currentPosition - seekBackwardTime >= 0){// forward songmp.seekTo(currentPosition - seekBackwardTime);

    }else{// backward to starting positionmp.seekTo(0);

    }

    }});

    /**

    * Next button click event* Plays next song by taking currentSongIndex + 1* */btnNext.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    // check if next song is there or not if(currentSongIndex < (songsList.size() - 1)){

    playSong(currentSongIndex + 1);currentSongIndex = currentSongIndex + 1;

    }else{// play first songplaySong(0);currentSongIndex = 0;

    }

    }});

    /*** Back button click event* Plays previous song by currentSongIndex - 1* */btnPrevious.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    if(currentSongIndex > 0){playSong(currentSongIndex - 1);currentSongIndex = currentSongIndex - 1;

    }else{// play last songplaySong(songsList.size() - 1);currentSongIndex = songsList.size() - 1;

    }

  • 8/2/2019 Android Building Audio Player Tutorial

    29/33

    Su tm v convert bi TVDT

    }});

    /*** Button Click event for Repeat button

    * Enables repeat flag to true* */btnRepeat.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    if(isRepeat){isRepeat = false;Toast.makeText(getApplicationContext(), "Repeat is OFF", Toast.LbtnRepeat.setImageResource(R.drawable.btn_repeat);

    }else{// make repeat to trueisRepeat = true;

    Toast.makeText(getApplicationContext(), "Repeat is ON", Toast.LE// make shuffle to falseisShuffle = false;btnRepeat.setImageResource(R.drawable.btn_repeat_focused); btnShuffle.setImageResource(R.drawable.btn_shuffle);

    }}

    });

    /*** Button Click event for Shuffle button* Enables shuffle flag to true* */btnShuffle.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    if(isShuffle){isShuffle = false;Toast.makeText(getApplicationContext(), "Shuffle is OFF", Toast.btnShuffle.setImageResource(R.drawable.btn_shuffle);

    }else{// make repeat to trueisShuffle= true;Toast.makeText(getApplicationContext(), "Shuffle is ON", Toast.L// make shuffle to falseisRepeat = false;

    btnShuffle.setImageResource(R.drawable.btn_shuffle_focused); btnRepeat.setImageResource(R.drawable.btn_repeat);

    }}

    });

    /*** Button Click event for Play list click event* Launches list activity which displays list of songs

  • 8/2/2019 Android Building Audio Player Tutorial

    30/33

    Su tm v convert bi TVDT

    * */btnPlaylist.setOnClickListener(new View.OnClickListener() {

    @OverridepublicvoidonClick(View arg0) {

    Intent i = newIntent(getApplicationContext(), PlayListActivity.clas

    startActivityForResult(i, 100);}});

    }

    /*** Receiving song index from playlist view* and play the song* */@OverrideprotectedvoidonActivityResult(intrequestCode,

    intresultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);if(resultCode == 100){currentSongIndex = data.getExtras().getInt("songIndex");// play selected songplaySong(currentSongIndex);

    }

    }

    /*** Function to play a song* @param songIndex - index of song* */

    publicvoid playSong(intsongIndex){// Play songtry{

    mp.reset();mp.setDataSource(songsList.get(songIndex).get("songPath")); mp.prepare();mp.start();// Displaying Song titleString songTitle = songsList.get(songIndex).get("songTitle");songTitleLabel.setText(songTitle);

    // Changing Button Image to pause imagebtnPlay.setImageResource(R.drawable.btn_pause);

    // set Progress bar valuessongProgressBar.setProgress(0); songProgressBar.setMax(100);

    // Updating progress barupdateProgressBar();

    } catch(IllegalArgumentException e) {e.printStackTrace();

    } catch(IllegalStateException e) {

  • 8/2/2019 Android Building Audio Player Tutorial

    31/33

    Su tm v convert bi TVDT

    e.printStackTrace();} catch(IOException e) {

    e.printStackTrace();}

    }

    /*** Update timer on seekbar* */publicvoidupdateProgressBar() {

    mHandler.postDelayed(mUpdateTimeTask, 100);}

    /*** Background Runnable thread* */privateRunnable mUpdateTimeTask = newRunnable() {

    publicvoidrun() {longtotalDuration = mp.getDuration();longcurrentDuration = mp.getCurrentPosition();

    // Displaying Total Duration timesongTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDura// Displaying time completed playingsongCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(current

    // Updating progress barintprogress = (int)(utils.getProgressPercentage(currentDuration, tot//Log.d("Progress", ""+progress);songProgressBar.setProgress(progress);

    // Running this thread after 100 millisecondsmHandler.postDelayed(this, 100);

    }};

    /**** */@OverridepublicvoidonProgressChanged(SeekBar seekBar, intprogress, booleanfromTouch) {

    }

    /**

    * When user starts moving the progress handler* */@OverridepublicvoidonStartTrackingTouch(SeekBar seekBar) {

    // remove message Handler from updating progress barmHandler.removeCallbacks(mUpdateTimeTask);

    }

    /*** When user stops moving the progress hanlder

  • 8/2/2019 Android Building Audio Player Tutorial

    32/33

    Su tm v convert bi TVDT

    * */@OverridepublicvoidonStopTrackingTouch(SeekBar seekBar) {

    mHandler.removeCallbacks(mUpdateTimeTask); inttotalDuration = mp.getDuration();intcurrentPosition = utils.progressToTimer(seekBar.getProgress(), totalDura

    // forward or backward to certain secondsmp.seekTo(currentPosition);

    // update timer progress againupdateProgressBar();

    }

    /*** On Song Playing completed* if repeat is ON play same song again* if shuffle is ON play random song* */

    @OverridepublicvoidonCompletion(MediaPlayer arg0) {

    // check for repeat is ON or OFFif(isRepeat){

    // repeat is on play same song againplaySong(currentSongIndex);

    } elseif(isShuffle){// shuffle is on - play a random songRandom rand = newRandom();currentSongIndex = rand.nextInt((songsList.size() - 1) - 0+ 1) + 0;playSong(currentSongIndex);

    } else{// no repeat or shuffle ON - play next songif(currentSongIndex < (songsList.size() - 1)){

    playSong(currentSongIndex + 1);currentSongIndex = currentSongIndex + 1;

    }else{// play first songplaySong(0);currentSongIndex = 0;

    }}

    }

    @OverridepublicvoidonDestroy(){

    super.onDestroy();mp.release();

    }

    }

  • 8/2/2019 Android Building Audio Player Tutorial

    33/33

    Sending files to Emulator SDCard (For Testing)

    To test this app in your android emulator you need to load your emulator with some songs. You can

    send files to emulator sdcard using adb tool which comes with Android SDK.

    Navigate to your android SDK folder/platform-tools/ using command line. And

    usingpush command you can send files to sdcard. (Start your emulator before performing push

    command)

    platform-tools> adb push "c:\Songs\White Flag.mp3" "/sdcard/"

    Run your application.