The Issue
Ultimately I want to run the following code whenever my app dies:
playerNotificationManager.setPlayer(null);
My Setup
I've seen a lot of questions asking how to keep a service alive, but I want my service to die and it keeps hanging around in the background.
I have an app using ExoPlayer with a service to continue playing audio in the background when you minimize the app. The service looks basically like so:
PlayerService.java:
package com.blueframetech.bfsdk.adapters;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import com.blueframetech.bfsdk.R;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.ui.PlayerNotificationManager;
public class PlayerService extends Service
{
public Player player;
private PlayerNotificationManager playerNotificationManager;
public void onCreate()
{
super.onCreate();
final Context context = this;
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
context, "Channel ID", R.string.app_name, 0,
new PlayerNotificationManager.MediaDescriptionAdapter() {
@Override
public String getCurrentContentTitle ( Player player )
{
return null;
}
@Nullable
@Override
public PendingIntent createCurrentContentIntent ( Player player )
{
return null;
}
@Nullable
@Override
public String getCurrentContentText ( Player player )
{
return null;
}
@Nullable
@Override
public Bitmap getCurrentLargeIcon (
Player player, PlayerNotificationManager.BitmapCallback callback
)
{
return null;
}
}
);
playerNotificationManager.setNotificationListener(new PlayerNotificationManager.NotificationListener() {
@Override
public void onNotificationStarted ( int notificationId, Notification notification )
{
startForeground(0, notification);
}
@Override
public void onNotificationCancelled ( int notificationId )
{
stopSelf();
}
});
}
private final IPlayerInterface.Stub mBinder = new IPlayerInterface.Stub() {
public void setPlayer ( int playerId ) throws RemoteException
{
if (playerId < 0)
{
playerNotificationManager.setPlayer(null);
}
else
{
player = ExoPlayerSingleton.getInstance(playerId);
playerNotificationManager.setPlayer(player);
}
}
};
@Override
public IBinder onBind ( Intent intent )
{
return mBinder;
}
}
To spin up the service, I do the following:
PlayerActivity.java:
playerId = ExoPlayerSingleton.createInstance();
playerView = findViewById(R.id.player_view);
serviceConnection = new ServiceConnection()
{
@Override
public void onServiceConnected ( ComponentName name, IBinder service )
{
playerService = (IPlayerInterface) service;
}
@Override
public void onServiceDisconnected ( ComponentName name )
{
playerService = null;
}
};
context.bindService(
new Intent(getContext(), PlayerService.class),
serviceConnection,
Context.BIND_AUTO_CREATE
);
Then in my activity's onDestroy
method, I added the following to avoid leaking the service when the back button was pressed:
getContext().unbindService(serviceConnection);
I also have an AIDL file and some code in onPause
and onResume
to switch between the PlayerView
and the PlayerService
(switching which is bound to the ExoPlayer instance) -- and that all seems to work as expected:
playerView.setPlayer(null);
playerService.setPlayer(playerId);
// ...
playerService.setPlayer(null);
playerView.setPlayer(ExoPlayerSingleton.getInstance(playerId));
What's Happening
If I minimize the app, the service takes over playback, the notification appears, and I continue to hear audio. However if I then go to the task manager and kill my app, the audio cuts out. This is fine. The issue is that after the audio cuts out, the notification remains open, and the service is still running in the background doing nothing. This is because the onDestroy
method of my activity isn't run when the app is killed this way.
Once I've gotten into this state, there are only two ways to kill the notification:
- Restart my app
- Go into Settings, find my app, and select "Force Stop"
How can I tell my service to die when my app dies? I don't like this zombie notification hanging around.