I have this problem, I have some audio I wish to play...
And I have two buttons for it, 'Play' and 'Stop'...
Problem is, after I press the stop button, and then press the Play button, nothing happens. -The stop button stops the song, but I want the Play button to play the song again (from the start) Here is my code:
final MediaPlayer mp = MediaPlayer.create(this, R.raw.megadeth);
And then the two public onclicks:
(For playing...)
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
button.setText("Playing!");
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
//
}
});
And for stopping the track...
final Button button2 = (Button) findViewById(R.id.cancel);
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mp.stop();
mp.reset();
}
});
Can anyone see the problem with this? If so could you please fix it... (For suggest)
Thanks alot...
James
You need to call prepare() or preparAsync() before start().
See the API for details (look at the state diagram).
There is a bug in the Android documentation, in this page it is said that you could stop() a "raw resource" mediaplayer, and then replay it just by calling reset() and prepare() before calling start() again. This doesn't work, as you have noticed.
The problem is that reset() clears the audio source and returns to the initial state, so you must set again the data source. Unfortunatelly you can't set a "raw resource" data source, because there is no API for this besides create().
I don't know a clean way of solving this issue. stealthcopter's way works great, but is a pain for your design, as you need the context for each start() call :( And involves destroying and creating a complex object, which has a price for realtime apps like games...
Another way that ensures that context will only be needed for the create() call, is to stop the media player this way:
stop()
prepare()
but if you call start() now, it won't restart from the beginning. You could call seekTo(0), but the sound will have a bit of noise from the previous play position.
I keep investigating on this. There must be a clean and efficient way of stopping and restarting the mediaplayer when created on a raw resource...
This is what I have working in my program. It releases the media player each time as I use different sounds each time it is called, however it should work as a work-around for your usage.
Creation:
public MediaPlayer mp=null;
Starting:
if (mp!=null){
mp.reset();
mp.release();
}
mp = MediaPlayer.create(test.this, soundResource);
mp.start();
Stopping:
mp.stop();
Also note that you do not require to use prepare because the create method already calls prepare for you (API REF).
Related
I have an online music player and my problem is when user press on play button
my app freeze for 1 or 2 second(network speed).
I play music of a link of my server and put it in Voice variable and play stream that.
whats the problem of my code?
Thanks.
My code:
detail_voice.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar snackbar = Snackbar.make(detail_date, " " + "دارم میگیرررررررررمش :| :)))", Snackbar.LENGTH_SHORT);
snackbar.show();
try {
mp.setDataSource(Voice);
mp.prepare();
mp.start();
detail_voice.setVisibility(View.GONE);
detail_voice_stop.setVisibility(View.VISIBLE);
} catch (IOException e) {
e.printStackTrace();
}
}
});
detail_voice_stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
detail_voice.setVisibility(View.VISIBLE);
detail_voice_stop.setVisibility(View.GONE);
mp.stop();
mp.reset();
detail_voice_stop.setVisibility(View.GONE);
}
});
The code you've provided is not extensive, but my guess is your problem might indeed have to do with loading your data over the network. Usually when loading data over a network, you'll want to do that asynchronously to avoid the program needlessly waiting for the data, and freeze during that time.
The MediaPlayer class has a prepareAsync() method which will do this for you. But, you cannot put the start() method below that anymore as it is now asynchronous. Try replacing this code:
mp.setDataSource(Voice);
mp.prepare();
mp.start();
With this:
mp.setDataSource(Voice);
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer player) {
player.start();
}
});
mp.prepareAsync();
If that code solves the problem, your connection was indeed the problem. You should not however use the setOnPreparedListener() method every time you click. I'd suggest moving it outside the onClickListener() method so it is only executed once.
This Stackoverflow question has a good implementation too. It might be worth a read as well.
I'm trying to create a mock radio app with about 100 songs that'll be played randomly, and occasionally interrupt the music with other audio files.
This is the snippet that's giving me trouble:
mp.start();
while(true)
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mPlayer) {
radio.playRadio();
}
});
I've gotten the code to work with some infinite loops that would hang the app (I couldn't even change volume), which is why I thought the OnCompletionListener would break that up. Instead, it doesn't even seem to go into the radio.PlayRadio function.
What I'm expecting to happen is that the program starts with the starting audio, then while that's playing goes into the while loop and stops at the OnCompletionListener. When it completes, goes into the function, performs the actions in there (sets media, plays them), exits, then loops back to the wait for complete.
If I take out the while(true), it goes into the function, so somehow the while loop is stopping everything, and reading documentation and other questions isn't explaining why.
You can use recursive method to tackle the problem. For example, if you are playing the song, you can create the following method:
private void playSong(Uri uri) {
// this is just example, don't expect the code to works.
MediaPlayer mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setDataSource(getApplicationContext(), uri);
mp.prepare();
mp.start();
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mPlayer) {
// get the next uri here
// assume there is next uri.
playSong(nextUri);
}
});
}
You should not use while loop to block your code. Instead, you need to rely on the message sent by the listener.
I'm trying make a simple mediaplayer but the pause button doesn't work. When I click on the pause button it stops but when I click on play again it starts at the start again.
I don't know how to make one button where I can play/pause the button.
Code I currently have:
http://pastebin.com/wiDkzw5S
Thanks already!
You would need to save current position of media player and restart it later from that position using seekTo.
Something like:
int currentPos = 0;
pause.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (mediaPlayer.isPlaying()) {
currentPos = mediaPlayer.getCurrentPosition();
mediaPlayer.pause();
//change image to play
} else {
mediaPlayer.seekTo(currentPos);
mediaPlayer.start();
//again revert image to pause
}
}
});
Hope it helps.
This is running test and running code, you may use this for pause and resume the media player.
int length=0;
Button pause = (Button) findViewById(R.id.pause);
pause.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
length=mediaPlayer.getCurrentPosition();
} else {
mediaPlayer.seekTo(length);
mediaPlayer.start();
}
}
});
I had a similar problem, but I couldn't get it to resume using the methods above.
I discovered my pauseAllSounds() function was pausing all MediaPlayer instances in my sound pool even if they weren't already playing. When that happened, it caused an error in each instance which wasn't playing which prevented that instance from playing again later. I discovered this after some time only by happening across the console output for my running process searching for the cause. It showed line after line of errors, revealing I was trying to pause from an invalid state.
// Make sure you test isPlaying() before pausing
public void pause() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
position = mediaPlayer.getCurrentPosition();
}
}
Once I added the test to only pause if it was already playing, everything worked.
I want to play an audio file in the background of my app. Easy enough. I want the music to persist and NOT stop or pause while switching between activities in my app. Also fairly easy and accomplished simply by doing this in the onCreate method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
mp = MediaPlayer.create(MainActivity.this, R.raw.lostmexicancity);
mp.setLooping(true);
mp.start();
}
The problem? Getting the music to stop when I press the HOME button.
Killing the sound when the user presses the back button seems easy. Here's what I have for that and works great:
public void onPause() {
if(this.isFinishing()){ //BACK was pressed from this activity
mp.stop();
}
super.onPause(); }
Not complicated, but this does not catch presses of the HOME button. If the Home button is pressed, the music keeps playing even while the user no longer sees my app.
I have seen answers that involve setting permission in the manifest to Get Tasks which I shouldn't have to do and appears dangerous to users. Besides that, the solution didn't even work. I've seen solutions that involve using a service, but none of those work either because the home button STILL plays the music just like before because there doesn't seem to be a way to catch it and it doesn't 'finish' the app (not to mention that every time someone suggest using a service for this task multiple people come in and state that this is not a proper use for services)
It seems the only way to kill the music when the Home button is pressed is to use a non-conditional stop() within onPause, but that's no good because that's called when I swap activities with intents, causing the music to end between activities which is no good.
I have trouble imagining that such a common function like background music is this hard, but I've seen post after post with the same issue as me and no proper answers other than ones that would kill the music between activities within the app.
How do all the other apps on the Google play store accomplish this and yet there appears to be no clear answer online? I could just stop and start the music with each onPause(), but that would cause unprofessional gaps in audio not to mention it would start the background audio from the beginning over and over again which is unacceptable.
I'm a bit new to Android Programming (few months) and today, I faced the same problem you did (maybe you still do?)
I made it work as the following :
Lets say I have MainActivity, and in MainActivity I have Btn2 which leads to SecondActivity, and Btn3 which leads to ThirdActivity.
I declared at the beginning of MainActivity :
public static boolean shouldPlay = false;
I then implemented my onStop() method :
public void onStop() {
super.onStop();
if (!shouldPlay) { // it won't pause music if shouldPlay is true
player.pause();
player = null;
}
}
If the boolean shouldPlay is set to true, then my onStop() won't be called entirely and my music won't turn off. I then have to decide when I set it to true. When I switch from MainActivity to SecondActivity, I do it through an Intent and that's when I'll set shouldPlay to true :
Button Btn2 = (Button) findViewById(R.id.Btn2);
Btn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
shouldPlay = true;
startActivity(intent);
}
});
And the same is done for Btn3.
Now, the last thing we want to be looking for is that if I was to go back to MainActivity after visiting SecondActivity or ThirdActivity, shouldPlay would then have been set to true. The first thing I tried was to set it to false as soon as Second and ThirdActivity are called (in their onCreate()) but it want to work, maybe because the onStop() from Main and onCreate() from others are called simultaneously (frankly I don't really get life cycle for now).
What worked is simply to set shouldPlay to false every time we launch onCreate() of Main :
shouldPlay = false;
This works properly for me.
Let me know if it does for you,
Cheers,
bRo.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if(keyCode == KeyEvent.KEYCODE_HOME){
Log.d("Jorgesys", "Home button pressed!!!");
}
return super.onKeyDown(keyCode, event);
}
but hey! This no longer works as of 4.0 + , Read this: Capture Home Key Event
Try with Back button:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK ) {
Log.d("Jorgesys", "Back button pressed!!!");
}
return super.onKeyDown(keyCode, event);
}
To stop the media player, you are using the method:
isFinishing(): if the activity is finishing, returns true; else
returns false, but you are only pausing the activity not finishing the
activity.
public void onPause() {
if(this.isFinishing()){ //INCORRECT, Here you are pausing you activity not finishing.
mp.stop();
}
super.onPause();
}
so change to:
public void onPause() {
if(mp.isPlaying())
{
mp.stop();
}
super.onPause();
}
When your activity is on pause, evaluates if your MediaPlayer is playing, if this is true then stops the audio.
I have a button that plays an audio file on its click listener. If the button is clicked again and again while the audio file is being played then the app crashes. What's the solution?
Here is some code for reference:
private OnClickListener btnMercyListener = new OnClickListener()
{
public void onClick(View v)
{
// Toast.makeText(getBaseContext(),
// "Mercy audio file is being played",
// Toast.LENGTH_LONG).show();
if (status==true)
{
mp.stop();
mp.release();
status = false;
}
else
{
mp = MediaPlayer.create(iMEvil.this,R.raw.mercy);
//mp.start();
try{
mp.start();
status= true;
//mp.release();
}catch(NullPointerException e)
{
Log.v("MP error",e.toString());
}
}
mp.setOnCompletionListener(new OnCompletionListener(){
// #Override
public void onCompletion(MediaPlayer arg0) {
mp.release();
status = false;
}
}
);
}
};
Two things:
1. Debug the crash and see where it's failing (which line).
2. Surround the whole statement with a try/catch and simply catch an Exception.
If you have an exception or a better idea where your code is failing, then it will be much easier to give you advice on how to fix it... as a matter of fact, you might not even need advice to fix it, you might end up solving the problem by yourself and then you will reap the fruits of your own success.
Update per comments:
The documentation for MediaPlayer indicates what might be the problem given the symptoms the OP is seeing:
To stop playback, call stop(). If you wish to later replay the media, then
you must reset() and prepare() the MediaPlayer object before calling
start() again. (create() calls prepare() the first time.)
It looks like if the play button is pressed too many times, then the media may end up not being in the prepared state and thus throw some exception. The idea of disabling the play button is valid and it should take care of this situation.
Here is some illustrative code on what you want your program to do:
private OnClickListener btnMercyListener = new OnClickListener()
{
public void onClick(View v)
{
if(isPressed)
{
return;
}
isPressed = true;
// create your media player
mp = MediaPlayer.create(iMEvil.this,R.raw.mercy);
// set your listener
mp.setOnCompletionListener(mp.setOnCompletionListener(new OnCompletionListener(){
// #Override
public void onCompletion(MediaPlayer arg0) {
if(!isPressed)
{
return;
}
isPressed = false;
// re-enable your play button
playButton.enable();
// disable the pause button
pauseButton.disable();
mp.release();
mp.prepare();
}
}
);
// disable the play button
playButton.disable();
// enable the pause button
pauseButton.enable();
// start playback
mp.start();
}
};
Of course you should have the appropriate try/catch statements in there so your app doesn't crash, but this code should give you a general idea of what to do.