Exoplayer: Allow to dismiss notification with stopforeground(false) destroying service

Created on 27 May 2019  路  4Comments  路  Source: google/ExoPlayer

Issue description

I added a listener to the player and inside onPlayerStateChanged() i call stopforeground(false) when playWhenReady is false to allow users to dismiss the notification
` mPlayer.addListener(new Player.EventListener() {

        @Override
        public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
            if (playWhenReady) {
                ContextWrapper contextWrapper = new ContextWrapper(mContext);
                contextWrapper.startService(mIntent);
                startForeground(mNotificationId, mNotification);
            } else {
                stopForeground(false);
            }
        }
    }`

The dismiss notification is working correctly, but if a use the back button to navigate to the launcher or lock the phone, after a while with the playback paused, the service is destroyed and this appears on the logs

 2019-05-27 14:59:12.928 13863-14904/com.android.voyce V/FA: Inactivity, disconnecting from the service
2019-05-27 15:02:11.525 13863-13863/com.android.voyce I/ExoPlayerImpl: Release c274b39 [ExoPlayerLib/2.10.1] [dreamlte, SM-G950F, samsung, 28] [goog.exo.core, goog.exo.ui, goog.exo.mediasession]
2019-05-27 15:02:11.538 13863-14549/com.android.voyce I/ACodec: [OMX.SEC.mp3.dec] signalFlush
2019-05-27 15:02:11.539 13863-14549/com.android.voyce I/ACodec: [OMX.SEC.mp3.dec] ExecutingState flushing now (codec owns 10/10 input, 0/5 output).
2019-05-27 15:02:11.549 13863-14549/com.android.voyce I/ACodec: [OMX.SEC.mp3.dec] Now Flushing
2019-05-27 15:02:11.556 13863-14549/com.android.voyce I/ACodec: [OMX.SEC.mp3.dec] FlushingState onOMXEvent(0,1,0)
2019-05-27 15:02:11.556 13863-14549/com.android.voyce I/ACodec: [OMX.SEC.mp3.dec] FlushingState onOMXEvent(0,1,1)
2019-05-27 15:02:11.559 13863-14549/com.android.voyce I/ACodec: [OMX.SEC.mp3.dec] Now Executing
2019-05-27 15:02:11.571 13863-14549/com.android.voyce I/ACodec: [OMX.SEC.mp3.dec] Now Executing->Idle
2019-05-27 15:02:11.590 13863-14549/com.android.voyce I/ACodec: [OMX.SEC.mp3.dec] Now Idle->Loaded
2019-05-27 15:02:11.590 13863-14549/com.android.voyce I/ACodec: [OMX.SEC.mp3.dec] Now Loaded
2019-05-27 15:02:11.591 13863-14549/com.android.voyce I/ACodec:  [OMX.SEC.mp3.dec] Now kWhatShutdownCompleted event : 8544
2019-05-27 15:02:11.598 13863-14549/com.android.voyce I/ACodec:  [OMX.SEC.mp3.dec] Now uninitialized
2019-05-27 15:02:11.604 13863-14549/com.android.voyce I/ACodec:  [] Now kWhatShutdownCompleted event : 8544
2019-05-27 15:02:11.604 13863-14549/com.android.voyce I/MediaCodec: Codec shutdown complete
2019-05-27 15:02:11.731 13863-14075/com.android.voyce W/m.android.voyc: Accessing hidden method Ldalvik/system/CloseGuard;->close()V (light greylist, linking) 

this is my NotificationListener code

new PlayerNotificationManager.NotificationListener() {
                    @Override
                    public void onNotificationCancelled(int notificationId, boolean dismissedByUser) {
                        if (dismissedByUser) {
                            stopSelf();
                        }
                    }

                    @Override
                    public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) {
                        mNotification = notification;
                        mNotificationId = notificationId;
                        if (ongoing) {
                            startForeground(notificationId, notification);
                        }
                    }
                }

Reproduction steps

I create the service with

 mPlayerServiceIntent = new Intent(this, AudioPlayerService.class);
        bindService(mPlayerServiceIntent, mPlayerServiceConnection, BIND_AUTO_CREATE);

on the activity on create, then when the user chooses a song (a simple mp3 url from firebasestorage) then i call Util.startForegroundService(this, mPlayerServiceIntent);

then i pause the playback and exits the app with the back button, the notification with the paused state stays for a while, then it is destroyed as i mentioned above.

Version of ExoPlayer being used

Version 2.10.1

Device(s) and version(s) of Android being used

Samsung s8, api 28.

question

Most helpful comment

I think you already implemented it according to best practices.

The service is kept in foreground, if the app goes to background when the player is playing (playWhenReady = true), then your service is in foreground still. The user can then

1) Pause with the button in the notification. This would remove the service from foreground and the system kills the service and remove the notification after a given time.

2) When paused, the notification can be dismissed, which gives you the chance to stopSelf the service.

That's how you already implemented it. Not removing the service from the foreground when not doing playback is not a 'good citizen' behavior.

All 4 comments

This behaviour seems to be working as intended to me. If you call stopForeground(false) the service is not in foreground anymore. Then you put the app into the background with the back button. From this moment on the service needs to be in the foreground, or the system may terminate the service, which is what happens according to the log statements you added.

Seems like all the resources are nicely released. That's it exactly how it is designed to work.

If you want the notification to stay you need to call startForeground(int, Notification) again in the moment when the app goes to background. But I think it would maybe make sense to just leave it as is, because if the user pauses playback and leaves the app this may actually indicate the user does not want to play anymore.

So if I got your question right this behaviour seems to be as designed.

Thank you so much for answering. I wanted to keep the notification when user presses the back button and still allow it to dismiss the notification outside of my app. Is it possible? The behavior that i wanted is to allow the users to pause the playback and move to other apps, and the notification persists so the user can resume playback using the notification.

I think you already implemented it according to best practices.

The service is kept in foreground, if the app goes to background when the player is playing (playWhenReady = true), then your service is in foreground still. The user can then

1) Pause with the button in the notification. This would remove the service from foreground and the system kills the service and remove the notification after a given time.

2) When paused, the notification can be dismissed, which gives you the chance to stopSelf the service.

That's how you already implemented it. Not removing the service from the foreground when not doing playback is not a 'good citizen' behavior.

Okay, I will leave the way it is implemented right now. Thanks again!

Was this page helpful?
0 / 5 - 0 ratings