This exercise modify from last exercise "Play 'audio/mp3' with MediaPlayer", to monitor and display the playing time on SeekBar and TextView.
We implement a ScheduledExecutorService (myScheduledExecutorService), it repeat running in 200ms. When time reached, it send a message to trigger handleMessage() method of monitorHandler, then update the SeekBar and TextView for playing time.
Please notice that we cannot update UI elements (SeekBar and TextView) in myScheduledExecutorService directly. Because it's run in non-UI thread. That's why we have to use Message-Handler.
AndroidPlayerActivity.java
package com.exercise.AndroidPlayer;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnErrorListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
public class AndroidPlayerActivity extends Activity {
TextView info, state;
Button buttonOpen;
Button buttonPlay, buttonPause, buttonStop;
SeekBar timeLine;
LinearLayout timeFrame;
TextView timePos, timeDur;
final static int RQS_OPEN_AUDIO_MP3 = 1;
MediaPlayer mediaPlayer;
String srcPath = null;
enum MP_State {
Idle, Initialized, Prepared, Started, Paused,
Stopped, PlaybackCompleted, End, Error, Preparing}
MP_State mediaPlayerState;
//ScheduledExecutorService myScheduledExecutorService;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonOpen = (Button)findViewById(R.id.open);
buttonOpen.setOnClickListener(buttonOpenOnClickListener);
info = (TextView)findViewById(R.id.info);
state = (TextView)findViewById(R.id.state);
buttonPlay = (Button)findViewById(R.id.play);
buttonPlay.setOnClickListener(buttonPlayOnClickListener);
buttonPause = (Button)findViewById(R.id.pause);
buttonPause.setOnClickListener(buttonPauseOnClickListener);
buttonStop = (Button)findViewById(R.id.stop);
buttonStop.setOnClickListener(buttonStopOnClickListener);
//
timeLine = (SeekBar)findViewById(R.id.seekbartimeline);
timeFrame = (LinearLayout)findViewById(R.id.timeframe);
timePos = (TextView)findViewById(R.id.pos);
timeDur = (TextView)findViewById(R.id.dur);
ScheduledExecutorService myScheduledExecutorService = Executors.newScheduledThreadPool(1);
myScheduledExecutorService.scheduleWithFixedDelay(
new Runnable(){
@Override
public void run() {
monitorHandler.sendMessage(monitorHandler.obtainMessage());
}},
200, //initialDelay
200, //delay
TimeUnit.MILLISECONDS);
}
Handler monitorHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
mediaPlayerMonitor();
}
};
private void mediaPlayerMonitor(){
if (mediaPlayer == null){
timeLine.setVisibility(View.INVISIBLE);
timeFrame.setVisibility(View.INVISIBLE);
}else{
if(mediaPlayer.isPlaying()){
timeLine.setVisibility(View.VISIBLE);
timeFrame.setVisibility(View.VISIBLE);
int mediaDuration = mediaPlayer.getDuration();
int mediaPosition = mediaPlayer.getCurrentPosition();
timeLine.setMax(mediaDuration);
timeLine.setProgress(mediaPosition);
timePos.setText(String.valueOf((float)mediaPosition/1000) + "s");
timeDur.setText(String.valueOf((float)mediaDuration/1000) + "s");
}else{
timeLine.setVisibility(View.INVISIBLE);
timeFrame.setVisibility(View.INVISIBLE);
}
}
}
OnErrorListener mediaPlayerOnErrorListener
= new OnErrorListener(){
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
mediaPlayerState = MP_State.Error;
showMediaPlayerState();
return false;
}};
private void cmdReset(){
if (mediaPlayer == null){
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnErrorListener(mediaPlayerOnErrorListener);
}
mediaPlayer.reset();
mediaPlayerState = MP_State.Idle;
showMediaPlayerState();
}
private void cmdSetDataSource(String path){
if(mediaPlayerState == MP_State.Idle){
try {
mediaPlayer.setDataSource(path);
mediaPlayerState = MP_State.Initialized;
} catch (IllegalArgumentException e) {
Toast.makeText(AndroidPlayerActivity.this,
e.toString(), Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IllegalStateException e) {
Toast.makeText(AndroidPlayerActivity.this,
e.toString(), Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IOException e) {
Toast.makeText(AndroidPlayerActivity.this,
e.toString(), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}else{
Toast.makeText(AndroidPlayerActivity.this,
"Invalid State@cmdSetDataSource - skip",
Toast.LENGTH_LONG).show();
}
showMediaPlayerState();
}
private void cmdPrepare(){
if(mediaPlayerState == MP_State.Initialized
||mediaPlayerState == MP_State.Stopped){
try {
mediaPlayer.prepare();
mediaPlayerState = MP_State.Prepared;
} catch (IllegalStateException e) {
Toast.makeText(AndroidPlayerActivity.this,
e.toString(), Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IOException e) {
Toast.makeText(AndroidPlayerActivity.this,
e.toString(), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}else{
Toast.makeText(AndroidPlayerActivity.this,
"Invalid State@cmdPrepare() - skip",
Toast.LENGTH_LONG).show();
}
showMediaPlayerState();
}
private void cmdStart(){
if(mediaPlayerState == MP_State.Prepared
||mediaPlayerState == MP_State.Started
||mediaPlayerState == MP_State.Paused
||mediaPlayerState == MP_State.PlaybackCompleted){
mediaPlayer.start();
mediaPlayerState = MP_State.Started;
}else{
Toast.makeText(AndroidPlayerActivity.this,
"Invalid State@cmdStart() - skip",
Toast.LENGTH_LONG).show();
}
showMediaPlayerState();
}
private void cmdPause(){
if(mediaPlayerState == MP_State.Started
||mediaPlayerState == MP_State.Paused){
mediaPlayer.pause();
mediaPlayerState = MP_State.Paused;
}else{
Toast.makeText(AndroidPlayerActivity.this,
"Invalid State@cmdPause() - skip",
Toast.LENGTH_LONG).show();
}
showMediaPlayerState();
}
private void cmdStop(){
if(mediaPlayerState == MP_State.Prepared
||mediaPlayerState == MP_State.Started
||mediaPlayerState == MP_State.Stopped
||mediaPlayerState == MP_State.Paused
||mediaPlayerState == MP_State.PlaybackCompleted){
mediaPlayer.stop();
mediaPlayerState = MP_State.Stopped;
}else{
Toast.makeText(AndroidPlayerActivity.this,
"Invalid State@cmdStop() - skip",
Toast.LENGTH_LONG).show();
}
showMediaPlayerState();
}
private void showMediaPlayerState(){
switch(mediaPlayerState){
case Idle:
state.setText("Idle");
break;
case Initialized:
state.setText("Initialized");
break;
case Prepared:
state.setText("Prepared");
break;
case Started:
state.setText("Started");
break;
case Paused:
state.setText("Paused");
break;
case Stopped:
state.setText("Stopped");
break;
case PlaybackCompleted:
state.setText("PlaybackCompleted");
break;
case End:
state.setText("End");
break;
case Error:
state.setText("Error");
break;
case Preparing:
state.setText("Preparing");
break;
default:
state.setText("Unknown!");
}
}
OnClickListener buttonPlayOnClickListener
= new OnClickListener(){
@Override
public void onClick(View v) {
if(srcPath == null){
Toast.makeText(AndroidPlayerActivity.this,
"No file selected",
Toast.LENGTH_LONG).show();
}else{
cmdPrepare();
cmdStart();
}
}
};
OnClickListener buttonPauseOnClickListener
= new OnClickListener(){
@Override
public void onClick(View v) {
cmdPause();
}
};
OnClickListener buttonStopOnClickListener
= new OnClickListener(){
@Override
public void onClick(View v) {
cmdStop();
}
};
OnClickListener buttonOpenOnClickListener
= new OnClickListener(){
@Override
public void onClick(View arg0) {
Intent intent = new Intent();
intent.setType("audio/mp3");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(
intent, "Open Audio (mp3) file"), RQS_OPEN_AUDIO_MP3);
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == RQS_OPEN_AUDIO_MP3) {
Uri audioFileUri = data.getData();
srcPath = audioFileUri.getPath();
info.setText(srcPath);
cmdReset();
cmdSetDataSource(srcPath);
}
}
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<Button
android:id="@+id/open"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Open MP3 file" />
<TextView
android:id="@+id/info"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/play"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Play" />
<Button
android:id="@+id/pause"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Pause" />
<Button
android:id="@+id/stop"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Stop" />
<TextView
android:id="@+id/state"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<SeekBar
android:id="@+id/seekbartimeline"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="invisible"/>
<LinearLayout
android:id="@+id/timeframe"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="invisible">
<TextView
android:id="@+id/pos"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/dur"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"/>
</LinearLayout>
</LinearLayout>
Download the files.
Next:
- Seek to specified time position with MediaPlayer - seekTo()
No comments:
Post a Comment