GOAL: Start, Stop, then Start play of a sound by clicking button 3 times
Hello All
I am new to Android.
I have had trouble restarting the play of a sound after stopping it by click of a button.
I have researched this problem
( Link ) and found different methods to apply.
So, I have tried four ways (unsuccessfully) to do this.
There are four buttons which use different methods.
Button 1 will be used as a control.
Look to comments for results of different methods.
I will post a couple entries from LogCat below.
Thank You
Here is a link to a relevant Android State Diagram
src/com.example.playsound/MainActivity.java
package com.example.playsound;
import java.io.IOException;
import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
//Create Media Player
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Button Sound
final MediaPlayer mPlayer1 = MediaPlayer.create(MainActivity.this, R.raw.playsound0);
final MediaPlayer mPlayer2 = MediaPlayer.create(MainActivity.this, R.raw.playsound1);
final MediaPlayer mPlayer3 = MediaPlayer.create(MainActivity.this, R.raw.playsound2);
final MediaPlayer mPlayer4 = MediaPlayer.create(MainActivity.this, R.raw.playsound3);
//Button References
Button button1 = (Button)this.findViewById(R.id.button1);
Button button2 = (Button)this.findViewById(R.id.button2);
Button button3 = (Button)this.findViewById(R.id.button3);
Button button4 = (Button)this.findViewById(R.id.button4);
//Button 1 OnClickListener
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mPlayer1.isPlaying() ) {
try {
mPlayer1.stop();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
// BUTTON 1
else { // plays sound upon first click, stops on second click
try { // but does not play on third click
mPlayer1.start();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
});
//Button 2 Uses .prepareAsync()
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mPlayer2.isPlaying() ) { // BUTTON 2
try { // Plays sound upon first click, stops on second click
mPlayer2.stop(); // But will not play upon third click
mPlayer2.reset();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
else {
try {
mPlayer2.prepareAsync();
} catch (IllegalStateException e) {
e.printStackTrace();
}
mPlayer2.start();
}
}
});
button3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mPlayer3.isPlaying() ) {
try { // BUTTON 3
mPlayer3.stop(); // Does not play sound upon first button click
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
else {
mPlayer3.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mPlayer3) {
mPlayer3.start();
}
});
}
}
});
//Button 4 OnClickListener
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mPlayer4.isPlaying() ) {
try {
mPlayer4.stop();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
// BUTTON 4
else { // does not play sound on first click
try {
mPlayer4.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mPlayer4.start();
}
}
});
}
}
Most errors in LogCat are similar to:
prepareAsync called in state 8
start called in state 0
start called in state 1
The errors are mostly "call in state #" errors.
I have referenced the diagram posted in the link above.
I still have these errors when I attempt to call methods in correct place.
You are calling methods in unappropriate states.
PrepareAsync can be called in only {Initialized, Stopped} state.
Start can be called only in {Prepared, Started, Paused, PlaybackCompleted} states.
So if you try to call those in other states than those then it will throw exception.
To have a clear knowledge about the states read this doc
Related
I need some advice about the code below. I'm trying to create a simple apps that when people click play button, then the music will start playing, and when people click the stop button, the music will stop playing. I'm using a single button for this two task start and stop.
I already test on android simulator, this start and stop button are working properly as I wanted to. But the problem occurred when I build an APK file and play it on a device. The stop button cannot work as I wanted to. If I press the stop button, the music will restart the playing from the beginning.
Any ideas about this problem? Thank you.
btn_playstop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (btn_playstop.isPressed()) {
if (player.isPlaying()) {
player.stop();
try {
player.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
player.seekTo(0);
btn_playstop.setBackgroundResource(R.drawable.play);
}
else {
player.start();
btn_playstop.setBackgroundResource(R.drawable.stop);
}
}
}
});
To achieve the play/stop button, do it this way.
btn_playstop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (player != null && player.isPlaying()) {
player.stop();
player.release();
player = null;
try {
player.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
player.seekTo(0); //<---- This is to resume the player from a specified position. It is helpful for a pause button. You can remove it for a stop button.
btn_playstop.setBackgroundResource(R.drawable.play);
}
else {
player.start();
btn_playstop.setBackgroundResource(R.drawable.stop);
}
}
});
You don't have to call the seekTo(Length) method for a stop button as it is meant for resuming the player from a specified position. Also if (btn_playstop.isPressed()) is unnecessary as you have already called the button using setOnClickListener.
imabutton=findViewById(R.id.imgbutton);
imabutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (imabutton.getTag().toString().contains("not_playing")){
if (mediaPlayer!=null)mediaPlayer.release();
mediaPlayer=MediaPlayer.create(MainActivity.this,R.raw.music1);
mediaPlayer.start();
imabutton.setImageResource(R.drawable.stop);
imabutton.setTag("playing");
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
imabutton.setTag("not_playing");
imabutton.setImageResource(R.drawable.play);
}
});
}else {
mediaPlayer.release();
imabutton.setImageResource(R.drawable.play);
imabutton.setTag("not_playing");
}
}
});
I want a play button in my app that when clicked plays the audio and changes to pause, and when the pause button is clicked the audio stops and the button changes to play again and so on. But the button is not working as expected. Please help. I'm adding my java code below.
public class surah extends AppCompatActivity {
MediaPlayer mp = new MediaPlayer();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_surah);
mp=MediaPlayer.create(surah.this, R.raw.surahkahf);
final ImageView audio = (ImageView)findViewById(R.id.btn);
audio.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mp.isPlaying()){
mp.stop();
audio.setBackgroundResource(R.drawable.play);
try {
mp.prepare();
}catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
mp.start();
audio.setImageResource(R.drawable.pause);
}
}
});
}
}
Use audio.setImageResource(R.drawable.play) instead of audio.setBackgroundResource(R.drawable.play). Use mp.pause() instead of mp.stop();
First, as aborocz mentions in comments, you probably intend to pause playback instead of stop it, so the method you want to use is pause(). In that case you would not need to prepare the MediaPlayer again, and it will start from the same place it was paused when playback is resumed.
Second, the isPlaying() method is not particularly appropriate for this purpose. There are race conditions that prevent the desired behavior. From the Android MediaPlayer documentation:
Note that the transition from the Started state to the Paused state
and vice versa happens asynchronously in the player engine. It may
take some time before the state is updated in calls to isPlaying(),
and it can be a number of seconds in the case of streamed content.
Instead, store your own boolean value.
public class surah extends AppCompatActivity {
private MediaPlayer mp;
private boolean isMediaPlaying = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_surah);
mp = MediaPlayer.create(surah.this, R.raw.surahkahf);
final ImageView audio = (ImageView)findViewById(R.id.btn);
audio.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isMediaPlaying) {
mp.pause();
audio.setBackgroundResource(R.drawable.play);
isMediaPlaying = false;
} else {
mp.start();
audio.setImageResource(R.drawable.pause);
isMediaPlaying = true;
}
}
});
}
}
I Have created a branch activity .Now i wanted to add two button on that branch activity.
When i click on 'sound on' button then my beep sound on start and when i clicked on 'sound off' then my beep sound off. and also they hide simultaneously.
Thank's
MY Code on Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.sound_layout);
soundBttnOn =(Button) findViewById(R.id.soundBttnOn);
soundBttnOn.setOnClickListener(
new OnClickListener(){
#Override
public void onClick(View v) {
startMediaPlayer();
}
}
);
soundBttnoff =(Button) findViewById(R.id.soundBttnOff);
soundBttnoff.setOnClickListener(
new OnClickListener(){
#Override
public void onClick(View v) {
stopMediaPlayer();
}
}
);
}
private void startMediaPlayer() {
mediaPlayer = MediaPlayer.create(SoundLayout.this,R.raw.keybutton5);
mediaPlayer.start();
}
private void stopMediaPlayer() {
if( mediaPlayer != null ) {
MediaPlayer mp = null;
mp.stop();
mp.release();
}
}
It showing no problem but it is not working too..:P..I am not able to implement sound.
You can do simple google search to find tons of samples for adding button. However for playing sound file check out the MediaPlayer class.
Button startBtn, stopBtn;
//get the reference of Button
....
final MediaPlayer mp = new MediaPlayer();
startBtn.onClickListener() {
public void onClick(View v) {
try {
mp.setDataSource(path+"/"+audio.mp3);
mp.prepare();
mp.start();
} catch (Exception e) {
e.printStackTrace();
}
}
};
stopBtn.onClickListener() {
public void onClick(View v) {
if(mp.isPlaying()) {
mp.stop();
//hide buttons
stopBtn.setVisibiltiy(View.GONE);
startBtn.setVisibility(View.GONE);
}
}
};
PS: For only on and off, you don't need two buttons, you could do with one button.
EDIT:
For single button, just use the playing state of Media player for deciding about the action to take on button click.
singleBtn.onClickListener() {
public void onClick(View v) {
try {
if(mp.isPlaying()) mp.stop();
else {
mp.setDataSource(path+"/"+audio.mp3);
mp.prepare();
mp.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
sorry my english, but I'm from Brazil and I used the google translator.
Well, I'm struggling in this application where I am trying to make a streaming an online radio, works fine in version 2.2, but version 4.0 does not work. No error occurs, simply does not work. Below is my code.
I appreciate any help.
package com.radiomiriam;
import java.io.IOException;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
public class Main extends Activity {
public String url = "http://69.64.48.96:9880";
public MediaPlayer player = new MediaPlayer();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void stop(){
Toast.makeText(getApplicationContext(), "Finalizando...", Toast.LENGTH_SHORT).show();
if(player.isPlaying()){
player.stop();
}
}
public void play(){
if(player.isPlaying()){
Toast.makeText(getApplicationContext(), "Já está em execução!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Preparando...", Toast.LENGTH_SHORT).show();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
try {
player.setDataSource(url);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
player.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
player.start();
}
}
public void onClick(View v) {
final int id = v.getId();
switch (id) {
case R.id.btnPlay:
play();
break;
case R.id.btnStop:
stop();
break;
}
}
}
Hello, excuse my insistence but I still have not found the solution to my problem and do not know how to solve, I have once again asking for your help to solve this problem.
The application runs in versions 2.x and 3.x but not in version 4.x. Below is a link to download the project, to which you can take a look and help me.
http://nsi.inf.br/RadioMiriam.rar (removed)
i downloaded your project and it actually returns error Code:
E/MediaPlayer( 1976): error (-38, 0)
It is caused by starting mediaplayer before it is prepared.
I have made few changes and it started to work. You should :
Set onPrepared listener on MediaPlayer (i.e. in onCreate)
player.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
Remove player.start() from your play() method
Set datasource in this way (in your play() method)
player.setDataSource(this, Uri.parse("http://69.64.48.96:9880/"));
It works on my HTC Sensation with Android 4.0.3
If you need any assistance please let me know.
EDIT: i forgot, i also removed
player.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
It is redundant
The prepare() call is probably blocking the UI thread (which android 4.0 hates it when you do that)
You will need to this work in a background thread like an asynctask. Here is a anonymous version of implementing AsyncTask to run play() in the background.
public void onClick(View v) {
final int id = v.getId();
switch (id) {
case R.id.btnPlay:
new AsyncTask<Void, Void, Void>(){
#Override
protected Void doInBackground(Void... voids) {
play();
return null;
}
}.execute();
break;
case R.id.btnStop:
stop();
break;
}
}
You will need to read up a bit about MediaPlayer's states (playing, preparing, stopped, etc) to learn why calling prepare will block the UI thread (
for more info on AsyncTasks
You haven't set any link between buttons in your .xml file and your code. onClick method is never called even though you are pressing the buttons.
Replace your onCreate method with this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button playButton = (Button) findViewById(R.id.btnPlay);
playButton.setOnClickListener(this);
Button stopButton = (Button) findViewById(R.id.btnStop);
stopButton.setOnClickListener(this);
play();
}
It is always better in android to do any IO work on a background thread.
And that includes MediaPlayer . but in MediaPlayer case you already have prepareAsync() method to prepare the MediaPlayer in the background for you.
A good way to do that is like this:
package com.radiomiriam;
import java.io.IOException;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
public class Main extends Activity implements OnPreparedListener{
public String url = "http://69.64.48.96:9880";
public MediaPlayer player = new MediaPlayer();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void stop(){
Toast.makeText(getApplicationContext(), "Finalizando...", Toast.LENGTH_SHORT).show();
if(player.isPlaying()){
player.stop();
}
}
public void play(){
if(player.isPlaying()){
Toast.makeText(getApplicationContext(), "J? est? em execuç?o!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Preparando...", Toast.LENGTH_SHORT).show();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
try {
player.setDataSource(url);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
player.setOnPreparedListener(this);
player.prepareAsync();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.start();
}
public void onClick(View v) {
final int id = v.getId();
switch (id) {
case R.id.btnPlay:
play();
break;
case R.id.btnStop:
stop();
break;
}
}
}
Also it is always a good practice to read the documentations, so here is a link to MediaPlayer API : MediaPlayer
i'm newbie, i'm tried to make play audio play and stop for 1 button only, but i'm in trouble now.
if i touch a button when audio is playing, it doesn't stop, even playing audio again and make a double sound.
here's my code
public class ProjectisengActivity extends Activity{
ImageButton mainkan;
MediaPlayer mp;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test2);
mainkan=(ImageButton)findViewById(R.id.imageButton1);
mainkan.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
go();
}
});
public void go(){
mp=MediaPlayer.create(ProjectisengActivity.this, R.raw.test);
if(mp.isPlaying()){
mp.stop();
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.seekTo(0);
}
else {
mp.start();
}
i'm create for android 3.0 (HoneyComb)
try below code in go function....
public void go() {
if(mp == null) {
mp=MediaPlayer.create(ProjectisengActivity.this, R.raw.test);
}
if(mp.isPlaying()){
mp.stop();
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.seekTo(0);
}
else {
mp.start();
}
}
It is simple, you should follow these steps to achieve this.
In your test2.xml create two buttons name start and stop.
Set the android:visibility attribute gone of stop button in xml file.
Now in your activity get the id of these two buttons and write the code for
starting and stopping of media player.
Set the visibility attribute gone on start click and visible of stop button,
follow its opposite on stop click.
I think you have wrong this line :
mp=MediaPlayer.create(ProjectisengActivity.this, R.raw.test);
You create new instance every time user clicks the button, so it's never playing and starts again. Put this line into onCreate rather than go()
Try also this,
public class MainActivity extends Activity {
MediaPlayer mPlayer;
int flag = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button mButton = (Button) findViewById(R.id.button1);
mButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (flag == 0) {
Log.v("Inside if", "Success" + "");
mPlayer = MediaPlayer.create(getApplicationContext(),
R.raw.sample);
mPlayer.start();
flag++;
} else {
Log.v("Inside else", "Success" + "");
mPlayer.stop();
mPlayer.release();
flag = 0;
}
}
});
}
}