Skip to content

Refactor listening stats tracking to MusicService#1976

Merged
theovilardo merged 1 commit into
masterfrom
impr/listening-stats-improvements
May 12, 2026
Merged

Refactor listening stats tracking to MusicService#1976
theovilardo merged 1 commit into
masterfrom
impr/listening-stats-improvements

Conversation

@theovilardo

Copy link
Copy Markdown
Collaborator

Moves the responsibility of tracking listening statistics from the PlayerViewModel and UI state holders to MusicService. This ensures more accurate tracking that persists independently of the UI lifecycle and centralizes logic for both local and remote (Cast) playback.

  • Refactors ListeningStatsTracker to be thread-safe using @Synchronized and decouples it from the Song data model by using songId.
  • Introduces ensureSession and onTrackChanged in ListeningStatsTracker to handle state synchronization more robustly.
  • Implements syncLocalListeningStatsFromPlayer in MusicService to update tracking state based on Media3 Player.Listener events.
  • Adds syncCastListeningStatsFromRemote to MusicService to support listening stats for Cast sessions via RemoteMediaClient callbacks.
  • Removes ListeningStatsTracker dependencies and manual progress reporting from PlayerViewModel, PlaybackStateHolder, and CastTransferStateHolder.
  • Ensures listening sessions are finalized in MusicService.onDestroy.

Moves the responsibility of tracking listening statistics from the `PlayerViewModel` and UI state holders to `MusicService`. This ensures more accurate tracking that persists independently of the UI lifecycle and centralizes logic for both local and remote (Cast) playback.

- Refactors `ListeningStatsTracker` to be thread-safe using `@Synchronized` and decouples it from the `Song` data model by using `songId`.
- Introduces `ensureSession` and `onTrackChanged` in `ListeningStatsTracker` to handle state synchronization more robustly.
- Implements `syncLocalListeningStatsFromPlayer` in `MusicService` to update tracking state based on Media3 `Player.Listener` events.
- Adds `syncCastListeningStatsFromRemote` to `MusicService` to support listening stats for Cast sessions via `RemoteMediaClient` callbacks.
- Removes `ListeningStatsTracker` dependencies and manual progress reporting from `PlayerViewModel`, `PlaybackStateHolder`, and `CastTransferStateHolder`.
- Ensures listening sessions are finalized in `MusicService.onDestroy`.
@theovilardo theovilardo merged commit 8882006 into master May 12, 2026
4 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cddca23ef0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 277 to 279
persistenceScope.launch {
runCatching {
persistPlaybackInternal(songId = songId, listened = listened, timestamp = timestamp)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor forced persistence before returning

When MusicService.onDestroy()/unload calls finalizeCurrentSession(forceSynchronousPersistence = true), the forced flag now reaches this method but is explicitly ignored and the write is only enqueued on persistenceScope. In those shutdown paths Android can tear down the service/process before the launched coroutine records the final session, so the last play can be missing from engagement/history even though callers asked for synchronous persistence; the forced path should block or otherwise await the write before returning.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant