Reputation: 15682
I am trying to write a service that comes with a MediaPlayer
. I have different Activities accessing it, so I thought it would be best to peruse a Service.
It works fine so far, I have also added a call to startForeground
, as described here. The notification shows up.
But when I now press the home or back button on the device, the service is stopped and onDestroy
is called, and the notification icon disappears. When I return, the service seems to reBind just fine.
I stop the music playback on onDestroy
, so of course it stops. But I would like to keep the notification and service alive even when the user is on another app.
EDIT: I hope this is the relevant part:
public class MediaPlayerService extends Service {
private static class PlayerMessageHandler extends Handler {
private final MediaPlayerService owner;
public PlayerMessageHandler(MediaPlayerService owner) {
this.owner = owner;
}
@Override
public void handleMessage(Message msg) {
// Handle
}
}
private static final int NOTIFICATION_ID = 13138;
private final Messenger messenger = new Messenger(new PlayerMessageHandler(
this));
private MediaPlayer player;
private Notification notification;
@Override
public IBinder onBind(Intent intent) {
startNotification();
return messenger.getBinder();
}
@Override
public void onCreate() {
super.onCreate();
Log.v(TAG, "Media player service created.");
player = new AudiobookPlayer(this);
new Thread(seekerUpdate).start();
isRunning = true;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "Received start id " + startId + ": " + intent);
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.v(TAG, "Media player service destroyed.");
if (player.isPlaying()) {
player.pause();
}
sendMessageToUI(MSG_PLAYER_HAS_PAUSED);
isRunning = false;
}
private void sendMessageToUI(int msg) {
Log.v(TAG, "Sending " + msg);
sendMessage(Message.obtain(null, msg));
}
private void sendMessage(final Message message) {
// Send
}
private void startNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(
this);
builder.setSmallIcon(R.drawable.notification);
builder.setContentTitle(getString(R.string.app_name));
notification = builder.build();
startForeground(NOTIFICATION_ID, notification);
}
}
EDIT2: Methods from the activity, taken from here
@Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MediaPlayerService.class),
playerServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (bound) {
unbindService(playerServiceConnection);
bound = false;
}
}
Upvotes: 3
Views: 3063
Reputation: 9705
You should make your service sticky. In fact, this is what the tutorial uses:
public class HelloService extends Service {
...
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
...
// If we get killed, after returning from here, restart
return START_STICKY;
}
...
}
EDIT: from the discussion that transpired since, turns out that my suspicion was correct, and Hugo provided a spot-on diagnosis. I guess you now need to add builder.setOngoing(true);
in startNotification()
.
Upvotes: 5
Reputation: 221
Extracted from http://developer.android.com/guide/components/services.html Bound
A service is "bound" when an application component binds to it by calling bindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.
You are binding your Activities on onStart
and unbinding on onStop
. When you press Home or Back, your last foreground Activity may call onStop
, unbinding the last Activity from the Service and killing it.
An alternative solution would be call startService
so the onStartCommand
will be called, then calling the bindService
to bind the Activities.
Upvotes: 4