How do i play my audio files in sequence from my sdcard? I have two classes, one for results another for the actual rendering. Is my while loop in the correct place?
public void DoIt() {
while(!mp.isPlaying()){
AudioRenderer mr = new AudioRenderer();
mp = mr.AudioRenderer(filePath);
if(mp!=null){
mp.start();
if(!mp.isPlaying())
break;
}
}
if(mp == null){ *write results logic*}
private class AudioRenderer extends Activity {
private MediaPlayer AudioRenderer(String filePath) {
MediaPlayer mp = new MediaPlayer();
File location = new File(filePath);
Uri path = Uri.fromFile(location);
ExtentionSeperator media = new ExtentionSeperator(filePath, '.');
if(ext.equals("mp3") || ext.equals("wav")|| ext.equals("ogg")|| ext.equals("mid")||
ext.equals("flac")){
mp= MediaPlayer.create(this, path);}
return mp;}
My app just keeps writing the results without waiting for the first one to stop playing first. I want it to Render -> Play -> Wait for whole audio to stop playing -> Write result into file -> Next file.
if you want them to play one after the other
there is an event in mediaplayer
mp.setOnCompletionListener()
which will fire once the first file is complete. here you can play the next file.
try this code
class MediaDemo extends Activity{
public static MediaPlayer myplayer=new MediaPlayer();
public static ArrayList<String> pathlist=new ArrayList<String>();
public void onCreate(Bundle savedInstanceState){
myplayer.reset();
myplayer.setOnCompletionListener(new OnCompletionListener(){
public void onCompletion(MediaPlayer arg0) {
pathlist.remove(0);
if(pathlist.size()>=1){
myplayer.reset();
playAudio();
}
}
});
pathlist.add("filename");
if(!myplayer.isPlaying()){
playAudio();
}
}
public void playAudio(){
try{
if(pathlist.size()>=1){
String path=pathlist.get(0);
myplayer.setDataSource(path);
myplayer.prepare();
myplayer.start();
}
}catch(Exception e){e.printStackTrace();}
}
}
according to your code you have to use the mp.setOnCompletionListener(). In this give path for the next file which you want to play.
Related
I am making a chat application and I have implemented the feature for sending audio messages.But here I find one thing which I don't want it to happen.It is that whenever my adapter gets updated,The media player starts loading again. In this way there will be an issue for if someone is listening to an audio and the user at other end sends a message ,the media player stops and it loads again.Here is the code of my adapter.
final MediaPlayer mediaPlayer;
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
handler = new Handler();
try {
mediaPlayer.setOnCompletionListener(mediaPlayer1 -> {
mediaPlayer1.stop();
binding.audioSeekbar.setProgress(0);
});
if (mediaPlayer.isPlaying()){
mediaPlayer.stop();
mediaPlayer.release();
}
mediaPlayer.setDataSource(finalUrlToLoad[1]);
mediaPlayer.setVolume(1f, 1f);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(mediaPlayer1 -> {
int totalDuration = mediaPlayer1.getDuration();
binding.totalDurationAudio.setText(createTimeLabel(totalDuration));
binding.loadingAudio.setVisibility(GONE);
binding.playPauseAudio.setVisibility(VISIBLE);
});
} catch (IOException e) {e.printStackTrace();}
binding.playPauseAudio.setOnClickListener(view -> {
if (mediaPlayer.isPlaying()){
handler.removeCallbacks(runnable);
mediaPlayer.pause();
binding.playPauseAudio.setImageResource(R.drawable.pause_to_play);
Drawable drawable = binding.playPauseAudio.getDrawable();
if( drawable instanceof AnimatedVectorDrawable) {
AnimatedVectorDrawable animation = (AnimatedVectorDrawable) drawable;
animation.start();
}
}else {
mediaPlayer.seekTo(binding.audioSeekbar.getProgress());
mediaPlayer.start();
handler.post(runnable);
binding.playPauseAudio.setImageResource(R.drawable.play_to_pause);
Drawable drawable = binding.playPauseAudio.getDrawable();
if( drawable instanceof AnimatedVectorDrawable) {
AnimatedVectorDrawable animation = (AnimatedVectorDrawable) drawable;
animation.start();
}
}
});
runnable = () -> {
int totalTime = mediaPlayer.getDuration();
binding.audioSeekbar.setMax(totalTime);
int currentPosition = mediaPlayer.getCurrentPosition();
binding.audioSeekbar.setProgress(currentPosition);
binding.totalDurationAudio.setText(createTimeLabel(totalTime));
Log.d("time", String.valueOf(currentPosition));
handler.postDelayed(runnable,1000);
};
binding.audioSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (b){
mediaPlayer.seekTo(i);
seekBar.setProgress(i);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mediaPlayer.setOnBufferingUpdateListener((mediaPlayer1, i) -> binding.audioSeekbar.setSecondaryProgress(i));
Here finalurltoload[1] is the url for the audio.
Now what do I need to do in order to prevent loading it again and again.
I will be really grateful to who answer this question.
Thanks😊.
It's hard to tell from this code but I assume this is all set in your onBind event? If so, then this means every time RecyclerView creates a new holder and binds it, the associated media will be prepped and loaded, and whichever is the 'last holder to have been called with onBind, "wins" (and is what MediaPlayer will be loaded with). Since by default RecyclerView typically creates multiple holders up front, you are seeing your MediaPlayer being "loaded" multiple times.
You probably just don't want to do the initialization of each audio message in the onBind. Instead, just use the onBind event to initialize state variables (duration, progress, etc.) to some default value, hide them and bind the specific audio Uri. Then when the user takes some action like tapping on the holder, you unhide an indeterminate progress bar while the initialization takes place, and in the onPrepared() event unhide the state information (duration, progress, seekbar, etc.), and finally hide the indeterminate progress bar and start the audio.
I assume you are also sending over the sound file as part of your messaging app (i.e. not storing it on the web somewhere in a central location?), and this file gets stored in an app-specific storage location? If so, you don't need to worry about persisting the permission to that URI, but if that isn't the case you will.
First extract the media player code into singleton class like AudioManager.
Add few method like setMediaUpdateListener that set a callback for seek duration. and togglePlayPause to play or pause the audio.
Passed the message id or any unique identifier to the audio manager while playing the video.
In Adapter class onBind Method.
First Compare the id and playing Id is same like AudioManager.getInstance().isPlaying(messageId);
If yes then set the seekUpdatelistner to the audio manager class.
also update the play/pause icon based on AudioManager.isPlaying() method.
3.if user play other message by clicking play button. call AudioManager.play(message) method.In which we release the previous message and play the new one.
If current message is not playing then reset the view on non-playing state.
If Auto play is enabled then you need to check if audioManager is free then only you can play the last message otherwise ignored.
Like a class who are managing the audio for you and store all the state.
class AudioManager {
public static AudioManager instance;
final MediaPlayer mediaPlayer;
private AudioListener audioListener;
private Uri currentPlaying;
public AudioManager getInstance() {
if (instance == null) {
instance = new AudioManager();
}
}
public void play(Uri dataUri) {
if (mediaPlayer != null && currentPlaying == null || currentPlaying.equals(dataUri)) {
if (!mediaPlayer.isPlaying) {
mediaPlayer.play();
}
return;
} else if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
}
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
handler = new Handler();
try {
mediaPlayer.setOnCompletionListener(mediaPlayer1 -> {
mediaPlayer1.stop();
sendProgress(0);
});
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
mediaPlayer.setDataSource(dataUri;
mediaPlayer.setVolume(1f, 1f);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(mediaPlayer1 -> {
int totalDuration = mediaPlayer1.getDuration();
sendTotalDuration(totalDuration);
});
} catch (IOException e) {
e.printStackTrace();
}
}
public void pause() {
// update the pause code.
}
public void sendProgress(int progress) {
if (audioListener != null) {
audioListener.onProgress(progress);
}
}
public void sendTotalDuration(int duration) {
if (audioListener != null) {
audioListener.onTotalDuraration(duration);
}
}
public void AudioListener(AudioListener audioListener) {
this.audioListener = audioListener;
}
public interface AudioListener {
void onProgress(int progress);
void onTotalDuraration(int duration);
void onAudioPlayed();
void onAudioPaused():
}
}
I am very new to android just started with Android currently referring the below code from past 2 days, not able to fix the issue.
Code:
https://github.com/quocnguyenvan/media-player-demo
Issue: Let's say we 4 Songs in the ListView when we click on the first song play it for some time and pause it without clicking on stop.
As soon as we click on the second song the first song starts playing we cannot play the second song unless we click on stop of the first song How to solve this issue.
The issue with code not able to figure out and fix it.I have referred many posts before posting on StackOverflow but could not make it, any suggestion or guidance is highly appreciated.
Problematic code:
// play music
viewHolder.ivPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(flag){
mediaPlayer = MediaPlayer.create(context, music.getSong());
flag = false;
}
if(mediaPlayer.isPlaying()) {
mediaPlayer.pause();
viewHolder.ivPlay.setImageResource(R.drawable.ic_play);
} else {
mediaPlayer.start();
viewHolder.ivPlay.setImageResource(R.drawable.ic_pause);
}
}
});
// stop
viewHolder.ivStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!flag) {
mediaPlayer.stop();
mediaPlayer.release();
flag = true;
}
viewHolder.ivPlay.setImageResource(R.drawable.ic_play);
}
});
These are the steps I used for playing song you can try to sync with my steps to resolve the error.
private void initMembers() {
//initialize the members here
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//media prepare
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mediaPlayer) {
//media player prepared
togglePlayPausePlayer();
}
});
//media completion
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(final MediaPlayer mediaPlayer) {
//handle the media play completion
handleOnCompletionLogic();
}
});
}
after that whenever I try to play the song. I call this method.
public void playMusic(final MusicModel musicModel) {
//here play the music with data in below
try {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
}
mMediaPlayer.reset();
mMediaPlayer.setDataSource(musicModel.getUrl());
mMediaPlayer.prepareAsync();
} catch (IOException | IllegalStateException exp) {
exp.printStackTrace();
showMessage(getString(R.string.error_unable_play));
}
}
above resets the playing song and prepare the player for another song.
and OnPreparedListener it calls the togglePlayPausePlayer() which play and pause the song accordingly.
private void togglePlayPausePlayer() {
//here handle the logic for play and pause the player
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
setPlayAndPause(false);
} else {
mMediaPlayer.start();
setPlayAndPause(true);
}
}
The key is we initialize the player and set an onPrepareListener for the media player to get prepared and then play the song, which will check if it's playing then it will stop and else it will play.
hope this may help you.
For on click on ListView you need to reset the media player, change the data source and start playing with new song.
mp.reset();
mp.setDataSource("song you selected from ListView");
mp.prepare();
mp.start();
When I click on any song from playlist first time it plays next song, this problem has only happened for the first time on second or more click on any song from the playlist it working fine.
But the major problem has, it unable to play next song after the end of any song anytime.
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.reset();
// play next song
if(listView_click_arg2 < (songPath.length - 1)){
listView_click_arg2=listView_click_arg2+1;
}
else{
// play first song
listView_click_arg2=0;
}
try {
playSong(songPath[listView_click_arg2]);
} catch (IOException e) {
e.printStackTrace();
}
}
});
private void playSong(String path) throws IllegalArgumentException, IllegalStateException, IOException {
startTime=0;
finalTime=0;
oneTimeOnly=0;
mediaPlayer.stop();
mediaPlayer=null;
mediaPlayer=new MediaPlayer();
mediaPlayer.setDataSource(path);
mediaPlayer.prepare();
mediaPlayer.start();
}
I found you have a problem because of mediaPlayer.reset() function. It says
When a MediaPlayer object is just created using new or after reset() is called, it is in the Idle state; and after release() is called, it is in the End state. Between these two states is the life cycle of the MediaPlayer object.
Please go through this link. There is a nice Flow chart:
https://developer.android.com/reference/android/media/MediaPlayer.html
I belive, after you remove mediaPlayer.reset() inside the onCompletionListener body, it will get solved.
Try adding release(). It looks like a out of memory issue.
private void playSong(String path) throws IllegalArgumentException, IllegalStateException, IOException {
startTime=0;
finalTime=0;
oneTimeOnly=0;
// changing the state of mediaPlayer inside its own callback is a bad practice.
//mediaPlayer.stop();
mediaPlayer.release(); // <<------ Add this before reference is gone.
mediaPlayer=null;
mediaPlayer=new MediaPlayer();
mediaPlayer.setDataSource(path);
mediaPlayer.prepare();
mediaPlayer.start();
}
Lets pretend that a 5 videos in sdcard or internal storage.
now I already get the file path, my problem is how can i insert a multiple videos in VIDEO VIEW ?
The next or previous button is not functioning
here is my code
public void getFile()
{
urls = getIntent().getStringArrayListExtra("url_videoAll");
keys = getIntent().getStringArrayListExtra("key_videoAll");
for(int i = 0; i<urls.size();i++) {
String FileName = URLUtil.guessFileName(urls.get(0), null, MimeTypeMap.getFileExtensionFromUrl(urls.get(0)));
String yourFilePath = getBaseContext().getFilesDir() + "/" + FileName;
fileList.add(new File(yourFilePath));
}
playallvideo(fileList);
}
in this CODE ARE WORKING IN SINGLE VIDEO how about if i have 5 videos ?
private void playallvideo(final List<File> file)
{
mediaController = new MediaController(this);
video.setMediaController(mediaController);
video.setVideoPath(file.get(0).toString());
video.start();
mediaController.setPrevNextListeners(new View.OnClickListener() {
public void onClick(View v) {
video.setMediaController(mediaController);
video.setVideoPath(file.get(1).toString());
video.requestFocus();
video.start();
// code for next
}
}, new View.OnClickListener() {
public void onClick(View v) {
video.setMediaController(mediaController);
video.setVideoPath(file.get(1).toString());
video.requestFocus();
video.start();
// code for previous
}
});
}
I need this because I will use MediaController and press the next video
You can use a counter and increment the value of it as soon as the first video has stopped playing. This can be achieved by using the MediaPlayer.OnCompletionListener.
Below worked for me:
private static int currentVideo = 0;
private List<String> fileData = new ArrayList<String>();
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
if(!(currentPosition < fileData.size())) {
return;
}
Uri nextUri = Uri.parse(fileData.get(currentPosition++));
videoView.setVideoURI(nextUri);
videoView.start();
//to keep looping into the list, reset the counter to 0.
//in case you need to stop playing after the list is completed remove the code.
if(currentPosition == fileData.size()) {
currentPosition = 0;
}
}
});
Though the post is too old to answer, the beginner developers who end up here will get as much help as I did.
Could someone show me or teach me how I can download 5 or more mp3 in a file and playing them in my app. I've searched about it but all of people how has asked this, nothing explained it well. I don't want to download only one mp3, but multiple mp3s in a file.here is main.java
public class StreamingMp3Player extends Activity implements OnClickListener, OnTouchListener, OnCompletionListener, OnBufferingUpdateListener{
private ImageButton buttonPlayPause;
private SeekBar seekBarProgress;
public EditText editTextSongURL;
private MediaPlayer mediaPlayer;
private int mediaFileLengthInMilliseconds; // this value contains the song duration in milliseconds. Look at getDuration() method in MediaPlayer class
private final Handler handler = new Handler();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initView();
}
/** This method initialise all the views in project*/
private void initView() {
buttonPlayPause = (ImageButton)findViewById(R.id.ButtonTestPlayPause);
buttonPlayPause.setOnClickListener(this);
seekBarProgress = (SeekBar)findViewById(R.id.SeekBarTestPlay);
seekBarProgress.setMax(99); // It means 100% .0-99
seekBarProgress.setOnTouchListener(this);
editTextSongURL = (EditText)findViewById(R.id.EditTextSongURL);
editTextSongURL.setText(R.string.testsong_20_sec);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
}
/** Method which updates the SeekBar primary progress by current song playing position*/
private void primarySeekBarProgressUpdater() {
seekBarProgress.setProgress((int)(((float)mediaPlayer.getCurrentPosition()/mediaFileLengthInMilliseconds)*100)); // This math construction give a percentage of "was playing"/"song length"
if (mediaPlayer.isPlaying()) {
Runnable notification = new Runnable() {
public void run() {
primarySeekBarProgressUpdater();
}
};
handler.postDelayed(notification,1000);
}
}
#Override
public void onClick(View v) {
if(v.getId() == R.id.ButtonTestPlayPause){
/** ImageButton onClick event handler. Method which start/pause mediaplayer playing */
try {
mediaPlayer.setDataSource(editTextSongURL.getText().toString()); // setup song from http://www.hrupin.com/wp-content/uploads/mp3/testsong_20_sec.mp3 URL to mediaplayer data source
mediaPlayer.prepare(); // you must call this method after setup the datasource in setDataSource method. After calling prepare() the instance of MediaPlayer starts load data from URL to internal buffer.
} catch (Exception e) {
e.printStackTrace();
}
mediaFileLengthInMilliseconds = mediaPlayer.getDuration(); // gets the song length in milliseconds from URL
if(!mediaPlayer.isPlaying()){
mediaPlayer.start();
buttonPlayPause.setImageResource(R.drawable.button_pause);
}else {
mediaPlayer.pause();
buttonPlayPause.setImageResource(R.drawable.button_play);
}
primarySeekBarProgressUpdater();
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if(v.getId() == R.id.SeekBarTestPlay){
/** Seekbar onTouch event handler. Method which seeks MediaPlayer to seekBar primary progress position*/
if(mediaPlayer.isPlaying()){
SeekBar sb = (SeekBar)v;
int playPositionInMillisecconds = (mediaFileLengthInMilliseconds / 100) * sb.getProgress();
mediaPlayer.seekTo(playPositionInMillisecconds);
}
}
return false;
}
#Override
public void onCompletion(MediaPlayer mp) {
/** MediaPlayer onCompletion event handler. Method which calls then song playing is complete*/
buttonPlayPause.setImageResource(R.drawable.button_play);
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
/** Method which updates the SeekBar secondary progress by current song loading from URL position*/
seekBarProgress.setSecondaryProgress(percent);
}
You'll need to use 3rd party libraries to support MP3 playback, as it is not included in the standard library. See Wikipedia for a list of alternatives.
For the downloading part, use an URLConnection to get an InputStream on the file and write it to a FileOutputStream. This might help, too: Working unbuffered Streams