SeekBar和Android中的媒体播放器

我有一个简单的播放器和录音机。 一切正常,但有一个问题。 我想添加search栏来查看播放logging的进度,并使用这个search栏从播放器设置的位置应该播放。 我有进步,但没有效果。 这是代码:

package com.example.recorder; import java.io.IOException; import android.app.Activity; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; public class MainActivity extends Activity implements OnSeekBarChangeListener { private static final String LOG_TAG = "AudioRecordTest"; private static String mFileName = null; private SeekBar seekBar; private MediaRecorder mRecorder = null; private Button startRecord, startPlaying, stopPlaying; private MediaPlayer mPlayer = null; private void onRecord(boolean start) { if (start) { startRecording(); } else { stopRecording(); } } private void startPlaying() { if(mPlayer != null && mPlayer.isPlaying()){ mPlayer.pause(); } else if(mPlayer != null){ mPlayer.start(); }else{ mPlayer = new MediaPlayer(); try { mPlayer.setDataSource(mFileName); mPlayer.prepare(); mPlayer.start(); } catch (IOException e) { Log.e(LOG_TAG, "prepare() failed"); } } } private void stopPlaying() { mPlayer.release(); mPlayer = null; startPlaying.setText("Start playing"); } private void pausePlaying(){ if(mPlayer.isPlaying()){ mPlayer.pause(); } else { mPlayer.start(); } } private void startRecording() { mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mRecorder.setOutputFile(mFileName); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); try { mRecorder.prepare(); } catch (IOException e) { Log.e(LOG_TAG, "prepare() failed"); } mRecorder.start(); } private void stopRecording() { mRecorder.stop(); mRecorder.release(); mRecorder = null; } public MainActivity() { mFileName = Environment.getExternalStorageDirectory().getAbsolutePath(); mFileName += "/audiorecordtest.3gp"; } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.activity_main); startPlaying = (Button) findViewById(R.id.buttonStartPlay); stopPlaying = (Button) findViewById(R.id.buttonStopPlaying); startRecord = (Button) findViewById(R.id.buttonStartRecord); seekBar = (SeekBar) findViewById(R.id.seekBar); startRecord.setOnClickListener(new OnClickListener() { boolean mStartRecording = true; @Override public void onClick(View v) { onRecord(mStartRecording); if (mStartRecording) { startRecord.setText("Stop recording"); } else { startRecord.setText("Start recording"); } mStartRecording = !mStartRecording; } }); startPlaying.setOnClickListener(new OnClickListener() { boolean mStartPlaying = true; @Override public void onClick(View v) { //onPlay(mStartPlaying); startPlaying(); if (mStartPlaying) { startPlaying.setText("Stop playing"); } else { startPlaying.setText("Start playing"); } mStartPlaying = !mStartPlaying; } }); stopPlaying.setOnClickListener(new OnClickListener() { boolean mStartPlaying = true; @Override public void onClick(View v) { stopPlaying(); } }); } @Override public void onPause() { super.onPause(); if (mRecorder != null) { mRecorder.release(); mRecorder = null; } if (mPlayer != null) { mPlayer.release(); mPlayer = null; } } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if(fromUser){ mPlayer.seekTo(progress); seekBar.setProgress(progress); } else{ // the event was fired from code and you shouldn't call player.seekTo() } } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } } 

任何想法如何利用寻求进步和创造logging应该发挥?

Solutions Collecting From Web of "SeekBar和Android中的媒体播放器"

要在SeekBarMediaPlayer之间创build“连接”,您需要首先获取当前的录制最大持续时间,并将其设置为您的search栏。

 mSeekBar.setMax(mFileDuration); // where mFileDuration is mMediaPlayer.getDuration(); 

在初始化MediaPlayer之后,例如按下playbutton,您应该创build处理程序并发布runnable,以便您可以使用MediaPlayer的当前位置更新您的SeekBar (在UI thread本身中),如下所示:

 private Handler mHandler = new Handler(); //Make sure you update Seekbar on UI thread MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { if(mMediaPlayer != null){ int mCurrentPosition = mMediaPlayer.getCurrentPosition() / 1000; mSeekBar.setProgress(mCurrentPosition); } mHandler.postDelayed(this, 1000); } }); 

并且每秒更新一次这个值。

如果您需要在用户拖动SeekBar时更新MediaPlayer的位置,则应将OnSeekBarChangeListener添加到您的SeekBar并在此处执行:

  mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if(mMediaPlayer != null && fromUser){ mMediaPlayer.seekTo(progress * 1000); } } }); 

而这应该做的伎俩! :)

编辑:我已经注意到你的代码中的一件事,不要这样做:

 public MainActivity() { mFileName = Environment.getExternalStorageDirectory().getAbsolutePath(); mFileName += "/audiorecordtest.3gp"; } 

在你的onCreate();进行所有的初始化onCreate(); ,不要创build你的Activity构造函数。

我已经成功地使用了这个教程,这很容易理解: http://www.androidhive.info 2012/03/android-building-audio-player- tutorial/

这是一个有趣的部分:

 /** * Update timer on seekbar * */ public void updateProgressBar() { mHandler.postDelayed(mUpdateTimeTask, 100); } /** * Background Runnable thread * */ private Runnable mUpdateTimeTask = new Runnable() { public void run() { long totalDuration = mp.getDuration(); long currentDuration = mp.getCurrentPosition(); // Displaying Total Duration time songTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDuration)); // Displaying time completed playing songCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(currentDuration)); // Updating progress bar int progress = (int)(utils.getProgressPercentage(currentDuration, totalDuration)); //Log.d("Progress", ""+progress); songProgressBar.setProgress(progress); // Running this thread after 100 milliseconds mHandler.postDelayed(this, 100); } }; /** * * */ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { } /** * When user starts moving the progress handler * */ @Override public void onStartTrackingTouch(SeekBar seekBar) { // remove message Handler from updating progress bar mHandler.removeCallbacks(mUpdateTimeTask); } /** * When user stops moving the progress hanlder * */ @Override public void onStopTrackingTouch(SeekBar seekBar) { mHandler.removeCallbacks(mUpdateTimeTask); int totalDuration = mp.getDuration(); int currentPosition = utils.progressToTimer(seekBar.getProgress(), totalDuration); // forward or backward to certain seconds mp.seekTo(currentPosition); // update timer progress again updateProgressBar(); } 

初始化MediaPlayerSeekBar ,可以这样做:

  Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { mSeekBar.setProgress(mMediaPlayer.getCurrentPosition()); } },0,1000); 

每秒更新一次SeekBar (1000ms)

而对于更新MediaPlayer ,如果用户拖动SeekBar ,则必须将OnSeekBarChangeListener添加到您的SeekBar

 mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { mMediaPlayer.seekTo(i); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); 

快乐的编码!

检查这个,你应该给msecs的参数,不要只发送progress seekTo(int)

并检查此getCurrentPostion()和getDuration() 。

你可以做一些计算,也就是说,以毫秒为msce = (progress/100)*getDuration()转换progress ,如msce = (progress/100)*getDuration()然后执行seekTo(msec)

否则,我有一个简单的想法,你不需要更改任何其他代码,只需添加seekBar.setMax(mPlayer.getDuration())一旦你的媒体播放器准备好了。

这里是链接正是你想要的栏更新

  int pos = 0; yourSeekBar.setMax(mPlayer.getDuration()); 

启动MediaPlayermplayer.start()

试试这个代码

 while(mPlayer!=null){ try { Thread.sleep(1000); pos = mPlayer.getCurrentPosition(); } catch (Exception e) { //show exception in LogCat } yourSeekBar.setProgress(pos); } 

在添加此代码之前,您必须为SeekBar创buildxml资源,并在您的Activity类的ur onCreate()方法中使用它。

添加到@ hardartcore的答案。

  1. 而不是调用Handler上的postDelayed,最好的方法是在回放过程中从MediaPlayer获取callback,然后根据进度更新seekBar。

  2. 另外,在onStartTrackingTouch(SeekBar seekBar)上暂停MediaPlayer ,然后在onStopTrackingTouch(SeekBar seekBar)上重新启动它。

根据之前的陈述,为了获得更好的性能,还可以添加if条件

 if (player.isPlaying() { handler.postDelayed(..., 1000); } 

下面的代码为我工作。

我为seekbar创build了一个方法

 @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) { } }); } 

SongProgress和SongMaxLength是TextView显示歌曲持续时间和歌曲长度。

这适用于我:

 seekbarPlayer.setMax(mp.getDuration()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { if(mp != null){ seekbarPlayer.setProgress(mp.getCurrentPosition()); } mHandler.postDelayed(this, 1000); } });