This question already has answers here:
Media Player start stop start
(8 answers)
Closed 6 years ago.
I have a button when clicked it plays an audio, and while it is playing I can pause it and replay it again and so forth. I have a shake event, where I want to play the audio on shake and replay it when device is shaken again (by first stopping the audio, calling stopAudio?)
I have the following code:
llBtn = (LinearLayout) findViewById(R.id.button);
llBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(MainActivity.this, "LL WAS CLICKED", Toast.LENGTH_SHORT).show();
//IF AUDIO IS NOT PLAYING... PLAY AUDIO
if (tvPS.getText() == "Stop Phrase!") {
StopAudio();
}
else {
PlayAudio();
}
}
});
//the same button is clicked to stop, it is currently setting to Pause.
public void StopAudio() {
mediaPlayer.pause();
Toast.makeText(MainActivity.this, "STOPPED", Toast.LENGTH_SHORT).show();
tvPS.setText("Play Phrase!");
}
public void PlayAudio() {
//stopPlaying(mediaPlayer);
tvPS.setText("Stop Phrase!");
inResId = getResources().getIdentifier("play" , "raw", getPackageName());
mediaPlayer = MediaPlayer.create(getBaseContext(), inResId);
mediaPlayer.seekTo(0);
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//Toast.makeText(MainActivity.this, "Done", Toast.LENGTH_SHORT).show();
tvPS.setText("Play Phrase!");
mediaPlayer.pause();
}
});
}
...
public void onShake() {
// Do stuff!
Toast.makeText(getBaseContext(), "Motion detected",
Toast.LENGTH_SHORT).show();
if (mediaPlayer == null) {
PlayAudio();
}
}
How can I modify the code above to handle Play, and then stop if stopped in the middle and then able to replay it again.
The button click works but I am creating a new instance each time and not recycling. When the device is shaken, it plays the audio twice instead of just once.
First of all create the MediaPlayer in onCreate of the context and not in some listener, and don't forget to release it when done, since it consumes a lot of resources,
mediaPlayer.release();
mediaPlayer = null;
Next thing, stop the audio using the stop() function instead of the pause() on completion of the song.
Steps
If you are using a service/activity to play a video create a MediaPlayer instance before it's usage begins, likely in onCreate.
Later use that instance to play/pause/stop the media.
In the onStop of the Service/Activity release the MediaPlayer instance.
Update your playMusic() function to use the MediaPlayer instance you just created, also in the listener use stop() instead of pause()
To change track of an existing MediaPlayer instance
You can use this:
String path = getExternalFilesDir(null).toString()+"/";
mMediaPlayer.setDataSource(path + mediafile);
Link: Changing data source for audio playback using existing MediaPlayer?
Related
I am developing a music player on android and the app has two activities (MainActivity and PlayActivity). In the MainActivity I have a listview with a list of songs and in the PlayActivity I have a button to listen and pause the music. The problem is that when go back to MainActivity and I select a new song from the listview, the first one keeps playing on background while the second one also starts playing. How can I stop the first song when I select a new one?
(I don't want to stop mediaplayer onBackPressed, I just want to stop the music when another song it's selected from listview and play a fresh song in PlayActivity)
EDIT: I'm using AsyncTask to start mediaplayer on PlayActivity: mp.prepareAsync();
You could try to stop MediaPlayer when onBackPressed()
MediaPlayer mp ; // mp is your MediaPlayer
#Override
public void onBackPressed() {
if (mp != null) {
mp.stop();
mp.release();
mp = null;
}
super.onBackPressed();
}
private void playMusic() {
if (mp != null) {
if (mp.isPlaying()) {
mp.stop();
mp.release();
MediaPlayer copyMp = new MediaPlayer();
try {
copyMp.setDataSource("/path");
mp = copyMp;
mp.prepare();
mp.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
From here
MediaPlayer is not thread-safe. Creation of and all access to player
instances should be on the same thread.
That means you have to maintain one media player instance throughout your whole application(As per your requirement). I don't know how you implemented the media player(Service/AsyncTask etc.). When you select a new song, you need to access that instance and replace the existing song with the selected one.
Im a newbie to android studio (programming at general) but i want to build a mediaplayer for learning purposes.
I have a a list of local music in a listView that contains 2 images 'play, pause and stop button'.
This is how my app works:
Click on playbutton -> start music
Click on pausebutton -> pause music
Click on stopbutton -> stop music
Very simple. BUT! the thing is -> when i pause a song and want to play another song in my list then it just resume the first song i clicked on.
I want it to release the first song and start the other one i click on.
This is my code:
// play music
viewHolder.playB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (flag) {
//get song you clicked on
mediaPlayer = MediaPlayer.create(context, song.getSong());
//set boolean to false so it can get ANOTHER song when
//clicked
flag = false;
Toast.makeText(context, "Playing" + song.getName(),
Toast.LENGTH_LONG).show();
}
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
viewHolder.playB.setImageResource(R.drawable.play);
} else {
mediaPlayer.start();
viewHolder.playB.setImageResource(R.drawable.pause);
}
}
});
// stop
viewHolder.stopB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!flag) {
mediaPlayer.stop();
mediaPlayer.release();
flag = true;
}
viewHolder.playB.setImageResource(R.drawable.play);
}
});
Your logic is a little bit wrong. When you create the MediaPlayer you set flag to false and as long as you do not stop playback flag doesn't change. But your MediaPlayer creation depends on it.
For future improvements (maybe when you're more confident in working with MediaPlayer and Android) you should take a look at a more "self-made" approach instead of MediaPlayer.create(...) cause this method is calling MediaPlayer's prepare() method that is going to eventually make your app extremely slow or crash it when loading big files.
Example according to comments
I assumed songis going to be the class object.
// class variable will hold the currently loaded song
private Song mCurrentSong;
[...]
viewHolder.playB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// MediaPlayer has not been initialized OR clicked song is not the currently loaded song
if (mCurrentSong == null || song != mCurrentSong) {
// Sets the currently loaded song
mCurrentSong = song;
mediaPlayer = MediaPlayer.create(context, song.getSong());
Toast.makeText(context, "Playing" + song.getName(),
Toast.LENGTH_LONG).show();
}
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
viewHolder.playB.setImageResource(R.drawable.play);
} else {
mediaPlayer.start();
viewHolder.playB.setImageResource(R.drawable.pause);
}
}
});
viewHolder.stopB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// If currently loaded song is set the MediaPlayer must be initialized
if (mCurrentSong != null) {
mediaPlayer.stop();
mediaPlayer.release();
mCurrentSong = null; // Set back currently loaded song
}
viewHolder.playB.setImageResource(R.drawable.play);
}
});
I have a list of songs i put manually inside my app and it currently have 3 functions: start, pause and stop (using ImageViews).
The problem is that i can play multiple songs at the same time that is not supposed to be like that. I really cant find the issue here and hope someone can help.
This is a demonstration on my problem
I want it to STOP currently playing song when another song is being clicked on.
Here is my code for my play button:
viewholder.playB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (currentSong == null || song != currentSong) {
currentSong = song;
mediaPlayer = MediaPlayer.create(context, song.getSong());
}
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
viewholder.playB.setImageResource(R.drawable.play_black);
} else {
mediaPlayer.start();
viewholder.playB.setImageResource(R.drawable.pause_black);
}
}
});
Instead of always creating a new instance of MediaPlayer every time the event onClick is called, you should create a single instance and reused it.
To play a new song don't forget to reset your player first. Here is an example:
mPlayer.reset();
mPlayer.setDataSource(context, song.getSong());
I have searched for another mp3 player to use in my android project but i couldn't find. MediaPlayer is not good !
I'm trying to play a song , so when i click the song it plays , but if i click it again it should stop , MediaPlayer is not working good , i tried to make a
ProgressDialog
it also did not work .
viewHolder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String name = model.getTitle();
Toast.makeText(MainActivity.this, "you clicked on -> " + name , Toast.LENGTH_SHORT).show();
String url = model.getMusic();
MediaPlayer mp = MediaPlayer.create(getApplicationContext() , Uri.parse(url));
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (progressDialog != null && progressDialog.isShowing()){
progressDialog.dismiss();
}
mp.start();
}
});
if(mp.isPlaying()){
mp.stop();
}else {
mp.start();
}
}
});
You are calling the static create() method. The media will be prepared before that method returns. Your OnPreparedListener listener will never be called in your existing code.
The simple solution is to get rid of the OnPreparedListener and call dismiss() after create(). Most likely, you will find that your ProgressDialog does not do much good.
Alternatively:
Replace create() with just calling new MediaPlayer()
Add your OnPreparedListener
Call setDataSource() on the MediaPlayer in a background thread, as this will perform some disk I/O, and you do not want to do that on the main application thread
You may need to then arrange to call dismiss() on the main application thread — I have not tried to dismiss() a dialog from a background thread, and I do not know if that is supported.
In Adnroid, at first i declare the mediaplayer by
MediaPlayer mpl;
next I have this in the onCreate method
mp = new MediaPlayer();
mp = MediaPlayer.create(this, R.raw.hit );
mp.setVolume(1, 1);
and a function that's supposed to play a sound when called
public void click()
{
mp.start();
}
yet the problem is that if the user calls this function multiple times, before it has stopped playing the last sound, it will die and stop playing any sounds, before the app is reset.
Any ideas how to fix that?
Thanks!
edit - found a solution:
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mpl.release();
}
});
public void click()
{
if( ! mp.isPlaying() ) {
mp.start();
}//if
}//met
you can disable the button.
or you can stop current playing and star
new in onClick()