0

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:

  1. Restart my app
  2. 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.

stevendesu
  • 15,753
  • 22
  • 105
  • 182
  • May be this link help you: https://stackoverflow.com/questions/5555765/stop-service-in-android – Saboor Siddique Jun 13 '19 at 21:23
  • @SaboorSiddique Unfortunately that link doesn't help. In their example the app is still open and they're using the interaction with a button view to trigger a call to `stopService`. In my case, I want to stop the service when my app is killed - and there is no callback for that which I can find. I tried `onStop`, `onDestroy`, and even the service's `onUnbind` - but nothing was called automatically when the app died – stevendesu Jun 13 '19 at 21:30

0 Answers0