MediaPlayer Tutorial and Examples
Android MediaPlayer Tutorial and Examples.
Here we want to explore some examples regarding the MediaPlayer
class using simple step by step examples written in either Kotlin or Java.
Why MediaPlayer?
Mobile devices have these days become many people's primary source of entertainment. Not only do we use them as our personal assistants which allow us schedule reminders, keep todo lists, shopping and even wish lists, but we also play games and music through them.
Some years back,probably just a decade ago, it was very expensive to find a phone that could do all these. During those days we had feature phones like nokia, sony ericson, alcatel,siemens etc. These phones were not smartphones and didn't do alot more than calling and sending text messages.
However, these days smarphones are as easy to get as almost anything else. Not just in tier one countries but also in poor countries people have powerful smartphones that can:
- Access the internet, Send emails, Whatsapp etc.
- Play media files like mp3 and mp4 songs.
- Install other apps.
MediaPlayer as a class therefore allows us continue this rich tradition of empowering users. These days we don't media files only for entertainment but also for educative purposes. Hence this class is one of the most empowering android framework classes that is continuing to revolutionize the tech world.
Example 1: Android Simple ListView MP3 Player Example
In this example we want to see how to create a simple MP3 Player using ListView and MediaPlayer
class. We load mp3 files from our external storage and show them in a simple listview. We do this recursively so that we don't miss songs found in sub-directories. We display the song names in a ListView.
Then when the user clicks a single song in our ListView, we open a new activity, a Player activity and automatically play the song. We will be passing the song path to that activity. Then we use the MediaPlayer
class to play the song.
As we play the song we display the a Lottie Animation. When the user will click the back button of our Player Activity, we will continue playing the song. In fact even if we open a new app, that is our app is paused we still continue playing the song.
Here is the screenshot demo of what we create:
1. MainActivity.java
Here's our MainActivity. The main responsibility of this class is to show our ListView of MP3 songs. To turn it into an Activity we derive from the android.app.Activity
class.
Among our imports include the java.io.File
as we are reading the file system. Please make sure you add the READ_EXTERNAL_STORAGE
permission in your android manifest. We also have the android.os.AsyncTask
, a class that allows us implement basic threading. In this case we create a simple asynctask to read our songs in the background. We've called it the SongsLoaderAsyncTask
. AsyncTask is an abstract class so we have to atleast override the doInBackground
method. The android.widget.ProgressBar
allows us show an indeterminate progressbar as we read our songs into the listview.
android.widget.ListView
is our list component. android.widget.ArrayAdapter
will be enough for us to adapt our simple data to our listview.
package info.camposha.mrmp3player;
import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Toast;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
private ListView listview;
private String mediaPath;
private List<String> songs = new ArrayList<String>();
private MediaPlayer mediaPlayer = new MediaPlayer();
private SongsLoaderAsyncTask task;
ProgressBar songsLoadingProgressBar;
ArrayList<String> songNames=new ArrayList<>();
/**
* We will scan and load all mp3 files in a background thread via asynctask.
*/
// Use AsyncTask to read all mp3 file names
private class SongsLoaderAsyncTask extends AsyncTask<Void, String, Void> {
private List<String> loadedSongs = new ArrayList<String>();
/**
* Before our background starts
*/
protected void onPreExecute() {
songsLoadingProgressBar.setVisibility(View.VISIBLE);
songNames.clear();
Toast.makeText(getApplicationContext(),"Scanning Songs..Please Wait.",Toast.LENGTH_LONG).show();
}
/**
* Load files in background thread here
* @param url
* @return
*/
protected Void doInBackground(Void... url) {
updateSongListRecursive(new File(mediaPath));
return null;
}
/**
* Recursively Load Files From ExternalStorage
* @param path
*/
public void updateSongListRecursive(File path) {
if (path.isDirectory()) {
for (int i = 0; i < path.listFiles().length; i++) {
File file = path.listFiles()[i];
updateSongListRecursive(file);
}
} else {
String songPath = path.getAbsolutePath();
String songName=path.getName();
publishProgress(songPath);
if (songPath.endsWith(".mp3")) {
loadedSongs.add(songPath);
songNames.add(songName.substring(0,songName.length()-4));
}
}
}
/**
* When our background work is over.
* @param args
*/
protected void onPostExecute(Void args) {
songsLoadingProgressBar.setVisibility(View.GONE);
ArrayAdapter<String> songList = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, songNames);
listview.setAdapter(songList);
songs = loadedSongs;
Toast.makeText(getApplicationContext(),"Scanning Complete."+songs.size()+" Songs Found.",Toast.LENGTH_LONG).show();
}
}
/*
*OPEN PLAYER ACTIVITY PASSING THE SONG TO PLAYER
*/
private void openPlayerActivity(int position)
{
Intent i=new Intent(this,PlayerActivity.class);
i.putExtra("SONG_KEY",songs.get(position));
startActivity(i);
}
/**
* When the activity is created.
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
songsLoadingProgressBar=findViewById(R.id.myProgressBar);
listview = findViewById(R.id.mListView);
mediaPath = Environment.getExternalStorageDirectory().getPath() + "/Music/";
//mediaPath = Environment.getExternalStorageDirectory().getPath() + "/Download/";
//mediaPath = Environment.getExternalStorageDirectory().getPath() + "/mnt/shared/Other/";
//mediaPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getPath() ;
//mediaPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() ;
// itemclick listener for our listview
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
openPlayerActivity(position);
}
});
//instantiate and execute our asynctask
task = new SongsLoaderAsyncTask();
task.execute();
}
/** Called when the activity is stopped */
@Override
public void onStop() {
super.onStop();
if (mediaPlayer.isPlaying()) mediaPlayer.reset();
}
}
2. PlayerActivity.java
Here's our PlayerActivity. This activity will play our song. As we play the song we will use the LottieAnimationView
to play our animation. Obviously MediaPlayer
is the class responsible for playing our mp3 files.
package info.camposha.mrmp3player;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.media.MediaPlayer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.airbnb.lottie.LottieAnimationView;
import java.io.IOException;
public class PlayerActivity extends AppCompatActivity {
private MediaPlayer mediaPlayer = new MediaPlayer();
TextView songTxt;
LottieAnimationView rippleAnimation;
String songToPlay;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
initializeViews();
receiveSong();
playSong();
}
/**
* Initialize widgets
*/
private void initializeViews(){
songTxt=findViewById(R.id.songTxt);
rippleAnimation = findViewById(R.id.lottieloading);
}
private void receiveSong(){
//receive passed song via intent
Intent i=this.getIntent();
songToPlay=i.getStringExtra("SONG_KEY");
}
private void playSong(){
//TextView to display the song name
songTxt.setText(songToPlay);
if(TextUtils.isEmpty(songToPlay))
{
Toast.makeText(this, "Hey PlayerActivity has received a null or empty song.", Toast.LENGTH_LONG).show();
}
else{
try {
mediaPlayer.reset();
// in recursive version
mediaPlayer.setDataSource(songToPlay);
mediaPlayer.prepare();
mediaPlayer.start();
} catch(IOException e) {
Toast.makeText(getBaseContext(), "Cannot Play Song!", Toast.LENGTH_SHORT).show();
}
}
showSplash();
}
public void showSplash() {
if (mediaPlayer.isPlaying()) {
rippleAnimation.setAnimation(R.raw.ripple);
rippleAnimation.playAnimation();
} else {
rippleAnimation.pauseAnimation();
}
}
/** Called when the activity is stopped */
@Override
public void onStop() {
super.onStop();
//if you want to stop playing when this activity is closed then uncomment this.
// if (mediaPlayer.isPlaying()){
// mediaPlayer.reset();
// rippleAnimation.pauseAnimation();
// }
}
}
3. activity_main.xml
This is the layout to be used as the user interface for MainActivity
. First it will contain a header textview to display our header text. Then below it we have a ListView to render our data in a list. We arrange them linearly using a LinearLayout with vertical orientation.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_orientation="vertical"
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=".MainActivity">
<TextView
android_id="@+id/headerTxt"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_padding="5dp"
android_text="ListView MP3 Player"
android_textAlignment="center"
android_textAppearance="@style/TextAppearance.AppCompat.Large"
android_textColor="@color/colorAccent"
android_textStyle="bold" />
<ProgressBar
android_id="@+id/myProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_indeterminate="true"
android_indeterminateBehavior="cycle"
android_visibility="gone" />
<ListView
android_id="@+id/mListView"
android_layout_width="match_parent"
android_layout_height="wrap_content"/>
</LinearLayout>
4. activity_player.xml
This is the layout responsible for showing our LottieAnimationView
. We will be showing an animation as our song plays. We wrap a TextView and LottieAnimationView
inside a RelativeLayout.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_id="@+id/activity_mp3_player"
android_layout_width="match_parent"
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"
android_background="#25272d"
tools_context="info.camposha.mrmp3player.PlayerActivity">
<TextView
android_id="@+id/songTxt"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_centerHorizontal="true"
android_textColor="@android:color/white"
android_textSize="10sp"
android_text="Rock With You"
android_layout_marginTop="50dp"/>
<com.airbnb.lottie.LottieAnimationView
android_id="@+id/lottieloading"
android_layout_width="match_parent"
android_layout_height="match_parent"
app_lottie_loop="true" />
</RelativeLayout>
5. AndroidManifest.xml
Add permission to read from songs from external storage
Download
Here are reference resources:
No. | Location | Link |
---|---|---|
1. | GitHub | Direct Download |
2. | GitHub | Browse |
3. | YouTube | Video Tutorial |
4. | YouTube | ProgrammingWizards TV Channel |
Example 2: Android MP3 MusicPlayer with Background Service
This example now shows you how you can play a music player via the MediaPlayer API alongside a Service.
Check the screenshot demo below:
Step 1: Create Project
Start by creating an empty Android Studio
project.
Step 2: Dependencies
No external or special dependency is needed for this project.
Step 3: Add Music
In your res
directory create a folder known as raw
and add your mp3 song inside it:
Step 4: Design Layout
Add two buttons: one to start our music player and the other to stop it, inside the MainActivity layout as shown below:
activity_main.xml
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
tools:context="com.example.ankitkumar.music_player.MainActivity"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/activity_main"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/button_start"
android:layout_marginBottom="103dp"
android:layout_alignLeft="@+id/button_stop"
android:layout_above="@+id/button_stop"
android:textStyle="bold"
android:textAllCaps="false"
android:text="@string/start"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/button_stop"
android:layout_marginBottom="169dp"
android:textStyle="bold"
android:textAllCaps="false"
android:text="@string/stop"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
Step 5: Create Music Service
We will be playing our music in a background service. Start by creating a file known as MusicService.java
and add the following imports:
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
Then extend the android.app.Service
class:
Declare the MediaPlayer object as our Musicplayer and override the onBind()
, in this case to return null:
Now override the onCreate()
. Inside it we will create our MusicPlayer by initiating the MediaPlayer using the create()
method. We pass the Context
as well as the Music Path:
@Override
public void onCreate()
{
super.onCreate();
musicPlayer = MediaPlayer.create(getApplicationContext(), R.raw.mission);
}
We will the override the onStartCommand()
. We will start our MusicPlayer here:
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
musicPlayer.start();
musicPlayer.setLooping(true);
return super.onStartCommand(intent, flags, startId);
}
In the onDestroy()
callback we will stop our MediaPlayer and release it:
@Override
public void onDestroy()
{
musicPlayer.stop();
musicPlayer.release();
super.onDestroy();
}
}
Here is the full code:
MusicService.java
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
public class MusicService extends Service {
MediaPlayer musicPlayer;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate()
{
super.onCreate();
musicPlayer = MediaPlayer.create(getApplicationContext(), R.raw.mission);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
musicPlayer.start();
musicPlayer.setLooping(true);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy()
{
musicPlayer.stop();
musicPlayer.release();
super.onDestroy();
}
}
Step 6: Create Activity
We have only one activity: our MainActivity:
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
MusicService musicService;
Button button_start, button_stop;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button_start = (Button) findViewById(R.id.button_start);
button_stop = (Button) findViewById(R.id.button_stop);
button_start.setOnClickListener(this);
button_stop.setOnClickListener(this);
}
@Override
public void onClick(View v)
{
if (v.getId() == R.id.button_start)
{
Intent intent = new Intent(this, MusicService.class);
startService(intent);
Log.e("button_start","startIntent");
}
else
{
Intent intent = new Intent(this, MusicService.class);
stopService(intent);
}
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
Example 3: Kotlin Android Audio Player App
In this third example we will write our music player or audioplayer with Kotlin.
Here is what is created:
Step 1: Create Project
Start by creating an empty Android Studio
kotlin project.
Step 2: Dependencies
No third party dependency is needed for this project. We however use Kotlin so make sure you've created a Kotlin project.
Step 3: Design Music Player Layout
We will do this in our activity_main.xml
:
activity_main.xml
We will have an imageview,imagebuttons for navigating to next or previous songs as well as playing or pausing the music, seekbar and textview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="@dimen/medium_margin">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/medium_margin"
android:layout_weight="1"
android:background="?attr/selectableItemBackgroundBorderless"
android:paddingBottom="@dimen/medium_margin"
android:src="@mipmap/music" />
<ImageButton
android:id="@+id/play_pause_btn"
android:layout_width="49dp"
android:layout_height="49dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/medium_margin"
android:background="?attr/selectableItemBackgroundBorderless"
android:paddingBottom="@dimen/medium_margin"
android:src="@android:drawable/ic_media_play" />
<TextView
android:id="@+id/song_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center_horizontal"
android:maxLines="1"
android:textSize="14sp" />
<TextView
android:id="@+id/song_artist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:maxLines="1"
android:text="Simple Rock"
android:textSize="16sp" />
<SeekBar
android:id="@+id/progressbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/medium_margin"
android:paddingTop="@dimen/medium_margin" />
<TextView
android:id="@+id/tv_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/progressbar"
android:layout_marginBottom="@dimen/medium_margin"
android:layout_marginLeft="@dimen/medium_margin"
android:layout_marginRight="@dimen/medium_margin"
android:gravity="center_horizontal"
android:maxLines="1" />
</LinearLayout>
Step 4: Create a SeekBar Handler class
Create the class under the utils
and add the following code:
utils/SeekBarHandler.kt
import android.media.MediaPlayer
import android.os.AsyncTask
import android.widget.SeekBar
import android.widget.TextView
class SeekBarHandler(val seekbar: SeekBar?, var mediaPlayer: MediaPlayer?, var isViewOn: Boolean,val timer:TextView): AsyncTask<Void, Void, Boolean>() {
override fun onPreExecute() {
super.onPreExecute()
seekbar?.max = mediaPlayer?.duration!!
}
override fun onProgressUpdate(vararg values: Void?) {
super.onProgressUpdate(*values)
val time = mediaPlayer?.getCurrentPosition()!!
seekbar?.setProgress(time);
var seconds = (time / 1000)
val minutes = time / (1000 * 60) % 60
seconds = seconds - minutes * 60
timer.setText(minutes.toString()+":"+seconds.toString())
}
override fun onCancelled() {
super.onCancelled()
setViewOnOff(false)
}
fun setViewOnOff(isOn:Boolean) {
isViewOn = isOn
}
fun refreshMediaPlayer(mediaPlayer: MediaPlayer?) {
this.mediaPlayer = mediaPlayer
}
override fun doInBackground(vararg params: Void?): Boolean {
while (mediaPlayer?.isPlaying() == true && isViewOn == true) {
try {
Thread.sleep(200)
} catch (e: InterruptedException) {
e.printStackTrace()
}
publishProgress()
}
return true
}
override fun onPostExecute(result: Boolean?) {
super.onPostExecute(result)
}
}
Step 5: Create MainActivity
And add the following code:
MainActivity.kt
import android.media.MediaPlayer
import android.os.Bundle
import android.os.PowerManager
import android.util.Log
import android.view.View
import android.view.View.OnClickListener
import android.widget.ImageButton
import android.widget.SeekBar
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.talentica.androidkotlin.audioplayer.utils.LogHelper
import com.talentica.androidkotlin.audioplayer.utils.SeekBarHandler
class MainActivity : AppCompatActivity(), SeekBar.OnSeekBarChangeListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener,
MediaPlayer.OnPreparedListener, MediaPlayer.OnSeekCompleteListener, OnClickListener {
private val TAG = LogHelper.makeLogTag("MainActivity")
private var mMediaPlayer: MediaPlayer? = null
private var mPlayPauseButton: ImageButton? = null
private var mSeekbar:SeekBar? = null
private var mTimer:TextView? = null
private var seekBarHandler:SeekBarHandler? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mSeekbar = findViewById<SeekBar>(R.id.progressbar)
mSeekbar?.setOnSeekBarChangeListener(this)
mPlayPauseButton = findViewById<ImageButton>(R.id.play_pause_btn)
mPlayPauseButton?.setOnClickListener(this)
mTimer = findViewById<TextView>(R.id.tv_progress)
}
override fun onClick(v: View?) {
if (v?.id == R.id.play_pause_btn) {
togglePlayback()
}
}
fun togglePlayback() {
if (mMediaPlayer?.isPlaying == true) {
pauseAudio()
} else {
createMediaPlayerIfNeeded()
playAudio()
}
}
/**
* Makes sure the media player exists and has been reset. This will create
* the media player if needed, or reset the existing media player if one
* already exists.
*/
private fun createMediaPlayerIfNeeded() {
Log.d(TAG, "createMediaPlayerIfNeeded")
if (mMediaPlayer == null) {
mMediaPlayer = MediaPlayer.create(this, R.raw.simplerock)
// Make sure the media player will acquire a wake-lock while
// playing. If we don't do that, the CPU might go to sleep while the
// song is playing, causing playback to stop.
mMediaPlayer?.setWakeMode(this.getApplicationContext(),
PowerManager.PARTIAL_WAKE_LOCK)
// we want the media player to notify us when it's ready preparing,
// and when it's done playing:
mMediaPlayer?.setOnPreparedListener(this)
mMediaPlayer?.setOnCompletionListener(this)
mMediaPlayer?.setOnErrorListener(this)
mMediaPlayer?.setOnSeekCompleteListener(this)
}
}
fun playAudio() {
mMediaPlayer?.start()
seekBarHandler = SeekBarHandler(mSeekbar, mMediaPlayer, isViewOn = true, timer = mTimer!!)
seekBarHandler?.execute()
val pauseDrawabale = ContextCompat.getDrawable(this, android.R.drawable.ic_media_pause)
mPlayPauseButton?.setImageDrawable(pauseDrawabale)
}
fun pauseAudio() {
seekBarHandler?.cancel(true)
mMediaPlayer?.pause()
val playDrawabale = ContextCompat.getDrawable(this, android.R.drawable.ic_media_play)
mPlayPauseButton?.setImageDrawable(playDrawabale)
}
/**
* Releases resources used by the service for playback. This includes the
* "foreground service" status, the wake locks and possibly the MediaPlayer.
* @param releaseMediaPlayer Indicates whether the Media Player should also
* * be released or not
*/
private fun relaxResources(releaseMediaPlayer: Boolean) {
LogHelper.d(TAG, "relaxResources. releaseMediaPlayer=", releaseMediaPlayer)
seekBarHandler?.cancel(true)
seekBarHandler = null
// stop and release the Media Player, if it's available
if (releaseMediaPlayer && mMediaPlayer != null) {
mMediaPlayer?.reset()
mMediaPlayer?.release()
mMediaPlayer = null
}
}
override fun onPause() {
super.onPause()
if (mMediaPlayer?.isPlaying == true) {
pauseAudio()
}
}
override fun onBackPressed() {
super.onBackPressed()
relaxResources(true)
}
override fun onCompletion(mp: MediaPlayer?) {
relaxResources(true)
val playDrawabale = ContextCompat.getDrawable(this, android.R.drawable.ic_media_play)
mPlayPauseButton?.setImageDrawable(playDrawabale)
mSeekbar?.progress = 0
}
override fun onError(mp: MediaPlayer?, what: Int, extra: Int): Boolean {
return false
}
override fun onPrepared(mp: MediaPlayer?) {
}
override fun onSeekComplete(mp: MediaPlayer?) {
}
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser) {
val progress = seekBar?.progress
mMediaPlayer?.seekTo(progress!!)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
}
Step 6: Add Permission
In your AndroidManifest.xml
add the following permission:
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
Example 4: Kotlin Android MediaPlayer with Adjustable Volume
This is the fourth mediaplayer example for you. It is written in Kotlin and teaches not only how to play the media but also programmatically adjust the volume of the playing music. We will provide a seekbar for this.
Step 1: Create Project
Start by creating an empty Android Studio
project.
Step 2: Dependencies
No external dependencies are needed for this project.
Step 3: Add Music
Add a music to your raw folder. If you don't have such a folder create it inside the res
directory.
res/raw/music.mp3
Step 4: Design Layout
Design your MainActivity layout to resemble a music player view or interface using seekbar, imageviews, textviews, buttons etc as follows:
activity_main.xml
<?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:orientation="vertical"
android:gravity="center"
android:background="@android:color/white"
tools:context=".MainActivity">
<ImageView
android:layout_width="400dp"
android:layout_height="400dp"
android:src="@drawable/img"/>
<SeekBar
android:id="@+id/positionBar"
android:layout_marginTop="30dp"
android:layout_width="300dp"
android:layout_height="wrap_content"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/elapsedTimeLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0:11"
android:layout_marginLeft="40dp"/>
<TextView
android:id="@+id/remainingTimeLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0:11"
android:layout_marginLeft="240dp"/>
</LinearLayout>
<Button
android:id="@+id/playBtn"
android:layout_marginTop="40dp"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/ic_play_arrow_black_24dp"
android:onClick="playBtnClick"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="40dp"
android:gravity="center">
<ImageView
android:layout_width="18dp"
android:layout_height="18dp"
android:src="@drawable/ic_volume_down_black_24dp"/>
<SeekBar
android:id="@+id/volumeBar"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:progress="50"
android:max="100"/>
<ImageView
android:layout_width="26dp"
android:layout_height="26dp"
android:src="@drawable/ic_volume_up_black_24dp"/>
</LinearLayout>
</LinearLayout>
Step 5: Play Media
The play/pause button can be used to play or pause the music as follows:
fun playBtnClick(v: View)
{
if (mp.isPlaying)
{
//stop
mp.pause()
playBtn.setBackgroundResource(R.drawable.ic_play_arrow_black_24dp)
}
else
{
//start
mp.start()
playBtn.setBackgroundResource(R.drawable.ic_stop_black_24dp)
}
}
Here's how a timer label is created for the music player:
fun createTimeLable(time: Int): String
{
var timeLabel = ""
var min = time / 100 / 60
var sec = time / 100 % 60
timeLabel = "$min:"
if (sec < 10)
{
timeLabel += "0"
}
else
{
timeLabel += sec
}
return timeLabel
}
Here is how the volume can be adjusted using a custom seekbar:
volumeBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser)
{
var volumeNum = progress / 100.0f
mp.setVolume(volumeNum, volumeNum)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
And here is how we can adjust the music position or seek to a certain period of the music:
positionBar.max = totalTime
positionBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser)
{
mp.seekTo(progress)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
Here's the full code:
MainActivity.kt
import android.annotation.SuppressLint
import android.media.MediaPlayer
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.view.View
import android.widget.SeekBar
import kotlinx.android.synthetic.main.activity_main.*
import java.lang.Exception
class MainActivity : AppCompatActivity() {
private lateinit var mp: MediaPlayer
private var totalTime : Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mp = MediaPlayer.create(this, R.raw.music)
mp.isLooping = true
mp.setVolume(0.5f, 0.5f)
totalTime = mp.duration
// Volume Bar
volumeBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser)
{
var volumeNum = progress / 100.0f
mp.setVolume(volumeNum, volumeNum)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
positionBar.max = totalTime
positionBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser)
{
mp.seekTo(progress)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
Thread(Runnable {
while (mp !=null)
{
try {
var msg = Message()
msg.what = mp.currentPosition
handler.sendMessage(msg)
Thread.sleep(1000)
}
catch (e: InterruptedException)
{
}
}
}).start()
}
@SuppressLint("HandlerLeak")
var handler = object : Handler()
{
override fun handleMessage(msg: Message) {
var currentPostion = msg.what
// Update positionbar
positionBar.progress = currentPostion
// Update labels
var elspedTime = createTimeLable(currentPostion)
elapsedTimeLabel.text = elspedTime
var remainingTime = createTimeLable(totalTime - currentPostion)
remainingTimeLabel.text = "-$remainingTime"
}
}
fun createTimeLable(time: Int): String
{
var timeLabel = ""
var min = time / 100 / 60
var sec = time / 100 % 60
timeLabel = "$min:"
if (sec < 10)
{
timeLabel += "0"
}
else
{
timeLabel += sec
}
return timeLabel
}
fun playBtnClick(v: View)
{
if (mp.isPlaying)
{
//stop
mp.pause()
playBtn.setBackgroundResource(R.drawable.ic_play_arrow_black_24dp)
}
else
{
//start
mp.start()
playBtn.setBackgroundResource(R.drawable.ic_stop_black_24dp)
}
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
3. | Code: Apache 2.0 License |