I'm developing an app that plays a background music. The music is managed by a service that runs in background. In the Main activity, in the onCreate() method, the service starts with:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Background music service.
Intent musicServiceIntent = new Intent(this, BackgroundSoundService.class);
startService(musicServiceIntent);
final BackgroundSoundService bss = new BackgroundSoundService();
buttonStart = (Button) v.findViewById(R.id.button_start);
buttonStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bss.onStart();
}
});
buttonPause = (Button) v.findViewById(R.id.button_pause);
buttonPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bss.onPause();
}
});
buttonStop = (Button) v.findViewById(R.id.button_stop);
buttonStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bss.onStop();
}
});
}
}
}
The service is the following code:
BackgroundSoundService.java
public class BackgroundSoundService extends Service {
private static final String TAG = null;
static MediaPlayer mMediaPlayer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mMediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.background_music);
mMediaPlayer.setVolume(1.0f, 1.0f);
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
playMusic();
}
});
playMusic();
}
public void playMusic() {
mMediaPlayer.start();
}
/**
*
* #param arg0 -
* #return -
*/
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
/**
*
*/
public void onStart() {
Log.d("A", "onStart()");
if(!mMediaPlayer.isPlaying()) {
Log.d("A", "mMediaPlayer is not playing");
playMusic();
} else {
Log.d("A", "mMediaPlayer is playing");
}
}
/**
*
*/
public void onPause() {
Log.d("A", "onPause()");
if(mMediaPlayer.isPlaying()) {
Log.d("A", "mMediaPlayer is playing");
mMediaPlayer.pause();
} else {
Log.d("A", "mMediaPlayer is not playing");
}
}
/**
*
*/
public void onStop() {
Log.d("A", "onStop()");
if(mMediaPlayer.isPlaying()) {
Log.d("A", "mMediaPlayer is playing");
mMediaPlayer.stop();
} else {
Log.d("A", "mMediaPlayer is not playing");
}
}
/**
*
*/
#Override
public void onDestroy() {
Log.d("A", "onDestroy()");
mMediaPlayer.stop();
mMediaPlayer.release();
}
/**
*
*/
#Override
public void onLowMemory() {
}
}
Now, MainActivity has three buttons to control the music. SART Button, starts music, PAUSE Button, put the sound in pause and STOP Button, stops music. Each one executes the methos onStart(), on Pause() and onStop() in the BackgroundSoundService. The problem is if I press the START Button after the STOP Button, the log show me this error:
E/MediaPlayer: start called in state 0
E/MediaPlayer: error (-38, 0)
I try solve this implementing:
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
But did not work. Any suggestions? Thank you.
Posting MainActivity code helps us to give an exact solution without deviating you to random answers.
After .stop() , if you want it to start again you need to reset it.
public void onStop() {
Log.d("A", "onStop()");
if(mMediaPlayer.isPlaying()) {
Log.d("A", "mMediaPlayer is playing");
mMediaPlayer.stop();
mMediaPlayer.reset();
mMediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.background_music);
} else {
Log.d("A", "mMediaPlayer is not playing");
}
}
EDIT
boolean isPrepared = false;
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
isPrepared = true;
}
});
public void playMusic() {
if(isPrepared){
mMediaPlayer.start();
isPrepared = false;
}
else{
Toast.makeText(getApplicationContext(),"Not prepared",LENGTH.SHORT)
.show();
}
}
Instead of mediaPlayer.create(), call new mediaplayer
Call prepare() and start() inside playMusic()
OR
prepareAsync() inside playMusic() and have onPreparedListener() calls start()
Related
I have created android app to stream online radio station and I want to run it in background using service.How to create service to run media player in background?
Here is source code of the application:
public class MainActivity extends AppCompatActivity
{
private ImageButton buttonPlay,buttonStop,buttonPause;
private String STREAM_URL = "http://178.149.86.162:8000/";
private MediaPlayer mPlayer;
Intent playbackServiceIntent;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonPlay = (ImageButton) findViewById(R.id.buttonPlay);
buttonStop = (ImageButton) findViewById(R.id.buttonStopPlay);
buttonPause = (ImageButton) findViewById(R.id.buttonPause);
mPlayer = new MediaPlayer();
buttonPlay.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
try
{
mPlayer.reset();
mPlayer.setDataSource(STREAM_URL);
mPlayer.prepareAsync();
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer mp)
{
mPlayer.start();
}
});
} catch (IOException e)
{
e.printStackTrace();
}
startService();
}
});
buttonStop.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
mPlayer.stop();
stopService();
}
});
buttonPause.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
mPlayer.pause();
stopService();
}
});
playbackServiceIntent = new Intent(this, BackgroundService.class);
}
private void startService()
{
startService(new Intent(MainActivity.this,BackgroundService.class));
}
private void stopService()
{
stopService(new Intent(MainActivity.this,BackgroundService.class));
}
}
public class BackgroundService extends Service implements OnCompletionListener
{
MediaPlayer mediaPlayer;
private String STREAM_URL = "http://178.149.86.162:8000/";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate()
{
mediaPlayer = new MediaPlayer();
try
{
mediaPlayer.setDataSource(STREAM_URL);
} catch (IOException e)
{
e.printStackTrace();
}
mediaPlayer.setOnCompletionListener(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!mediaPlayer.isPlaying()) {
try
{
mediaPlayer.reset();
mediaPlayer.setDataSource(STREAM_URL);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer mp)
{
mediaPlayer.start();
}
});
} catch (IOException e)
{
e.printStackTrace();
}
}
return START_STICKY;
}
public void onDestroy() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
}
public void onCompletion(MediaPlayer _mediaPlayer) {
stopSelf();
}
}
When i launch app and lock the screen without clicking(playing audio) button and after when i unlock the screen and press the play button i am getting Exception.
public class DemoActivity extends Activity {
MediaPlayer mp;
Button btn;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
mp = MediaPlayer.create(DemoActivity.this,R.raw.mus);
btn = (Button) findViewById(R.id.btnOk);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (btn.getText().toString().equalsIgnoreCase("play")) {
mp.start();
btn.setText("Pause");
} else if (btn.getText().toString().equalsIgnoreCase("pause")) {
mp.pause();
btn.setText("Play");
}
}
});
#Override
public void onPause() {
super.onPause();
if (mp.isPlaying()) {
mp.start();
} else {
mp.release();
}
}
#Override
protected void onRestart() {
try {
if (mp.isPlaying() && mp!=null) {
mp.start();
} else {
mp.release();
}
} catch (IllegalStateException e) {
e.printStackTrace();
}
super.onRestart();
}
#Override
protected void onDestroy() {
super.onDestroy();
mp.release();
}
}
Here is my code please try to give me a solution.
Thanks in advance
please try call mp.prepare() before every mp.start(). You are getting the error because the mp is not yet ready for your use, and calling start() on that will cause IllegalStateException.
You may have seen that I have had a problem with creating a Media Player a few months back. Well I am trying to get to the next stage by getting it to work in a fragment but the app keeps on stopping/crashing on me. Can someone help me please? Here is my activity/fragment (code-behind) class
public class MediaPlayerNew extends Fragment implements
android.media.MediaPlayer.OnCompletionListener,
android.media.MediaPlayer.OnPreparedListener,
android.media.MediaPlayer.OnErrorListener,
android.media.MediaPlayer.OnBufferingUpdateListener{
private MediaPlayer mp = null;
private String TAG = getClass().getSimpleName();
private Button play;
private Button pause;
private Button stop;
private TextView txtVStatus;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_player, container, false);
return view;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
play = (Button) getActivity().findViewById(R.id.btnPlay);
pause = (Button) getActivity().findViewById(R.id.btnPause);
stop = (Button) getActivity().findViewById(R.id.btnStop);
//status = (TextView) findViewById(R.id.txtVStatus);
pause.setEnabled(false);
stop.setEnabled(false);
play.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
play();
}
});
pause.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
pause();
}
});
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
stop();
}
});
}
private void play() {
//HTTP to BCRFM STREAM
Uri myUri = Uri.parse("http://37.187.193.36:8002");
try {
if (mp == null) {
this.mp = new android.media.MediaPlayer();
} else {
mp.stop();
mp.reset();
}
mp.setDataSource(myUri.toString()); // Go to Initialized state)
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setOnPreparedListener(this);
mp.setOnBufferingUpdateListener(this);
mp.setOnErrorListener(this);
mp.prepareAsync();
Log.d(TAG, "LoadClip Done");
} catch (Throwable t) {
Log.d(TAG, t.toString());
}
}
#Override
public void onPrepared(android.media.MediaPlayer mp) {
Log.d(TAG, "Stream is prepared");
final TextView textViewToChange = (TextView) getActivity().findViewById(R.id.txtVStatus);
textViewToChange.setText("Welcome to BCRfm");
mp.start();
play.setEnabled(false);
pause.setEnabled(true);
stop.setEnabled(true);
}
private void pause() {
mp.pause();
final TextView textViewToChange = (TextView) getActivity().findViewById(R.id.txtVStatus);
textViewToChange.setText("You have paused your feed to BCRfm");
play.setEnabled(true);
pause.setEnabled(false);
stop.setEnabled(true);
}
private void stop() {
mp.stop();
final TextView textViewToChange = (TextView) getActivity().findViewById(R.id.txtVStatus);
textViewToChange.setText(" ");
play.setEnabled(true);
pause.setEnabled(false);
stop.setEnabled(false);
}
#Override
public void onDestroy() {
super.onDestroy();
stop();
}
public void onCompletion(android.media.MediaPlayer mp) {
stop();
}
public boolean onError(android.media.MediaPlayer mp, int what, int extra) {
StringBuilder sb = new StringBuilder();
sb.append("Media Player Error: ");
switch (what) {
case android.media.MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
sb.append("Not Valid for Progressive Playback");
break;
case android.media.MediaPlayer.MEDIA_ERROR_SERVER_DIED:
sb.append("Server Died");
break;
case android.media.MediaPlayer.MEDIA_ERROR_UNKNOWN:
sb.append("Unknown");
break;
default:
sb.append(" Non standard (");
sb.append(what);
sb.append(")");
}
sb.append(" (" + what + ") ");
sb.append(extra);
Log.e(TAG, sb.toString());
return true;
}
public void onBufferingUpdate(android.media.MediaPlayer mp, int percent) {
Log.d(TAG, "PlayerService onBufferingUpdate : " + percent + "%");
}
}
There are issues with your code, and I will number them for clarity.
1) With methods onCreateView and onCreate, at least (check others!), place the keyword #Override above the methods declaration. Please compare sample codes in Google.
Failure to do this and perhaps the compiler would not consider it as overriding.
2) There is nothing wrong with
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
This is normal code.
3) Change from:
#Override
public void onDestroy() {
super.onDestroy();
}
TO:
#Override
public void onDestroy() {
stop();
super.onDestroy();
}
The main difference is calling stop() before onDestroy() call. When you're destructing, it's standard to call destroy/destruct after all the other codes.
And...you should stop the Media Player, otherwise it will still keep playing whatever even after the app exits.
Its okay, I fixed it.
I changed:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);......
to
public void onActivityCreated(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);..
And it works perfectly, only thing is when I want to switch from this fragment to another, the app crashes. Any tips?
Fixed it
Changed
#Override
public void onDestroy() {
super.onDestroy();
stop();
}
to
#Override
public void onDestroy() {
super.onDestroy();
}
In my code, I have a start/stop button.I am trying to play an audio clip from the raw folder. On completion of an audio clip, the start/stop button has to change from stop mode to start mode. I don't want to loop the audio. For this,I have called OnCompletionListener. However, the listener is called only once. If the media player is reset and created again, OnCompletionListener is no longer called.
public void playsong(View view) {
if (mySound != null)
{
if (!pause) {mySound.start();
btnStartStop.setBackgroundResource(R.drawable.button);
pause = true;
} else {
if (mySound.isPlaying()) {
mySound.stop();
do_it();
}
}
}
}
mySound.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mySound) {
do_it();
}
});
public void do_it() {
mySound.reset();
mySound = MediaPlayer.create(this, R.raw.a);
pause = false;
btnStartStop.setBackgroundResource(R.drawable.button2);
}
Try this code ?
In this example oncompletionlistner is called everytime
btnDemo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(objPlayer!=null){
if(objPlayer.isPlaying())
stopPlaying(objPlayer);
}
objPlayer = MediaPlayer.create(getApplicationContext(),R.raw.demoaudio);
if(objPlayer.isPlaying())
objPlayer.pause();
else
objPlayer.start();
Log.d("null", "Media Player started!");
if(objPlayer.isLooping() != true){
Log.d("null", "Problem in Playing Audio");
}
objPlayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
objPlayer.release();
objPlayer = null;
};
});
}
});
I'm newbie in android programming. I have the following code with a mediaplayer. when the user presses the back key or goes to another activity the sound won't stop.
what's the problem? I have the onDestory method but my problem exists!
public class Elementary1Activity extends Activity implements Runnable, OnClickListener, OnSeekBarChangeListener{
private SeekBar seekBar;
private ImageButton startMedia;
private ImageButton pauseMedia;
private MediaPlayer mp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.elementary1);
AudioControl();
}
public void AudioControl(){
seekBar = (SeekBar) findViewById(R.id.seekBarnew2);
startMedia = (ImageButton) findViewById(R.id.playbuttonnew2);
pauseMedia = (ImageButton) findViewById(R.id.pausebuttonnew2);
seekBar.setOnSeekBarChangeListener(this);
startMedia.setOnClickListener(this);
pauseMedia.setOnClickListener(this);
}
public void run() {
int currentPosition= 0;
int total = mp.getDuration();
while (mp!=null && currentPosition<total) {
try {
Thread.sleep(1000);
currentPosition= mp.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
seekBar.setProgress(currentPosition);
}
}
public void onClick(View v) {
pauseMedia.setVisibility(View.VISIBLE);
seekBar.setVisibility(View.VISIBLE);
startMedia.setVisibility(View.INVISIBLE);
if (v.equals(startMedia)) {
if (mp != null && mp.isPlaying()) return;
if(seekBar.getProgress() > 0) {
mp.start();
return;
}
mp = MediaPlayer.create(Elementary1Activity.this, R.raw.e1);
mp.start();
seekBar.setProgress(0);
seekBar.setMax(mp.getDuration());
new Thread(this).start();
}
if (v.equals(pauseMedia) && mp!=null) {
mp.pause();
pauseMedia.setVisibility(View.INVISIBLE);
startMedia.setVisibility(View.VISIBLE);
}
}
#Override
public void onDestroy() {
super.onStop();
mp= MediaPlayer.create(Elementary1Activity.this,R.raw.e1);
if(mp.isPlaying())
{
mp.stop();
mp.release();
finish();
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if(fromUser) mp.seekTo(progress);
}
}
I'd use onPause() event in your Elementary1Activity to manage the music pausing.
Something like:
#Override
public void onPause() {
super.onPause();
if (mp!=null) {
mp.pause();
}
}
You can do two things. If you want that MediaPlayer stop when you push back button and you want to close the app the best option is:
#Override
public void onDestroy(){
if(mp != null){
if(mp.isPlaying()){
mp.stop
}
mp.release();
}
super.onDestroy();
}
And if you want to make that MediaPlayer stop when you change of activity:
#Override
public void onPause(){
if (mp != null && mp.isPlaying()){
mp.pause();
}
}
Apart of that, don't create a new MediaPlayer when you want to close your app.