Android Media Player Song With SeekBar

Filed Under: Android

In this tutorial, we’ll use the MediaPlayer class to implement a basic Audio Player in our Android Application. We’ll add a Play/Stop feature and also allow the user to change the position of the song with a SeekBar.

Android MediaPlayer

MediaPlayer class is used for playing Audio and Video files. The common methods of the MediaPlayer class that we’ll use are:

  • start()
  • stop()
  • release() – To prevent memory leaks.
  • seekTo(position) – This will be used with the SeekBar
  • isPlaying() – Let’s us know whether the song is being played or not.
  • getDuration() – Is used to get the total duration. Using this we’ll know the upper limit of our SeekBar. This function returns the duration in milli seconds
  • setDataSource(FileDescriptor fd) – This is used to set the file to be played.
  • setVolume(float leftVolume, float rightVolume) – This is used to set the volume level. The value is a float between 0 an 1.

We’ll be playing an mp3 file stored in the assets folder of our Android Studio Project.

Fetching the sound assets file from the Assets folder


AssetFileDescriptor descriptor = getAssets().openFd("filename");
                mediaPlayer.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
                descriptor.close();

In order to create an Application that plays Audio and lets you change the position of the current song track we need to implement three things:

  • MediaPlayer
  • SeekBar With Text – To show the current progress time besides the thumb.
  • Runnable Thread – To update the Seekbar.

Project Structure

android media player song seekbar project

Add the following dependency in your build.gradle:


implementation 'com.android.support:design:28.0.0-alpha3'

Code

The code for the activity_main.xml is given below:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:layout_gravity="center"
    android:gravity="center"
    android:layout_margin="16dp"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="PLAY/STOP SONG.\nSCRUB WITH SEEKBAR"
        android:textStyle="bold" />


    <SeekBar
        android:id="@+id/seekbar"
        android:layout_margin="16dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />


    <android.support.design.widget.FloatingActionButton
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@android:drawable/ic_media_play"
        android:text="PLAY SOUND" />

</LinearLayout>

We’ve added a FloatingActionButon that’ll play/stop when clicked.

The code for the MainActivity.java class is given below:


package com.journaldev.androidmediaplayersong;

import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements Runnable {


    MediaPlayer mediaPlayer = new MediaPlayer();
    SeekBar seekBar;
    boolean wasPlaying = false;
    FloatingActionButton fab;

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


        fab = findViewById(R.id.button);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                playSong();
            }
        });

        final TextView seekBarHint = findViewById(R.id.textView);

        seekBar = findViewById(R.id.seekbar);

        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

                seekBarHint.setVisibility(View.VISIBLE);
            }

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
                seekBarHint.setVisibility(View.VISIBLE);
                int x = (int) Math.ceil(progress / 1000f);

                if (x < 10)
                    seekBarHint.setText("0:0" + x);
                else
                    seekBarHint.setText("0:" + x);

                double percent = progress / (double) seekBar.getMax();
                int offset = seekBar.getThumbOffset();
                int seekWidth = seekBar.getWidth();
                int val = (int) Math.round(percent * (seekWidth - 2 * offset));
                int labelWidth = seekBarHint.getWidth();
                seekBarHint.setX(offset + seekBar.getX() + val
                        - Math.round(percent * offset)
                        - Math.round(percent * labelWidth / 2));

                if (progress > 0 && mediaPlayer != null && !mediaPlayer.isPlaying()) {
                    clearMediaPlayer();
                    fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, android.R.drawable.ic_media_play));
                    MainActivity.this.seekBar.setProgress(0);
                }

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {


                if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                    mediaPlayer.seekTo(seekBar.getProgress());
                }
            }
        });
    }

    public void playSong() {

        try {


            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                clearMediaPlayer();
                seekBar.setProgress(0);
                wasPlaying = true;
                fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, android.R.drawable.ic_media_play));
            }


            if (!wasPlaying) {

                if (mediaPlayer == null) {
                    mediaPlayer = new MediaPlayer();
                }

                fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, android.R.drawable.ic_media_pause));

                AssetFileDescriptor descriptor = getAssets().openFd("suits.mp3");
                mediaPlayer.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
                descriptor.close();

                mediaPlayer.prepare();
                mediaPlayer.setVolume(0.5f, 0.5f);
                mediaPlayer.setLooping(false);
                seekBar.setMax(mediaPlayer.getDuration());

                mediaPlayer.start();
                new Thread(this).start();

            }

            wasPlaying = false;
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    public void run() {

        int currentPosition = mediaPlayer.getCurrentPosition();
        int total = mediaPlayer.getDuration();


        while (mediaPlayer != null && mediaPlayer.isPlaying() && currentPosition < total) {
            try {
                Thread.sleep(1000);
                currentPosition = mediaPlayer.getCurrentPosition();
            } catch (InterruptedException e) {
                return;
            } catch (Exception e) {
                return;
            }

            seekBar.setProgress(currentPosition);

        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        clearMediaPlayer();
    }

    private void clearMediaPlayer() {
        mediaPlayer.stop();
        mediaPlayer.release();
        mediaPlayer = null;
    }
}

In the above code on clicking the FloatingActionButton, the playSong function gets triggered in which we stop the song and reset the MediaPlayer and FloatingActionButton icon every second time.

Once the mediaPlayer.prepare() is called, the details are available for the song. We can now get the duration and set it on the SeekBar max position.

setLoooping to false prevents the song from playing infinitely until stopped by the user.

We start the thread which triggers the run method which was a part of the Runnable interface that we've implemented.

Inside the run method, we update the progress every second which triggers the onProgressChanged method of the SeekBar listener.

Inside the listener, we've set the TextView offset to below the SeekBar's thumb. We set the time duration by converting the milliseconds to seconds there.

When the seek bar is moved the same method is triggered. When the user stops scrubbing the SeekBar the onStopTrackingTouch is triggered in which using the seekTo method we update the song position on the MediaPlayer instance.

Once the song is completed, we update the position of the SeekBar back to the initial and clear the MediaPlayer instance.

The output of the application without audio is given below:

android media player song seekbar output

This brings an end to this tutorial. You can download the project from the link below and play the song for yourself.

Comments

  1. Manish says:

    How can i add music from mobile… on button click..please help me

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages