Create a simple MP3 player in Android

In this post, you will learn to create a simple MP3 player in Android devices. Many interesting subjects in Android are involved while creating a simple MP3 player. Such as Cursor,ListView, Customized List View Adapter, SeekBar, Thread, MediaPlayer and Runtime permission for Marshmallow 6.0.

I am going just write the codes here. This post is suitable for Basic and Intermediate level android programmers.

MainActivity.java


public class MainActivity extends AppCompatActivity implements MediaPlayer.OnPreparedListener {
    List SongPath=new ArrayList<>();
    List SongNames=new ArrayList<>();
    List AlbumNames=new ArrayList<>();
    ListAlbumDuration=new ArrayList<>();
    List AlbumArts=new ArrayList<>();
    public static final int MY_PERMISSION_REQUEST_READ_EXTERNAL_STORAGE=1;
    String [] sngPath,sngName,AlbName,sngduration;
    Integer[] AlbumImages;
    static String TAG;
    String SongPosition;
    long mSongDuration;
    MediaPlayer mp;
    ImageButton play;
    ListView listView;
    SeekBar seekBar;
    TextView SongProgress,SongMaxLength;




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

        showSongsList();
        seekBar=(SeekBar)findViewById(R.id.seekBar);
        SongProgress=(TextView)findViewById(R.id.textView4);
        SongMaxLength=(TextView)findViewById(R.id.textView5);


    }
    //creating a method to show songs list only if permission is granted
    public void showSongsList(){
        if(ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED){
            if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.READ_EXTERNAL_STORAGE)){

            }else{
                ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},MY_PERMISSION_REQUEST_READ_EXTERNAL_STORAGE);
            }
        }else{

            //Getting songs from cursor
            getSongs();

            //Converting List to String[]
            sngPath=SongPath.toArray(new String[SongPath.size()]);
            sngName=SongNames.toArray(new String[SongNames.size()]);
            AlbName=AlbumNames.toArray(new String[AlbumNames.size()]);
            sngduration=AlbumDuration.toArray(new String[AlbumDuration.size()]);

            //Showing collected data from cursor using listView
             listView=(ListView)findViewById(R.id.list);
            CustomListAdapter adapter=new CustomListAdapter(this,sngPath,sngName,AlbName,sngduration,AlbumImages);
            listView.setAdapter(adapter);

            //Creating a method to play selected song.
            getSelectedSong();
            mp = new MediaPlayer();
            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mp.setOnPreparedListener(this);
            PrepareMediaPlayer();
            Log.d(TAG,"OnCreate service");
            play=(ImageButton)findViewById(R.id.imageButton);
            play.setOnClickListener(new View.OnClickListener() {
                @Override                public void onClick(View v) {
                    if (mp.isPlaying()) {
                        mp.pause();
                        play.setImageResource(R.mipmap.ic_pause_circle_outline_black_24dp);
                        ImageView img=(ImageView)findViewById(R.id.imageView);
                        img.setImageResource(R.mipmap.ic_play_circle_outline_black_24dp);

                    } else {
                        mp.start();
                    }
                    play.setImageResource(R.mipmap.ic_play_circle_outline_black_24dp);
                }
            });



        }
    }




    //Once User responds to RequestRunTimePermission() method, output executed by the below method.
    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case -1:
                //hello
                break;
            case MY_PERMISSION_REQUEST_READ_EXTERNAL_STORAGE:
                if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
                    showSongsList();
                }
                else{
                    Toast.makeText(getApplicationContext(),"You've denied permission",Toast.LENGTH_LONG).show();
                }return;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }


    }

    //A method for getting Track name and Album name using cursor.
public void getSongs(){
    try{
        ContentResolver contentResolver=getContentResolver();

        Uri uri=EXTERNAL_CONTENT_URI;
        Cursor cursor=contentResolver.query(uri,null,MediaStore.Audio.Media.IS_MUSIC + " =1",null,null);

        if(cursor != null && cursor.moveToFirst()){
            int songname=cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME);
            int songalbum=cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM);
            int songpath=cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
            int songduration=cursor.getColumnIndex(MediaStore.Audio.Media.DURATION);
            do{
                String CurrentSongPath=cursor.getString(songpath);
                String CurrentSongName=cursor.getString(songname);
                String CurrentSongAlbum=cursor.getString(songalbum);
                String CurrentSongDuration= cursor.getString(songduration);
                String AlbumId=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
                SongPath.add(CurrentSongPath);
                SongNames.add(CurrentSongName);
                AlbumNames.add(CurrentSongAlbum);
                AlbumDuration.add(CurrentSongDuration);
                AlbumArts.add(Integer.valueOf(AlbumId));
            }while(cursor.moveToNext());
        }cursor.close();
    }catch(NumberFormatException e){e.printStackTrace();}
}

    //Creating a method for songs selection
public void getSelectedSong(){
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override        public void onItemClick(AdapterView adapterView, View view, int i, long l) {
            SongPosition= String.valueOf(listView.getItemAtPosition(i));
            ImageView img=(ImageView)view.findViewById(R.id.imageView);
            img.setImageResource(R.mipmap.ic_equalizer_black_24dp);
            play.setImageResource(R.mipmap.ic_pause_circle_outline_black_24dp);
            mp.reset();
            PrepareMediaPlayer();
            TextView txtview=(TextView)view.findViewById(R.id.textView6);
            mSongDuration= Long.parseLong(txtview.getText().toString());




        }
    });
}
    //creating a method for playing a song.
    public void PrepareMediaPlayer(){
        if(SongPosition==null){
            Log.d(TAG,"Nothing Selected from the list");
        }else {

            try {
                Log.d(TAG, "setAudioStreamType");

                mp.setDataSource(SongPosition);

                Log.d(TAG, "setDataSource");

                mp.prepareAsync();

                Log.d(TAG, "prepareAsync");


            } catch (IOException e) {
            } catch (IllegalArgumentException e) {
            } catch (IllegalStateException e) {
            }
        }
    }


    @Override    public void onPrepared(MediaPlayer mediaPlayer) {
        mp.start();
         getDurationTimer();
        getSeekBarStatus();


    }
    //Creating duration time method
    public void getDurationTimer(){
        final long minutes=(mSongDuration/1000)/60;
        final int seconds= (int) ((mSongDuration/1000)%60);
        SongMaxLength.setText(minutes+ ":"+seconds);


    }


    //creating a method for seekBar progress
    public void getSeekBarStatus(){

        new Thread(new Runnable() {

            @Override            public void run() {
                // mp is your MediaPlayer
                // progress is your ProgressBar

                int currentPosition = 0;
                int total = mp.getDuration();
                seekBar.setMax(total);
                while (mp != null && currentPosition < total) {
                    try {
                        Thread.sleep(1000);
                        currentPosition = mp.getCurrentPosition();
                    } catch (InterruptedException e) {
                        return;
                    }
                    seekBar.setProgress(currentPosition);

                }
            }
        }).start();





        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            int progress=0;

            @Override            public void onProgressChanged(final SeekBar seekBar, int ProgressValue, boolean fromUser) {
                if (fromUser) {
                    mp.seekTo(ProgressValue);//if user drags the seekbar, it gets the position and updates in textView.
                }
                final long mMinutes=(ProgressValue/1000)/60;//converting into minutes
                final int mSeconds=((ProgressValue/1000)%60);//converting into seconds
                SongProgress.setText(mMinutes+":"+mSeconds);
            }

            @Override            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }

    @Override    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }
}


CustomListAdapter.java


public class CustomListAdapter extends ArrayAdapter {
    private Activity context;
    private String[] Path;
    private String[] Track;
    private String[] Description;
    private String[] Duration;
    private Integer[] AlbumImage;

    public  CustomListAdapter(Activity context,String[] Path ,String[] Track, String[] Description,String[] Duration,Integer[] AlbumImage){
        super(context,R.layout.list_item,R.id.textView,Path);
        this.context=context;
        this.Path=Path;
        this.Track=Track;
        this.Description=Description;
        this.Duration=Duration;
        this.AlbumImage=AlbumImage;


    }
    private class ViewHolder{
        TextView path;
        TextView track;
        TextView description;
        TextView duration;
        ImageView imgview;


    }

    @NonNull    @Override    public View getView(int position, View convertView, ViewGroup parent) {

    ViewHolder holder;
        LayoutInflater inflater=context.getLayoutInflater();
        if(convertView==null){

            convertView=inflater.inflate(R.layout.list_item,null);
            holder=new ViewHolder();
            holder.path=(TextView)convertView.findViewById(R.id.textView);
            holder.track=(TextView)convertView.findViewById(R.id.textView2);
            holder.description=(TextView)convertView.findViewById(R.id.textView3);
            holder.duration=(TextView)convertView.findViewById(R.id.textView6);
            holder.imgview=(ImageView)convertView.findViewById(R.id.imageView);




            //store the data in view
            convertView.setTag(holder);
        }
        else{
            //we've just avoided calling findViewById() on resource everytime
            //just use view holder
            holder=(ViewHolder)convertView.getTag();
        }
        holder.path.setText(Path[position]);
        holder.track.setText(Track[position]);
        holder.description.setText(Description[position]);
        holder.duration.setText(Duration[position]);
        holder.imgview.setImageResource(R.mipmap.ic_album_black_24dp);



        return convertView;
    }
}

create an xml for customlistadapter

list_item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">

    <ImageView        android:layout_width="90dp"        android:layout_height="60dp"        app:srcCompat="@mipmap/ic_launcher"        android:contentDescription="Image"        android:id="@+id/imageView"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true"        android:layout_alignTop="@+id/textView" />

    <TextView        android:text="TextView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="18dp"        android:id="@+id/textView2"        android:layout_marginLeft="32dp"        android:layout_marginStart="32dp"        android:layout_below="@+id/textView"        android:layout_toRightOf="@+id/imageView"        android:layout_toEndOf="@+id/imageView" />

    <TextView        android:text="TextView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="13dp"        android:textSize="0dp"        android:id="@+id/textView"        android:layout_alignParentTop="true"        android:layout_alignLeft="@+id/textView2"        android:layout_alignStart="@+id/textView2" />

    <TextView        android:text="TextView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@+id/textView2"        android:layout_toRightOf="@+id/textView"        android:layout_toEndOf="@+id/textView"        android:id="@+id/textView3" />

    <TextView        android:text="TextView"        android:textSize="0dp"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignBottom="@+id/imageView"        android:layout_alignLeft="@+id/textView3"        android:layout_alignStart="@+id/textView3"        android:id="@+id/textView6" />

</RelativeLayout>


activity_main.xml(portrait)

<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:id="@+id/activity_main"    android:layout_width="match_parent"    android:background="#909090"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.cerebri.learning2.MainActivity"    android:weightSum="1">


    <ImageButton        android:layout_width="80dp"        android:layout_height="80dp"        android:scaleType="fitXY"        android:background="#909090"        app:srcCompat="@mipmap/ic_play_circle_outline_black_24dp"        android:id="@+id/imageButton"        android:layout_above="@+id/seekBar"        android:layout_centerHorizontal="true" />

    <SeekBar        android:layout_width="290dp"        android:layout_height="wrap_content"        android:maxWidth="3dp"        android:maxHeight="3dp"        android:layout_alignParentBottom="true"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true"        android:layout_marginLeft="35dp"        android:layout_marginStart="35dp"        android:layout_marginBottom="34dp"        android:id="@+id/seekBar"         />

    <TextView        android:text=""        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginLeft="16dp"        android:layout_marginStart="16dp"        android:layout_marginBottom="12dp"        android:id="@+id/textView4"        android:layout_alignParentBottom="true"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true" />

    <TextView        android:text=""        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignBottom="@+id/textView4"        android:layout_alignRight="@+id/list"        android:layout_alignEnd="@+id/list"        android:id="@+id/textView5" />

    <ListView        android:layout_width="match_parent"        android:layout_height="350dp"        android:id="@+id/list"        android:layout_alignParentTop="true"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true" />


</RelativeLayout>


activity_main.xml(Landscape)

just copy and paste the same activity_main.xml file into Layou-land folder under res and design xml file according landscape view.


<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:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#909090"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.cerebri.learning2.MainActivity"    android:weightSum="1">


    <ImageButton        android:layout_width="80dp"        android:layout_height="80dp"        android:scaleType="fitXY"        android:background="#909090"        app:srcCompat="@mipmap/ic_play_circle_outline_black_24dp"        android:id="@+id/imageButton"        android:layout_above="@+id/seekBar"        android:layout_centerHorizontal="true" />

    <ListView        android:layout_width="match_parent"        android:layout_height="130dp"        android:id="@+id/list"        android:layout_alignParentTop="true"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true" />

    <SeekBar        android:layout_width="450dp"        android:layout_height="wrap_content"        android:id="@+id/seekBar"        android:maxHeight="3dp"        android:maxWidth="3dp"        android:layout_marginBottom="30dp"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"         />

    <TextView        android:text=""        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true"        android:layout_marginLeft="23dp"        android:layout_marginStart="23dp"        android:layout_marginBottom="10dp"        android:id="@+id/textView4" />

    <TextView        android:text=""        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignBottom="@+id/textView4"        android:layout_alignParentRight="true"        android:layout_alignParentEnd="true"        android:layout_marginRight="38dp"        android:layout_marginEnd="38dp"        android:id="@+id/textView5" />


</RelativeLayout>


AndroidManifest.xml

Make sure you add the highlighted things.
<uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"            android:configChanges="screenLayout|screenSize"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>


Comments

Popular posts from this blog

Reasoning-Number Series

Reasoning-Letter Series

Multiply Negative numbers in java