I am not able to continue playing when the app is swiped away.
I am not able to continue playing when the app is swiped away. My service looks like this:
public class PlayerService extends MediaSessionService {
private static final String TAG = "PlayerService";
private MediaSession mediaSession = null;
@Override
public void onCreate() {
super.onCreate();
ExoPlayer player = new ExoPlayer.Builder(this).build();
mediaSession = new MediaSession.Builder(this, player)
.setSessionActivity(getMainIntent()).build();
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
private PendingIntent getMainIntent() {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra(Common.isPlaying, mediaSession != null && mediaSession.getPlayer().isPlaying());
return PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ?
PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT));
}
@Nullable
@Override
public MediaSession onGetSession(@NonNull MediaSession.ControllerInfo controllerInfo) {
return mediaSession;
}
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Player player = mediaSession.getPlayer();
if (!player.getPlayWhenReady()
|| player.getMediaItemCount() == 0
|| player.getPlaybackState() == Player.STATE_ENDED) {
stopSelf();
}
}
@Override
public void onDestroy() {
if (mediaSession != null) {
mediaSession.getPlayer().release();
mediaSession.release();
mediaSession = null;
}
super.onDestroy();
}
}
My MainAcitivty:
@Override
protected void onStart() {
super.onStart();
SessionToken sessionToken = new SessionToken(this,
new ComponentName(this, PlayerService.class));
controllerListenableFuture = new MediaController.Builder(this, sessionToken).buildAsync();
controllerListenableFuture.addListener(() -> {
try {
player = controllerListenableFuture.get();
player.addMediaItem(media); //media created from uri
player.prepare();
player.play();
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}, MoreExecutors.directExecutor());
}
Whenever I close the app, playback stops, and the notification disappears. How do I keep the player running in the background?
Originally posted by @colorgold in https://github.com/androidx/media/issues/389#issuecomment-2192874277
If you add logging, do you see control flow entering the if inside onTaskRemoved when you close the app? If so, which of the 3 OR'd conditions is true to result in that happening?
If you don't see control flow entering that if, do you see anything in logcat to indicate why your service is being stopped?
If you add logging, do you see control flow entering the
ifinsideonTaskRemovedwhen you close the app? If so, which of the 3 OR'd conditions is true to result in that happening?If you don't see control flow entering that
if, do you see anything in logcat to indicate why your service is being stopped?
I added the following logs in the PlayerService:
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.d(TAG, "PlayerService: onTaskRemoved called");
Player player = mediaSession.getPlayer();
if (!player.getPlayWhenReady()
|| player.getMediaItemCount() == 0
|| player.getPlaybackState() == Player.STATE_ENDED) {
Log.d(TAG, "PlayerService: onTaskRemoved: Service will be stopped");
stopSelf();
}else{
Log.d(TAG, "PlayerService: onTaskRemoved service continues");
}
}
@Override
public void onDestroy() {
Log.d(TAG, "PlayerService: onDestroy called");
if (mediaSession != null) {
mediaSession.getPlayer().release();
mediaSession.release();
mediaSession = null;
Log.d(TAG, "PlayerService: onDestroy: service destroyed");
}
super.onDestroy();
}
When I close the application while the media is playing, the control flow never enters the if statement, but the service gets destroyed. It only enters when the media is not playing, as expected.
In MainActivity I added a button that controls playback:
private void togglePlay() {
if (player.isPlaying()) {
player.pause()
} else {
player.play()
}
}
Logcat shows this error when I press play:
MediaResumeListener com.android.systemui E Cannot resume with ComponentInfo{com.murcianys.micaster/com.murcianys.micaster.services.PlayerService}
When I remove the app from recents while playing and then I reopen and press play again, I get these in logcat
MediaResumeListener com.android.systemui D Testing if we can connect to ComponentInfo{com.murcianys.micaster/com.murcianys.micaster.services.PlayerService}
2024-06-28 18:46:35.127 1972-2072 ResumeMediaBrowser com.android.systemui D Service connected for ComponentInfo{com.murcianys.micaster/com.murcianys.micaster.services.PlayerService}
2024-06-28 18:46:35.128 1972-2072 MediaResumeListener com.android.systemui D Connected to ComponentInfo{com.murcianys.micaster/com.murcianys.micaster.services.PlayerService}
2024-06-28 18:46:35.130 1972-2072 ResumeMediaBrowser com.android.systemui D Subscribe error for ComponentInfo{com.murcianys.micaster/com.murcianys.micaster.services.PlayerService}: androidx.media3.session.MediaLibraryService
I added a screen recording for reference.
https://github.com/androidx/media/assets/45986859/b11dda3e-57b7-4328-b39c-a0fefde3cf50
Please can you capture an adb bugreport shortly after reproducing the issue (including your additional logging) and either upload it here or send it to [email protected] with the subject Issue #1507.
This line from the BR makes it look like your service crashed (but I can't see any stack trace or similar before that to indicate what would have caused the crash):
07-02 17:08:44.821 1000 1039 2511 W ActivityManager: Scheduling restart of crashed service com.murcianys.micaster/.services.PlayerService in 1000ms for start-requested
Looking elsewhere, it also seems like the service is stopped ~2s before that:
07-02 17:08:42.961 1000 1039 1109 I am_foreground_service_stop: [0,com.murcianys.micaster/.services.PlayerService,1,PROC_STATE_TOP,34,34,0,0,8261,1,STOP_FOREGROUND,2]
And then the same restart is logged:
07-02 17:08:44.821 1000 1039 2511 I am_schedule_service_restart: [0,com.murcianys.micaster/.services.PlayerService,1000]
I noticed the BR is from a Samsung A51. Does the same issue reproduce on a Pixel device or an emulator created from Android Studio? I wonder if your service is being killed by some background battery saving logic added by Samsung: https://www.samsung.com/us/support/troubleshoot/TSG10001536
This line from the BR makes it look like your service crashed (but I can't see any stack trace or similar before that to indicate what would have caused the crash):
07-02 17:08:44.821 1000 1039 2511 W ActivityManager: Scheduling restart of crashed service com.murcianys.micaster/.services.PlayerService in 1000ms for start-requestedLooking elsewhere, it also seems like the service is stopped ~2s before that:
07-02 17:08:42.961 1000 1039 1109 I am_foreground_service_stop: [0,com.murcianys.micaster/.services.PlayerService,1,PROC_STATE_TOP,34,34,0,0,8261,1,STOP_FOREGROUND,2]And then the same restart is logged:
07-02 17:08:44.821 1000 1039 2511 I am_schedule_service_restart: [0,com.murcianys.micaster/.services.PlayerService,1000]I noticed the BR is from a Samsung A51. Does the same issue reproduce on a Pixel device or an emulator created from Android Studio? I wonder if your service is being killed by some background battery saving logic added by Samsung: https://www.samsung.com/us/support/troubleshoot/TSG10001536
I followed the steps in the link you provided, specifically #2 Remove the app from Sleeping apps. My app was listed in the Sleeping apps section, so after removing it, the notification works in the background.
I had the app installed on the phone long ago and just came back to work on it. The device has a setting that puts unused apps to sleep which caused the service to stop.
Thanks for the help!
Great, glad you got it sorted.