Create a mini audio player

Posted By : Keshav Gupta | 23-Sep-2018

We are going to develop a simple music player application having two screens one is playlist screen and the other is a player screen. So we will be going step by step. We will be using Content Provider

Step1: We will be fetching all songs file from storage and listing them in a custom listview using ContentProvider media resolver query. There will be a PlayList activity class having ListView in its layout component which will be hosting list of songs from MediaStore. Code for this will be like:

public class AudioHome extends Activity {
ListView songList;
ArrayList<SongsInfo> songDetails;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
songList = (ListView) findViewById(R.id.songsList);
TextView header = new TextView(this);
header.setTextColor(Color.WHITE);
header.setTextSize(25);
header.setText("Playlist");
songList.addHeaderView(header);
Log.i("dap", "Audio player started, initializing audio list...");
initializeList();
Log.i("dap", "List Initialized, select Song to play...");
}

private class SongSelectionListener implements OnItemClickListener {

@Override
public void onItemClick(AdapterView<?> parent, View clickedView,
int index, long id) {
Log.i("dap", "Song indexed " + index+ " is selected for playing, creating uri...");
SongsInfo info = songDetails.get(index - 1);
String uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "/"+ info.getId();
Log.i("dap", "starting activity to play song...");
Intent intent = new Intent(getApplicationContext(),SongPlaying.class);
intent.putExtra("uri", uri);
intent.putExtra("title", info.getTitle());
startActivityForResult(intent, 1);
}

}

@Override
protected void onActivityResult(int request, int result, Intent datamain) {
super.onActivityResult(request, result, datamain);
if (result == 1) {
Log.i("dap", "Terminating app...");
Process.killProcess(Process.myPid());

}
}

private void initializeList() {

Log.i("dap", "Fetching MediaStore contents... ");
ContentResolver resolver = getContentResolver();
String projection[] = { MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.ARTIST };
Cursor cursor = resolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, null,
null,MediaStore.Audio.Media.TITLE +" ASC");
songDetails = new ArrayList<SongsInfo>();
while (cursor.moveToNext()) {
int id = cursor.getInt(0);
String title = cursor.getString(1);
int dur = cursor.getInt(2);
String artist = cursor.getString(3);
songDetails.add(new SongsInfo(id, title, artist, dur));

}
cursor.close();
//	Log.i("dap", "Content Fetched, displaying on list... ");
//ArrayAdapter<SongsInfo> ad=new ArrayAdapter<SongsInfo>(getApplicationContext(), R.layout.songlist, R.id.title, songDetails);


ArrayAdapter<SongsInfo> adapter = new MyArrayAdapter(
getApplicationContext(), R.layout.songlist, songDetails);
songList.setAdapter(adapter);
songList.setOnItemClickListener(new SongSelectionListener());
//Log.i("dap", "Adapter set, Listener registered... ");
}

Step2: We will also create an adapter class whose layout file will contain the view for a title, artist and date and time for a song. The adapter will recreate view on the scroll as ListView works. In this, we are setting data to views from media array list collected in playlist class from MediaStore.The code will be like.

public class MyArrayAdapter extends ArrayAdapter<SongsInfo> {

int layout;

public MyArrayAdapter(Context context, int layoutId,
List<SongsInfo> objects) {
super(context, layoutId, objects);
layout = layoutId;
}

@Override
public View getView(int pos, View view, ViewGroup container) {
RelativeLayout newView;
SongsInfo detail = songDetails.get(pos);
if (view == null) {
newView = new RelativeLayout(getContext());
LayoutInflater li = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
li.inflate(layout, newView, true);
} else {
newView = (RelativeLayout) view;
}
TextView title = (TextView) newView.findViewById(R.id.title);
title.setText(detail.getTitle());
TextView duration = (TextView) newView.findViewById(R.id.duration);
duration.setText(detail.getDisplayDuration());
TextView artist = (TextView) newView.findViewById(R.id.artist);
artist.setText(detail.getArsist());
return newView;
}

}}

Step3: We will now design a Player class where the song will be played on user selection on the list. Basically, the user can now get all media controller features to play, pause and stop feature. There will be an activity named SongPlaying.class which will be having views like button for stop, start and resume media tracks in its layout.xml file. We will be implementing code for several media controller feature on selection buttons. A progress bar will be there to show play status. The code will be like:

package com.example.mediakit;

import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class SongPlaying extends Activity {

MediaPlayer player;
TextView playing;
Button pauseAndResume, playlist, stopPlayer;
ProgressBar songProgress;
ProgressBarUpdater pbarUpdater;
public boolean playFlag;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.playing);

playing = (TextView) findViewById(R.id.playing);
songProgress = (ProgressBar) findViewById(R.id.songProgress);

pauseAndResume = (Button) findViewById(R.id.btnPauseResume);
stopPlayer = (Button) findViewById(R.id.btnStop);
playlist = (Button) findViewById(R.id.btnPlaylist);

pauseAndResume.setOnClickListener(new PauseAndResumeListener());
stopPlayer.setOnClickListener(new StopClickListener());
playlist.setOnClickListener(new PlayListClickListener());

Intent intent = getIntent();
String uri = intent.getStringExtra("uri");
String title = intent.getStringExtra("title");
playing.setText("Currently Playing : " + title);
Log.i("dap", "Player Activity Started, obtaining media player...");
playSong(uri);

}

private class StopClickListener implements OnClickListener {
@Override
public void onClick(View v) {
Log.i("dap", "Stopping playler...");
playFlag = false;
pbarUpdater.interrupt();
player.stop();
player.release();
setResult(1);
finish();
}
}

private class PlayListClickListener implements OnClickListener {

@Override
public void onClick(View v) {
Log.i("dap", "returning to playlist...");
setResult(0);
finish();
}

}

private class PauseAndResumeListener implements OnClickListener {

@Override
public void onClick(View v) {
if (pauseAndResume.getText().equals("Pause")) {

player.pause();
pauseAndResume.setText("Resume");
Log.i("dap", "paused.");
} else {
player.start();
pauseAndResume.setText("Pause");
Log.i("dap", "resumed.");

}
}

}

private class ProgressBarUpdater extends Thread {

public ProgressBarUpdater() {
start();
songProgress.setMax(player.getDuration());
}

public void run() {
while (playFlag) {
songProgress.setProgress(player.getCurrentPosition());
try {
Thread.sleep(1000);
} catch (Exception e) {
Log.i("dap", "progress bar updater thread interrupted.");
}
}
}
}

private void playSong(String songUri) {
Uri uri = Uri.parse(songUri);
player = PlayerApp.getApplication().getPlayer();
if (player != null) {
if (player.isPlaying() || player.isLooping()) {
Log.i("dap", "stopping current player to reset data source...");
player.stop();
}
try {
player.reset();
playFlag = false;
player.setDataSource(getApplicationContext(), uri);
player.prepare();
Log
.i("dap",
"Player prepared for current song after being stopped...");
} catch (Exception e) {
Log.i("dap", e.toString());

}
} else {

player = MediaPlayer.create(getApplicationContext(), uri);
PlayerApp.getApplication().setPlayer(player);
Log.i("dap", "player created and set in scope...");

}
player.start();
player.setOnCompletionListener(new OnCompletionListener() {

@Override
public void onCompletion(MediaPlayer mp) {
playFlag = false;
Toast.makeText(getApplicationContext(), "Song Completed.",
Toast.LENGTH_LONG).show();
}
});
playFlag = true;
pbarUpdater = new ProgressBarUpdater();
Log.i("dap", "player started...");
}
}

Step 4: There will be bean class SongsInfo to hold data object collected from the media store in playlist class. There will be a method to manipulate time for songs track. The code will be like:

package com.example.mediakit;
public class SongsInfo {
private int id;
String title, arsist, displayDuration;
int duration;

public SongsInfo(int id, String title, String arsist, int duration) {
super();
this.id = id;
this.title = title;
this.arsist = arsist;
this.duration = duration;
this.displayDuration = durationInSeconds(duration);

}

public int getId() {
return id;
}

public String getDisplayDuration() {
return displayDuration;
}

public String getTitle() {
return title;
}

public String getArsist() {
return arsist;
}

public int getDuration() {
return duration;
}

public String durationInSeconds(int dur) {
int min, sec;
int time = dur / 1000;
min = time / 60;
sec = time % 60;
String minPart = Integer.toString(min);
if (min < 10)
minPart = "0" + Integer.toString(min);
String secPart = Integer.toString(sec);
if (sec < 10)
secPart = "0" + Integer.toString(sec);
return minPart + ":" + secPart;
}
}

Note: This was all about an overall idea that anyone can develop its offline music player. You can add more features.

About Author

Author Image
Keshav Gupta

Keshav Gupta is Android Developer in Oodles, he always look forward for new tasks and new things to learn more.

Request for Proposal

Name is required

Comment is required

Sending message..