Learn to list and play audio files in Android and make music player of your own.

This tutorial is for beginners in Android development, who intend to explore the exciting field of mobile app development and chose to begin with Android.

Following this tutorial, we will create two activities

  1. MusicPlayerActivity: To play the audio files
  2. MusicListActivity: To list all the audio files in our internal memory of the Android device

It's very obvious for a beginner in Android development to wonder, what is an activity? In the most simple way: It is a page or screen of your application.

Remember how the screen changes when you navigate through an android app? You are actually switching through "activities" while navigating (or fragments, which are components of an activity).

Since we want two screens in our application, we are going to create two activities as listed above.

Every activity has an XML file and a java class. The XML file is used to define the layout (look and feel) of the activity and the Java class contains code to make it interactive/dynamic. With this basic knowledge lets proceed to create our first activity.

At first glance, the code below may look a bit scary for someone just starting Android development, but that's universal so you need not to worry. We will explain each part of the code and its purpose, later in this blog.

MusicPlayerActivity

XML Layout: activity_music_player.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MusicPlayerActivity">

<Button
android:id="@+id/playBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Play"
tools:layout_editor_absoluteX="147dp"
tools:layout_editor_absoluteY="230dp" />

<TextView
android:id="@+id/audioName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="480dp"
android:text="TextView"
tools:layout_editor_absoluteX="162dp"
tools:layout_editor_absoluteY="178dp" />

<SeekBar
android:id="@+id/seekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="43dp" />

<Button
android:id="@+id/viewAllMedia"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/playBtn"
android:layout_alignStart="@+id/playBtn"
android:layout_marginStart="-21dp"
android:layout_marginTop="14dp"
android:text="View all media" />
</RelativeLayout>

 

JAVA  class: MusicPlayerActivity.java

package com.hack4m.android.basicmusicplayer;

import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Timer;
import java.util.TimerTask;

public class MusicPlayerActivity extends AppCompatActivity {

    MediaPlayer mediaPlayer;
    AudioModel audio;
    SeekBar seekBar;

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

        Intent intent = getIntent();
        audio = (AudioModel) intent.getSerializableExtra("audio");

        TextView audioName = findViewById(R.id.audioName);
        Button playBtn = findViewById(R.id.playBtn);
        Button viewAllMediaBtn = findViewById(R.id.viewAllMedia);

        if(audio!=null){
            audioName.setText(audio.getaName());
        }else{
            audioName.setText("Piano.wav");
        }


        playBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startPlaying();
            }
        });

        viewAllMediaBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopPlaying();
                startActivity(new Intent(getApplicationContext(),MusicListActivity.class));
                //finish();
            }
        });

    }

    public void startPlaying(){
        if(mediaPlayer!=null && mediaPlayer.isPlaying()){
            mediaPlayer.stop();
        }

        if(audio!=null){

            Toast.makeText(getApplicationContext(),"Playing from device; "+audio.getaPath(),Toast.LENGTH_SHORT).show();
            mediaPlayer = MediaPlayer.create(MusicPlayerActivity.this, Uri.parse(audio.getaPath()));
            mediaPlayer.start();

        }else{

            Toast.makeText(getApplicationContext(),"Playing from app",Toast.LENGTH_SHORT).show();
            try {
                AssetFileDescriptor afd = getAssets().openFd("piano.wav");
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
                afd.close();
                mediaPlayer.prepare();
                mediaPlayer.start();

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

        enableSeekBar();
    }

    public void stopPlaying(){
        if(mediaPlayer!=null){
            mediaPlayer.stop();
        }
    }

    public void enableSeekBar(){
        seekBar =  findViewById(R.id.seekBar);
        seekBar.setMax(mediaPlayer.getDuration());

        new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {

                if(mediaPlayer!=null && mediaPlayer.isPlaying()){
                    seekBar.setProgress(mediaPlayer.getCurrentPosition());
                }
            }
        }, 0, 10);


        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

                //Update the progress depending on seek bar
                if(fromUser){
                    mediaPlayer.seekTo(progress);
                }

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }

    @Override
    public void onBackPressed() {
        stopPlaying();
        super.onBackPressed();
    }

}

MusicListActivity

This activity lists all the audio files in the internal memory of our Android device and we can select them to play in our MusicPlayerActivity.

XML layout: activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MusicListActivity">

<android.support.v7.widget.RecyclerView
android:id="@+id/audioListView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>

Java Class: MusicListActivity.java

package com.hack4m.android.basicmusicplayer;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MusicListActivity extends AppCompatActivity {

    RecyclerView audioListView;
    AudioListAdapter audioListAdapter;
    Context context;

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


        //Checks permissions
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

                requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1);
                return;
            }
        }

        //Finds all the mp3 files in device and makes a list
        getSongs();

    }

    public void getSongs(){
        context = MusicListActivity.this;
        audioListView = findViewById(R.id.audioListView);

        List allAudioFiles = getAllAudioFromDevice(context);

        audioListAdapter = new AudioListAdapter(context,allAudioFiles);
        audioListView.setLayoutManager(new LinearLayoutManager(context));
        audioListView.setAdapter(audioListAdapter);
    }

    public List getAllAudioFromDevice(final Context context) {

        final List tempAudioList = new ArrayList<>();

        Uri uri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;
        String[] projection = {MediaStore.Audio.AudioColumns.DATA, MediaStore.Audio.AudioColumns.ALBUM, MediaStore.Audio.ArtistColumns.ARTIST,};
        Cursor c = context.getContentResolver().query(uri,
                projection,
                null,
                null,
                null);

        if (c != null) {
            while (c.moveToNext()) {

                AudioModel audioModel = new AudioModel();

                String path = c.getString(0);
                String album = c.getString(1);
                String artist = c.getString(2);

                String name = path.substring(path.lastIndexOf("/") + 1);

                audioModel.setaName(name);
                audioModel.setaAlbum(album);
                audioModel.setaArtist(artist);
                audioModel.setaPath(path);

                tempAudioList.add(audioModel);
            }
            c.close();
        }

        return tempAudioList;
    }

    //Handling callback
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 1: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    getSongs();
                    Toast.makeText(context,"Permission granted",Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(context,"Permission denied",Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
}

This activity scans the internal memory of the device and creates a list of audio files. We pass that list to the RecyclerView adapter (Create a List with RecyclerView ) which adds them in the RecyclerView and we can see the list on our screen.

 

XML design for a single row in the RecyclerView: audio_list_row.xml 

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/audioName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Placeholder"
android:padding="20dp"
android:layout_marginTop="3dp"
android:background="#fff"
android:layout_marginBottom="3dp" />

</android.support.constraint.ConstraintLayout>

The Adapter class: AudioListAdapter.java

package com.hack4m.android.basicmusicplayer;

import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.List;

public class AudioListAdapter extends RecyclerView.Adapter {

    private List audioDataSet;
    private LayoutInflater mInflater;
    Context mContext;

    public AudioListAdapter(Context context, List audioModelList){

        mInflater = LayoutInflater.from(context);
        mContext = context;
        audioDataSet = audioModelList;
    }

    @NonNull
    @Override
    public AudioViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        // create a new view
        View v = mInflater.inflate(R.layout.audio_list_row, viewGroup, false);

        AudioViewHolder vh = new AudioViewHolder(mContext,audioDataSet,v);
        return vh;
    }

    @Override
    public void onBindViewHolder(@NonNull AudioViewHolder audioViewHolder, int i) {
        audioViewHolder.mTextView.setText(audioDataSet.get(i).getaName());
    }

    @Override
    public int getItemCount() {
        return audioDataSet.size();
    }

    public static class AudioViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        Context nContext;
        List audioList;
        public TextView mTextView;

        public AudioViewHolder(Context context,List audioModelList, View v) {
            super(v);
            nContext = context;
            audioList = audioModelList;
            mTextView = v.findViewById(R.id.audioName);

            v.setOnClickListener(this);
        }

        @Override
        public void onClick(View view){

            int itemPosition = getAdapterPosition();

            Intent intent = new Intent(nContext,MusicPlayerActivity.class);
            intent.putExtra("audio",audioList.get(itemPosition));

            nContext.startActivity(intent);

        }
    }
}

And the last class in our app: AudioModel.java

package com.hack4m.android.basicmusicplayer;

import java.io.Serializable;

public class AudioModel implements Serializable {

    String aPath;
    String aName;
    String aAlbum;
    String aArtist;

    public String getaPath() {
        return aPath;
    }

    public void setaPath(String aPath) {
        this.aPath = aPath;
    }

    public String getaName() {
        return aName;
    }

    public void setaName(String aName) {
        this.aName = aName;
    }

    public String getaAlbum() {
        return aAlbum;
    }

    public void setaAlbum(String aAlbum) {
        this.aAlbum = aAlbum;
    }

    public String getaArtist() {
        return aArtist;
    }

    public void setaArtist(String aArtist) {
        this.aArtist = aArtist;
    }
}

That's it, these are all the files we need to develop this basic audio player.

Try the code,  comment if you run into any problem implementing the project.
I will try to explain the code later by editing this blog, till then you have Google!

This project is open-source and  hosted on GitHub: https://github.com/hack4mer/Android-BasicMusicPlayer.git
APK file:  https://drive.google.com/file/d/17Wj6lZC7cDONn4C0jsmdVJdW6sxLnoUN/view?usp=sharing

Comments