Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onTaskRemoved not called when app dismissed from recent tasks on Android 14 #805

Open
1 task
svenoaks opened this issue Nov 11, 2023 · 12 comments
Open
1 task
Assignees
Labels

Comments

@svenoaks
Copy link

svenoaks commented Nov 11, 2023

Version

Media3 1.1.1

More version details

Also happens with 1.2.0rc-1

Devices that reproduce the issue

  • API 34 emulator (Google Play)
  • Pixel 6a with Android 14

Devices that do not reproduce the issue

  • API 33 emulator (Google APIs)
  • Samsung Tab S7+ with Android 13

Reproducible in the demo app?

Yes

Reproduction steps

  1. Play some audio in demo-session app
  2. Tap pause in the app
  3. Navigate to the home screen
  4. Swipe up on the demo-session app from recent apps
  5. Observe dead notification in notifications

Expected result

There is no notification in the notification drawer

Actual result

There is a notification in the notification drawer that is inoperable, if you click on play button, a DeadObjectException is thrown

Media

Jazz & Blues, Jazz in Paris

Bug Report

@svenoaks
Copy link
Author

screen-20231111-183613.mp4

Here's video of the bug occurring, perhaps an important reproduction step is you have to navigate back to the home screen before going to the recent apps list, otherwise it doesn't seem to occur

@marcbaechinger
Copy link
Contributor

Yeah, true. I can repro this. Took a while to make it repro but I was able to see that twice now. Thanks for reporting. We look into this.

@marcbaechinger
Copy link
Contributor

This is a bug in Android 14. We have reported this internally and a fix is on it's way. There is nothing Media3 as a library or an app could do about it.

@leejooheon
Copy link

leejooheon commented Feb 7, 2024

It has been fixed to the security patch version of 2024-02-05, Android14, Pixel6

It's my mistake. sorry.
This bug still exists.

@marcbaechinger
Copy link
Contributor

Thanks for the heads up. Can you give us the build number with which you have verified this has been fixed and how you tried to repro?

When I test with UQ1A.240205.004 I still see the problem I'm afraid.

@jigarpandya-techholding
Copy link

@svenoaks @marcbaechinger I'm facing this issue on Android 13 as well. The work around that I have implemented as @marcbaechinger described in one of the comments is to release the player and session before calling stopSelf in onTaskRemoved. I just wanted to confirm whether this issue is only occurring when player is paused ? as when player is playing and I remove app from recents, it works fine.

@marcbaechinger
Copy link
Contributor

I think these are two different issues.

On Android 14 and with the repro steps from above, onTaskRemoved isn't called at all.

I just wanted to confirm whether this issue is only occurring when player is paused ?
as when player is playing and I remove app from recents, it works fine.

Pausing the player to repro this issue is required, because that is how the demo app is implemented. Without pausing, playback would continue in the background when dismissing the app from recents which is working as intended.

Generally, to stop the service the service must not run in the foreground (hence the player needs to be paused) and no controller/browser must be bound to the service (options: all controller disconnected already or the session is released). If either of these conditions are violated, calling stopSelf is a no-op.

@jigarpandya-techholding
Copy link

@marcbaechinger thanks for the clarity. the two conditions that you mention about stopping the service make sense. In my case, even on paused state, on dismissing the app doesn't remove the notification implies that any controller is not disconnected yet ? then trying to play the media from notification results in ForegroundServiceDidNotStartInTimeException.

@marcbaechinger marcbaechinger changed the title Swiping demo-session app out from recents on Android 14 results in a dead notification onTaskRemoved not called app dismmised from recent taks on Android 14 Feb 8, 2024
@marcbaechinger marcbaechinger changed the title onTaskRemoved not called app dismmised from recent taks on Android 14 onTaskRemoved not called app dismmised from recent tasks on Android 14 Feb 8, 2024
@marcbaechinger marcbaechinger changed the title onTaskRemoved not called app dismmised from recent tasks on Android 14 onTaskRemoved not called when app dismissed from recent tasks on Android 14 Feb 8, 2024
@marcbaechinger
Copy link
Contributor

I'd guess so yes, but I can't know with the available information. #1059 is about the same thing and may be interesting for you.

@nift4
Copy link

nift4 commented Feb 15, 2024

I was able to work around this issue with this code (simplified version):

         handler.post {
            if (willDie) {
                if (Build.VERSION.SDK_INT != Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
                    throw NullPointerException("this code path should never be reachable")
                }
                // Android 14 bug.
                // https://github.com/androidx/media/issues/805
                // In Android 13:
                // 1. Service starts
                // 2. UI thread moves on to this call
                // 3. Some time later, user swipes away app (while music paused)
                // 4. onTaskRemoved() calls stopSelf()
                // 5. onDestroy() called, happy ending
                // In Android 14:
                // 1. Service starts
                // 2. UI thread moves on to this call
                // 3. Some time later, user swipes away app (while music paused)
                // 4. App process killed, notification abandoned
                // 5. App process restarted
                // 6. instantly, onTaskRemoved() calls stopSelf()
                // 7. This is called (and because we are after onTaskRemoved, willDie is true)
                // 8. onDestroy() called
                // To workaround this, we cancel notification here and let service die peacefully
                val nm = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
                nm.cancel(DefaultMediaNotificationProvider.DEFAULT_NOTIFICATION_ID)
                return@post
            }
       }

in onCreate()

and this in onTaskRemoved():

    override fun onTaskRemoved(rootIntent: Intent?) {
        if (!mediaSession!!.player.playWhenReady || mediaSession!!.player.mediaItemCount == 0) {
            willDie = true // a14 bug workaround
            stopSelf()
        }
    }

intermarc added a commit to dharmaseed/dharmaseed-android that referenced this issue Apr 21, 2024
This merge pulls in changes that were made to fix the "App Not
Responding" issues that we have been seeing in production. Apart from
updating to the latest release of the media3 library, the changes
concern two ways in which the new `PlaybackService` works.

**Retrieval of the MediaController**
Our ANR problem has been discussed in
[this](androidx/media#890) open issue. There
was a very helpful response regarding what might be done. In particular,
the suggestions were:

1. Using `Futures.addCallback()` instead of
`controllerFuture.addListener()`
2. Using `MoreExecutors.directExecutor()` instead of
`ContextCompat.getMainExecutor()`

Both of these were implemented in
403c480

**Stopping the `MediaSessionService` when the app is killed in the
background**
Another potential source of ANRs and crashes was described in [this
issue](androidx/media#805), which applies to
our app as well. I've also been able to reproduce a similar and perhaps
directly related issue on a phone running an older version of android
(see the video in #99).

To limit the scope of the changes in this pull request, I've opted for
the simple solution of ending the `MediaSessionService` when the app is
closed in the background (see c980064).
With this change, the media notification no longer "hangs around" when
the app is stopped in the background, thereby preventing this kind of
issue.

The disadvantage of this approach is that the media notification is gone
and the user has to explicitly re-start the app and find the right talk
to continue listening. I've created the branch `playback_resumption` to
implement a more satisfactory solution (following the [official
documentation](https://developer.android.com/media/media3/session/background-playback#resumption)).
@patryk84a
Copy link

patryk84a commented Sep 25, 2024

Jeśli mi się uda, obejść ten problem, za pomocą wyjaśnionego kodu (wersja uproszczona):

         handler.post {
            if (willDie) {
                if (Build.VERSION.SDK_INT != Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
                    throw NullPointerException("this code path should never be reachable")
                }
                // Android 14 bug.
                // https://github.com/androidx/media/issues/805
                // In Android 13:
                // 1. Service starts
                // 2. UI thread moves on to this call
                // 3. Some time later, user swipes away app (while music paused)
                // 4. onTaskRemoved() calls stopSelf()
                // 5. onDestroy() called, happy ending
                // In Android 14:
                // 1. Service starts
                // 2. UI thread moves on to this call
                // 3. Some time later, user swipes away app (while music paused)
                // 4. App process killed, notification abandoned
                // 5. App process restarted
                // 6. instantly, onTaskRemoved() calls stopSelf()
                // 7. This is called (and because we are after onTaskRemoved, willDie is true)
                // 8. onDestroy() called
                // To workaround this, we cancel notification here and let service die peacefully
                val nm = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
                nm.cancel(DefaultMediaNotificationProvider.DEFAULT_NOTIFICATION_ID)
                return@post
            }
       }

w onCreate()

i do w onTaskRemoved():

    override fun onTaskRemoved(rootIntent: Intent?) {
        if (!mediaSession!!.player.playWhenReady || mediaSession!!.player.mediaItemCount == 0) {
            willDie = true // a14 bug workaround
            stopSelf()
        }
    }

On Android 14 in Chinese POCO, the problem of not calling onTaskRemoved still exists. When playback is stopped and the app is removed from the recent list, the onTaskRemoved method is not called at all. That's why your fix won't work, because onTaskRemoved is not called. I wanted to solve the problem by adding a method to my activity in the onDestroy event that removes MediaItems from the Player. Then the service would go to the background and be killed after some time. I just don't know why it doesn't work:

 @Override
  public void onDestroy() {
    if(!mediaBrowser.isPlaying()) {
      mediaBrowser.clearMediaItems();
      mediaBrowser.release();
    }
    MediaBrowser.releaseFuture(browserFuture);  
  }

Edit: Instead of onDestroy I used onStop and the code started working. When playback is stopped and the application goes to the background, MediaItems are removed. The notification disappears, the service goes to the background. After a while, the service is killed by the system.

@lovegaoshi
Copy link

I just spent a frustrating day on this exact issue, and #843 (comment) resolved it for me. as a result I see a gazillion onStartCommand calls with a null intent, but I guess its not too bad.

I've followed most stale notification issues and its similar to another fella (I cant find anymore) with the same Scheduling restart of crashed service. I'm deducing that it might be related to a onTrimMemory(40) event, but really no clue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants