I start my service when I click the play button to play a song and bundle the song mp3 with it and receive that in the onStartCommand. The problem is that when my activity that starts the service ends, my service calls onStartCommand again. When it goes to receive that bundle it's not there because the activity did not start it this time. Because of this I'm getting an illegalstateexception when preparing my mediaplayer. I am not binding my service.
Why does the onStartCommand get called when my activity ends?
Starting the service:
Intent i = new Intent(SongList.this,MyService.class);
i.putExtra("songURL", user.songurlz);
i.putExtra("songNAME", songplay_name);
startService(i);
The service class:
public class MyService extends Service {
static MediaPlayer mediaPlayer;
static int pauseplay;
static NotificationManager notificationManagerPlay;
static CharSequence tickerText;
static Notification notification4;//Notification variable(for song playing)
TelephonyManager telephonyManager;
PhoneStateListener listener;
static Notification notification;
static NotificationManager mNotificationManager;
String songurl;
String songname;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
super.onCreate();
mediaPlayer = new MediaPlayer();
pauseplay = 1;
MainMenu.serviceRunning = 1;
telephonyManager = (TelephonyManager) getSystemService(
Context.TELEPHONY_SERVICE);
// Create a new PhoneStateListener
listener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
case TelephonyManager.CALL_STATE_RINGING:
if (mediaPlayer.isPlaying() == true && mediaPlayer != null){
pauseSong();
}
break;
}
}
};
// Register the listener wit the telephony manager
telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (intent != null) {
Bundle bundle = intent.getExtras();
//Retrieve your data using the name
songurl = bundle.getString("songURL");
Bundle bundle2 = intent.getExtras();
//Retrieve your data using the name
songname = bundle2.getString("songNAME");
}
Toast toast = Toast.makeText(getApplicationContext(), "Now Playing: "
+ songname, Toast.LENGTH_LONG);
toast.show();
// configure the intent
Intent playIntent = new Intent(MyService.this, SongList.class);
final PendingIntent pendingIntent = PendingIntent.getActivity(
MyService.this, 0, playIntent, 0);
notification = new Notification(R.drawable.playicon, "Buffering...",
System.currentTimeMillis());
notification.contentView = new RemoteViews(getPackageName(),
R.layout.custom_notification2);
notification.contentIntent = pendingIntent;
if (SongList.bitmap != null) {
notification.contentView.setImageViewBitmap(R.id.notifimage,
SongList.bitmap);
} else {
notification.contentView.setImageViewResource(R.id.notifimage,
R.drawable.icon);
}
notification.contentView
.setTextViewText(R.id.notiftitle, "Now Playing");
notification.contentView.setTextViewText(R.id.notiftext, songname);
notification.flags = notification.flags
| Notification.FLAG_ONGOING_EVENT;
mNotificationManager = (NotificationManager) getApplicationContext()
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(4, notification);
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(songurl);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// register an error listener via MediaPlayer's setOnErrorListener
mediaPlayer.setOnErrorListener(new OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e("MEDIAPLAYER ERRORS", "what: " + what + " extra: "
+ extra);
mediaPlayer.reset();
mNotificationManager.cancel(4);
return false;
}
});
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
mediaPlayer
.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
public void onCompletion(MediaPlayer mp) {
stopSelf();
}
});
return START_STICKY;
}
@Override
public void onDestroy() {
MainMenu.serviceRunning = 0;
mNotificationManager.cancel(4);
}
public static void pauseSong() {
if (mediaPlayer.isPlaying() == true) {
mediaPlayer.pause();
mNotificationManager.cancel(4);
pauseplay = 0;
}
}
public static void playSong() {
if (pauseplay == 0) {
mNotificationManager.notify(4, notification);
mediaPlayer.start();
pauseplay = 1;
}
}
}
onStartCommand() is called every time a client starts the service using startService(Intent intent) . This means that onStartCommand() can get called multiple times. You should do the things in this method that are needed each time a client requests something from your service.
To start a foreground service, call startForeground() . To stop it, call stopForeground() .
startService() then the system will retrieve the service (creating it and calling its onCreate() method if needed) and then call its onStartCommand(Intent, int, int) method with the arguments supplied by the client. The service will at this point continue running until Context. stopService() or stopSelf() is called.
A service is started when an application component, such as an activity, starts it by calling startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. A service is bound when an application component binds to it by calling bindService().
Why does the onStartCommand get called when my activity ends?
Either you are calling startService()
when your "activity ends" (whatever that means), or Android is restarting your service for some reason due to your use of START_STICKY
.
Personally, for a music player, I argue that START_NOT_STICKY
is the right answer. If your service is stopped for whatever reason, the user should be in charge of starting it up again.
I know that this answer might not be useful anymore, but I had the same issue and by checking the documentation of this return code for onStartCommand
I found that it will solve the issue.
EDIT:
Your onStartCommand should
be like this:
public int onStartCommand(Intent intent, int flags, int startId)
{
//the same code
//......
//then return the new code which I'm pointing to
return START_REDELIVER_INTENT;
}
Here's what the documentation say about this return code:
public static final int START_REDELIVER_INTENT
Constant to return from
onStartCommand(Intent, int, int)
: if this service's process is killed while it is started (after returning fromonStartCommand(Intent, int, int)
), then it will be scheduled for a restart and the last delivered Intent re-delivered to it again viaonStartCommand(Intent, int, int)
.
Using this return code will make the OS resend the Intent every time the method onStartCommand
recalled (for whatever reason might cause this).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With