J'ai un lecteur simple et un enregistreur. Tout fonctionne très bien mais j'ai un problème. Je veux ajouter une barre de recherche pour voir les progrès de la lecture d'un disque et utiliser cette barre de recherche pour définir l'emplacement du lecteur que vous souhaitez lire. J'ai un progrès mais sans effet. C'est le code:
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
}
}
Avez-vous des idées sur l'utilisation de la barre de recherche pour voir les progrès et définir le lieu de l'enregistrement?
Pour créer une «connexion» entre SeekBar
et MediaPlayer
, vous devez d’abord obtenir la durée maximale de votre enregistrement actuel et la définir comme barre de recherche.
mSeekBar.setMax(mFileDuration); // where mFileDuration is mMediaPlayer.getDuration();
Après avoir initialisé votre MediaPlayer
et appuyé, par exemple, sur le bouton de lecture, vous devez créer un gestionnaire et une publication exécutable afin de pouvoir mettre à jour votre SeekBar
(dans le UI thread
lui-même) avec la position actuelle de votre MediaPlayer
comme ceci:
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);
}
});
et mettre à jour cette valeur chaque seconde.
Si vous devez mettre à jour la position de la MediaPlayer
pendant que l'utilisateur déplace votre SeekBar
, vous devez ajouter OnSeekBarChangeListener
à votre SeekBar
et le faire ici:
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);
}
}
});
Et ça devrait faire l'affaire! :)
EDIT: Une chose que j'ai remarqué dans votre code, ne faites pas:
public MainActivity() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
}
faites toutes les initialisations dans votre onCreate();
, ne créez pas de constructeur de votre Activity
.
J'ai utilisé ce tutoriel avec succès, c'est vraiment simple à comprendre: www.androidhive.info/2012/03/Android-building-audio-player-tutorial/
C'est la partie intéressante:
/**
* 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();
}
Après avoir initialisé votre MediaPlayer
et votre SeekBar
, vous pouvez procéder comme suit:
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
mSeekBar.setProgress(mMediaPlayer.getCurrentPosition());
}
},0,1000);
Ceci met à jour SeekBar
chaque seconde (1000ms)
Et pour mettre à jour MediaPlayer
, si l'utilisateur fait glisser SeekBar
, vous devez ajouter OnSeekBarChangeListener
à votre 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) {
}
});
CODAGE HEUREUX !!!
cochez cette case, vous devriez donner des arguments en msec, Ne pas envoyer que progress
à seekTo (int)
et aussi vérifier ceci getCurrentPostion () et getDuration () .
Vous pouvez faire des calculs, par exemple, convertir progress
en msec comme msce = (progress/100)*getDuration()
puis faire seekTo(msec)
Sinon, j'ai une idée simple, vous n'avez pas besoin de changer de code, ajoutez simplement seekBar.setMax(mPlayer.getDuration())
une fois que votre lecteur multimédia est prêt.
et voici le lien exactement ce que vous voulez cherchez barre de mise à jour
int pos = 0;
yourSeekBar.setMax(mPlayer.getDuration());
Après avoir démarré votre MediaPlayer
i.e mplayer.start()
while(mPlayer!=null){
try {
Thread.sleep(1000);
pos = mPlayer.getCurrentPosition();
} catch (Exception e) {
//show exception in LogCat
}
yourSeekBar.setProgress(pos);
}
Avant d’ajouter ce code, vous devez créer une ressource xml
pour SeekBar
et l’utiliser dans votre classe Activity
de la méthode ur onCreate()
.
Pour ajouter à la réponse de @ hardartcore.
Au lieu d'appeler postDelayed sur un gestionnaire, la meilleure approche consiste à obtenir des rappels à partir de la variable MediaPlayer
lors de la lecture, puis à mettre à jour la barre de recherche en conséquence.
En outre, mettez votre MediaPlayer
en pause à la onStartTrackingTouch(SeekBar seekBar)
de la OnSeekBarChangeListener
, puis redémarrez-le à la onStopTrackingTouch(SeekBar seekBar)
.
Sur la base des déclarations précédentes, vous pouvez également ajouter une condition if pour de meilleures performances
if (player.isPlaying() {
handler.postDelayed(..., 1000);
}
Cela fonctionne pour moi:
seekbarPlayer.setMax(mp.getDuration());
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if(mp != null){
seekbarPlayer.setProgress(mp.getCurrentPosition());
}
mHandler.postDelayed(this, 1000);
}
});
Code en Kotlin:
var updateSongTime = object : Runnable {
override fun run() {
val getCurrent = mediaPlayer?.currentPosition
startTimeText?.setText(String.format("%d:%d",
TimeUnit.MILLISECONDS.toMinutes(getCurrent?.toLong() as Long),
TimeUnit.MILLISECONDS.toSeconds(getCurrent?.toLong()) -
TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(getCurrent?.toLong()))))
seekBar?.setProgress(getCurrent?.toInt() as Int)
Handler().postDelayed(this, 1000)
}
}
Pour changer le fichier audio du lecteur multimédia toutes les secondes
Si l'utilisateur fait glisser la barre de recherche, l'extrait de code suivant peut être utilisé.
Statified.seekBar?.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
if(b && Statified.mediaPlayer != null){
Statified.mediaPlayer?.seekTo(i)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {}
})
Essayez ce code:
public class MainActivity extends AppCompatActivity {
MediaPlayer mplayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//You create MediaPlayer variable ==> set the path and start the audio.
mplayer = MediaPlayer.create(this, R.raw.example);
mplayer.start();
//Find the seek bar by Id (which you have to create in layout)
// Set seekBar max with length of audio
// You need a Timer variable to set progress with position of audio
final SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar);
seekBar.setMax(mplayer.getDuration());
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
seekBar.setProgress(mplayer.getCurrentPosition());
}
}, 0, 1000);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// Update the progress depending on seek bar
mplayer.seekTo(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
Le code ci-dessous a fonctionné pour moi.
J'ai créé une méthode pour seekbar
@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 et SongMaxLength sont les propriétés TextView pour afficher la durée et la durée du morceau.