In this tutorial we will learn how to play MP3 file saved in the application. We will create an app that plays a soothing sound of the forest (or waves, or rain) that plays in the loop. We will also learn how to control the playback.
Showing posts with label MediaPlayer. Show all posts
Showing posts with label MediaPlayer. Show all posts
As an Amazon Associate I earn from qualifying purchases.
Android: MediaPlayer
In this tutorial we will learn how to play MP3 file saved in the application. We will create an app that plays a soothing sound of the forest (or waves, or rain) that plays in the loop. We will also learn how to control the playback.
Step 1: Create a new Module "appNatureSounds"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<?xml version="1.0" encoding="utf-8"?>
package com.chicagoandroid.cit299.naturesounds.appnaturesounds;
package com.chicagoandroid.cit299.naturesounds.appnaturesounds;
public void play(View view) {
class SeekBarListener implements OnSeekBarChangeListener {
public void pause(View view) {
void toast(String text) {
private Runnable SongUpdateThread = new Runnable() {
res/dimens.xml
16dp
16dp
Step 1: Create a new Module "appNatureSounds"
- min API 8
Step 2: Design UI of your player
<RelativeLayout 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"
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/uiSoundTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Song Title"/>
<LinearLayout
android:id="@+id/controlLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentBottom="true">
<ImageButton
android:id="@+id/uiFastForward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="20"
android:layout_marginBottom="14dp"
android:onClick="forward"
android:src="@android:drawable/ic_media_ff"/>
<ImageButton
android:layout_weight="40"
android:id="@+id/uiPlayButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="24dp"
android:onClick="play"
android:src="@android:drawable/ic_media_play"/>
<ImageButton
android:layout_weight="20"
android:id="@+id/uiPausePlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="14dp"
android:onClick="pause"
android:src="@android:drawable/ic_media_pause"/>
<ImageButton
android:layout_weight="20"
android:id="@+id/uiRewind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginLeft="22dp"
android:onClick="rewind"
android:src="@android:drawable/ic_media_rew"/>
</LinearLayout>
<LinearLayout
android:id="@+id/progressLayout"
android:layout_above="@id/controlLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/uiCurrentTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="15"
android:text="@string/zero_time"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<SeekBar
android:id="@+id/uiProgressSeekBar"
android:layout_weight="70"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/uiDuration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:layout_gravity="right"
android:layout_weight="15"
android:text="@string/zero_time"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
<ImageView
android:id="@+id/uiPlayerBackground"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/progressLayout"
android:layout_below="@+id/uiSoundTitle"
android:src="@drawable/bg_rainforest"/>
</RelativeLayout>
Step: Add any language specific text
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Nature Sounds</string>
<string name="action_settings">Settings</string>
<string name="zero_time">0:0</string>
</resources>
Step: Record, or find a SHORT royalty-free MP3 you want to play
Step: create a class that will hold the TIME of the song.
package com.chicagoandroid.cit299.naturesounds.appnaturesounds;
import java.text.SimpleDateFormat;
/**
* Wrapper for time mm:ss
* Created by uki on 11/8/14.
*/
public class PlayTime {
long time;
public PlayTime(long value) {
time = value;
}
public void update(int value) {
time = (long) value;
}
public void add(int value) {
time = time + value;
}
public boolean subtract(int value) {
if (time - value > 0) {
time = time - value;
return true;
}
return false;
}
public PlayTime(int value) {
time = (long) value;
}
public int toInt() {
return (int) time;
}
public String toString() {
SimpleDateFormat ft = new SimpleDateFormat("mm:ss");
return ft.format(time);
}
}
Step: MainActivity.OnCreate()
package com.chicagoandroid.cit299.naturesounds.appnaturesounds;
import android.media.MediaPlayer;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.View;
import android.widget.*;
/** Nature Sounds app */
public class MainActivity extends ActionBarActivity {
private static int FORWARD_TIME = 5000;
private static int REWIND_TIME = 5000;
private static int DELAY_TIME = 100; // update 10 times per second
private TextView soundTitle, currentTimeLabel, durationTimeLabel;
private ImageView backgroundImage;
private MediaPlayer mediaPlayer;
private PlayTime currentTime = new PlayTime(0);
private PlayTime durationTime = new PlayTime(0);
private Handler threadHandler = new Handler();;
private SeekBar progressSeekBar;
private ImageButton playButton, pauseButton;
private boolean userChangingProgress = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
soundTitle = (TextView) findViewById(R.id.uiSoundTitle);
currentTimeLabel = (TextView) findViewById(R.id.uiCurrentTime);
durationTimeLabel = (TextView) findViewById(R.id.uiDuration);
progressSeekBar = (SeekBar) findViewById(R.id.uiProgressSeekBar);
playButton = (ImageButton) findViewById(R.id.uiPlayButton);
pauseButton = (ImageButton) findViewById(R.id.uiPausePlay);
backgroundImage = (ImageView) findViewById(R.id.uiPlayerBackground);
// set UI values to initial state before play
durationTimeLabel.setText(durationTime.toString());
currentTimeLabel.setText(currentTime.toString());
progressSeekBar.setClickable(false);
pauseButton.setEnabled(false);
// this could be loaded from the database
soundTitle.setText("Rain forest");
mediaPlayer = MediaPlayer.create(this, R.raw.sound_001);
backgroundImage.setImageResource(R.drawable.bg_rainforest);
}
Step: play method
public void play(View view) {
//play sound over and over
mediaPlayer.setLooping(true);
mediaPlayer.start();
toast("Playing sound");
durationTime.update(mediaPlayer.getDuration());
currentTime.update(mediaPlayer.getCurrentPosition());
durationTimeLabel.setText(durationTime.toString());
currentTimeLabel.setText(currentTime.toString());
progressSeekBar.setProgress(currentTime.toInt());
progressSeekBar.setMax(durationTime.toInt());
pauseButton.setEnabled(true);
playButton.setEnabled(false);
threadHandler.postDelayed(SongUpdateThread, DELAY_TIME);
progressSeekBar.setOnSeekBarChangeListener(new SeekBarListener());
}
Step: create SeekBarListener
class SeekBarListener implements OnSeekBarChangeListener {
/**
* Notification that the progress level has changed. Clients can use the fromUser parameter
* to distinguish user-initiated changes from those that occurred programmatically.
*
* @param seekBar The SeekBar whose progress has changed
* @param progress The current progress level. This will be in the range 0..max where max
* was set by {@link android.widget.ProgressBar#setMax(int)}. (The default value for max is 100.)
* @param fromUser True if the progress change was initiated by the user.
*/
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
currentTime.update(progress);
mediaPlayer.seekTo(currentTime.toInt());
}
}
/**
* Notification that the user has started a touch gesture. Clients may want to use this
* to disable advancing the seekbar.
*
* @param seekBar The SeekBar in which the touch gesture began
*/
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
userChangingProgress = true;
}
/**
* Notification that the user has finished a touch gesture. Clients may want to use this
* to re-enable advancing the seekbar.
*
* @param seekBar The SeekBar in which the touch gesture began
*/
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
userChangingProgress = false;
}
}
Step: additional control methods
public void pause(View view) {
toast("Pausing sound");
mediaPlayer.pause();
pauseButton.setEnabled(false);
playButton.setEnabled(true);
}
public void forward(View view) {
int temp = currentTime.toInt();
if ((temp + FORWARD_TIME) <= durationTime.toInt()) {
currentTime.add(FORWARD_TIME);
mediaPlayer.seekTo(currentTime.toInt());
}
else {
toast("Cannot jump forward " + FORWARD_TIME / 1000 + " seconds");
}
}
public void rewind(View view) {
if ((currentTime.toInt() - REWIND_TIME) > 0) {
currentTime.subtract(REWIND_TIME);
mediaPlayer.seekTo(currentTime.toInt());
}
else {
toast("Cannot jump backward " + REWIND_TIME / 1000 + " seconds");
}
}
Step: utility methods
void toast(String text) {
Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER | Gravity.CENTER, 0, 0);
toast.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
Step: Song Update Thread
private Runnable SongUpdateThread = new Runnable() {
public void run() {
if (!userChangingProgress) {
currentTime.update(mediaPlayer.getCurrentPosition());
progressSeekBar.setProgress(currentTime.toInt());
}
currentTimeLabel.setText(currentTime.toString());
// call itself
threadHandler.postDelayed(this, DELAY_TIME);
}
};
res/dimens.xml
find similar posts:
Android,
MediaPlayer,
SimpleDateFormat
0
comments
Subscribe to:
Posts (Atom)
apt quotation..
“A man should be able to change a diaper, plan an invasion, butcher a hog, conn a ship, design a building, write a sonnet, balance accounts, build a wall, set a bone, comfort the dying, take orders, give orders, cooperate, act alone, solve equations, analyze a new problem, pitch manure, program a computer, cook a tasty meal, fight efficiently, die gallantly. Specialization is for insects.” by Robert A. Heinlein (author, aeronautical engineer, and naval officer)

