This PR migrates the Android playback/session integration from ExoPlayer 2.18.7 to Media3 1.9.2 and
updates the affected APIs to the current Media3 equivalents while preserving the current playback
behavior.
Which issue is fixed?
No existing issue found for this Media3 migration.
Pull Request Type
Android only.
This change affects the native Android player/session integration layer. It does not change the
backend.
In-depth Description
This PR migrates the Android player/session layer from ExoPlayer 2.18.7 to Media3 1.9.2.
The main changes are:
Replaced ExoPlayer package usage with the corresponding Media3 APIs in the player/session layer.
Moved the media session integration from the older compat / connector-style setup to the Media3
session model.
Updated custom playback actions and session button handling to use the current Media3 APIs.
Updated cast volume handling and CastPlayer command declarations to match the current Media3 Player API.
Preserved the playback speed action and restored the speed-specific icon using supported Media3
custom icon APIs.
Added a short code comment clarifying that Media3 now owns the real session callback and the
legacy MediaSessionCallback class is only used as a helper for media button intent handling.
The main reason for this change is long-term support and maintainability of the Android playback
stack. ExoPlayer has moved into AndroidX Media3, and ongoing player/session development is happening
there. Staying on ExoPlayer 2.18.7 would make future maintenance harder, while Media3 1.9.2 provides
the current API surface for player control, sessions, custom commands, casting, and Android Auto
integration.
Media3 continues the ExoPlayer codebase, but several APIs have changed shape during the move,
especially around sessions, command handling, controller integration, and custom actions. This PR
updates those parts so the app is using the supported Media3 model instead of staying on the older
ExoPlayer integration pattern.
In practice, this PR helps in a few ways:
It moves the app onto the supported AndroidX Media3 playback/session APIs.
It keeps custom playback actions, cast volume handling, and Android Auto integration aligned with
the newer Media3 command model.
It preserves the playback speed action behavior, including the speed-specific icon, while using
the supported Media3 button API.
It reduces future upgrade risk by removing migration-related deprecated API usage introduced while
porting the playback stack.
It reduces build noise by removing deprecated player/session APIs that would otherwise keep
showing up during Gradle builds and make real regressions harder to spot.
It simplifies future Gradle and dependency maintenance because the playback layer is no longer
split across old ExoPlayer-era integration patterns and newer AndroidX Media3 ones.
It keeps the project aligned with the actively maintained Android media stack, which is important
for future fixes and behavior changes around notifications, media sessions, controller
interactions, casting, and Android Auto.
It removes some migration friction in the player code by standardizing on one session/control
model instead of carrying both the old connector-oriented approach and the newer Media3 callback
model.
This is not an edge case change. These code paths affect normal playback controls, media buttons,
cast playback, notifications / lockscreen controls, and Android Auto behavior for Android users.
How have you tested this?
On the Now Playing screen, verified:
Play / pause works
Jump backward works
Jump forward works
Skip previous / next works for multi-track playback
clicking the playback speed button repeatedly and validate:
the playback speed changes as expected
the speed button icon updates to match the current speed
Leave the app and use the Android notification / lockscreen media controls. Verify:
Play / pause works
Jump backward / jump forward works
the playback session stays in sync with the app
Open a podcast episode details screen and start podcast playback. Confirm the same playback
controls still behave correctly there.
Start playback, connect to a cast device from the player controls, and verify:
cast playback starts successfully
cast volume controls work
switching between local playback and cast playback keeps the session usable
Screenshots
No UI layout changes. Optional screenshot/video can be added showing the playback speed action icon
updating in the Android media controls.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.
## 📋 Pull Request Information
**Original PR:** https://github.com/advplyr/audiobookshelf-app/pull/1839
**Author:** [@isink17](https://github.com/isink17)
**Created:** 3/31/2026
**Status:** 🔄 Open
**Base:** `master` ← **Head:** `chore/media3-migration-cleanup`
---
### 📝 Commits (1)
- [`a5cb3ce`](https://github.com/advplyr/audiobookshelf-app/commit/a5cb3ce61ba908d8a5bdcd5c50804fd04b4e31e6) android: Media3 migration cleanup
### 📊 Changes
**15 files changed** (+366 additions, -590 deletions)
<details>
<summary>View changed files</summary>
📝 `android/app/build.gradle` (+8 -14)
📝 `android/app/src/main/java/com/audiobookshelf/app/data/PlaybackSession.kt` (+2 -2)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/AbMediaDescriptionAdapter.kt` (+26 -14)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/CastManager.kt` (+4 -1)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/CastPlayer.kt` (+106 -55)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/CastTimeline.kt` (+3 -4)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/CastTimelineTracker.kt` (+1 -1)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/CastTrackSelection.kt` (+8 -5)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt` (+3 -143)
➖ `android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionPlaybackPreparer.kt` (+0 -93)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/PlayerListener.kt` (+2 -2)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationListener.kt` (+4 -1)
📝 `android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt` (+198 -249)
📝 `android/app/src/main/java/com/audiobookshelf/app/plugins/AbsDatabase.kt` (+0 -5)
📝 `android/variables.gradle` (+1 -1)
</details>
### 📄 Description
## Brief summary
This PR migrates the Android playback/session integration from ExoPlayer 2.18.7 to Media3 1.9.2 and
updates the affected APIs to the current Media3 equivalents while preserving the current playback
behavior.
## Which issue is fixed?
No existing issue found for this Media3 migration.
## Pull Request Type
Android only.
This change affects the native Android player/session integration layer. It does not change the
backend.
## In-depth Description
This PR migrates the Android player/session layer from ExoPlayer 2.18.7 to Media3 1.9.2.
The main changes are:
- Replaced ExoPlayer package usage with the corresponding Media3 APIs in the player/session layer.
- Moved the media session integration from the older compat / connector-style setup to the Media3
session model.
- Updated custom playback actions and session button handling to use the current Media3 APIs.
- Updated cast volume handling and `CastPlayer` command declarations to match the current Media3
`Player` API.
- Preserved the playback speed action and restored the speed-specific icon using supported Media3
custom icon APIs.
- Added a short code comment clarifying that Media3 now owns the real session callback and the
legacy `MediaSessionCallback` class is only used as a helper for media button intent handling.
The main reason for this change is long-term support and maintainability of the Android playback
stack. ExoPlayer has moved into AndroidX Media3, and ongoing player/session development is happening
there. Staying on ExoPlayer 2.18.7 would make future maintenance harder, while Media3 1.9.2 provides
the current API surface for player control, sessions, custom commands, casting, and Android Auto
integration.
Media3 continues the ExoPlayer codebase, but several APIs have changed shape during the move,
especially around sessions, command handling, controller integration, and custom actions. This PR
updates those parts so the app is using the supported Media3 model instead of staying on the older
ExoPlayer integration pattern.
In practice, this PR helps in a few ways:
- It moves the app onto the supported AndroidX Media3 playback/session APIs.
- It keeps custom playback actions, cast volume handling, and Android Auto integration aligned with
the newer Media3 command model.
- It preserves the playback speed action behavior, including the speed-specific icon, while using
the supported Media3 button API.
- It reduces future upgrade risk by removing migration-related deprecated API usage introduced while
porting the playback stack.
- It reduces build noise by removing deprecated player/session APIs that would otherwise keep
showing up during Gradle builds and make real regressions harder to spot.
- It simplifies future Gradle and dependency maintenance because the playback layer is no longer
split across old ExoPlayer-era integration patterns and newer AndroidX Media3 ones.
- It keeps the project aligned with the actively maintained Android media stack, which is important
for future fixes and behavior changes around notifications, media sessions, controller
interactions, casting, and Android Auto.
- It removes some migration friction in the player code by standardizing on one session/control
model instead of carrying both the old connector-oriented approach and the newer Media3 callback
model.
This is not an edge case change. These code paths affect normal playback controls, media buttons,
cast playback, notifications / lockscreen controls, and Android Auto behavior for Android users.
## How have you tested this?
1. On the Now Playing screen, verified:
- Play / pause works
- Jump backward works
- Jump forward works
- Skip previous / next works for multi-track playback
- clicking the playback speed button repeatedly and validate:
- the playback speed changes as expected
- the speed button icon updates to match the current speed
2. Leave the app and use the Android notification / lockscreen media controls. Verify:
- Play / pause works
- Jump backward / jump forward works
- the playback session stays in sync with the app
3. Open a podcast episode details screen and start podcast playback. Confirm the same playback
controls still behave correctly there.
4. Start playback, connect to a cast device from the player controls, and verify:
- cast playback starts successfully
- cast volume controls work
- switching between local playback and cast playback keeps the session usable
## Screenshots
No UI layout changes. Optional screenshot/video can be added showing the playback speed action icon
updating in the Android media controls.
---
<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/advplyr/audiobookshelf-app/pull/1839
Author: @isink17
Created: 3/31/2026
Status: 🔄 Open
Base:
master← Head:chore/media3-migration-cleanup📝 Commits (1)
a5cb3ceandroid: Media3 migration cleanup📊 Changes
15 files changed (+366 additions, -590 deletions)
View changed files
📝
android/app/build.gradle(+8 -14)📝
android/app/src/main/java/com/audiobookshelf/app/data/PlaybackSession.kt(+2 -2)📝
android/app/src/main/java/com/audiobookshelf/app/player/AbMediaDescriptionAdapter.kt(+26 -14)📝
android/app/src/main/java/com/audiobookshelf/app/player/CastManager.kt(+4 -1)📝
android/app/src/main/java/com/audiobookshelf/app/player/CastPlayer.kt(+106 -55)📝
android/app/src/main/java/com/audiobookshelf/app/player/CastTimeline.kt(+3 -4)📝
android/app/src/main/java/com/audiobookshelf/app/player/CastTimelineTracker.kt(+1 -1)📝
android/app/src/main/java/com/audiobookshelf/app/player/CastTrackSelection.kt(+8 -5)📝
android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt(+3 -143)➖
android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionPlaybackPreparer.kt(+0 -93)📝
android/app/src/main/java/com/audiobookshelf/app/player/PlayerListener.kt(+2 -2)📝
android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationListener.kt(+4 -1)📝
android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt(+198 -249)📝
android/app/src/main/java/com/audiobookshelf/app/plugins/AbsDatabase.kt(+0 -5)📝
android/variables.gradle(+1 -1)📄 Description
Brief summary
This PR migrates the Android playback/session integration from ExoPlayer 2.18.7 to Media3 1.9.2 and
updates the affected APIs to the current Media3 equivalents while preserving the current playback
behavior.
Which issue is fixed?
No existing issue found for this Media3 migration.
Pull Request Type
Android only.
This change affects the native Android player/session integration layer. It does not change the
backend.
In-depth Description
This PR migrates the Android player/session layer from ExoPlayer 2.18.7 to Media3 1.9.2.
The main changes are:
session model.
CastPlayercommand declarations to match the current Media3PlayerAPI.custom icon APIs.
legacy
MediaSessionCallbackclass is only used as a helper for media button intent handling.The main reason for this change is long-term support and maintainability of the Android playback
stack. ExoPlayer has moved into AndroidX Media3, and ongoing player/session development is happening
there. Staying on ExoPlayer 2.18.7 would make future maintenance harder, while Media3 1.9.2 provides
the current API surface for player control, sessions, custom commands, casting, and Android Auto
integration.
Media3 continues the ExoPlayer codebase, but several APIs have changed shape during the move,
especially around sessions, command handling, controller integration, and custom actions. This PR
updates those parts so the app is using the supported Media3 model instead of staying on the older
ExoPlayer integration pattern.
In practice, this PR helps in a few ways:
the newer Media3 command model.
the supported Media3 button API.
porting the playback stack.
showing up during Gradle builds and make real regressions harder to spot.
split across old ExoPlayer-era integration patterns and newer AndroidX Media3 ones.
for future fixes and behavior changes around notifications, media sessions, controller
interactions, casting, and Android Auto.
model instead of carrying both the old connector-oriented approach and the newer Media3 callback
model.
This is not an edge case change. These code paths affect normal playback controls, media buttons,
cast playback, notifications / lockscreen controls, and Android Auto behavior for Android users.
How have you tested this?
controls still behave correctly there.
Screenshots
No UI layout changes. Optional screenshot/video can be added showing the playback speed action icon
updating in the Android media controls.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.