feat(android): MinstrelPlayerService — Media3 MediaSessionService (M8 phase 6.2)

The actual replacement for everything audio_service plugin wrapped.
Media3 owns the foreground-service lifecycle, MediaSession token,
notification card, lock-screen surface, Bluetooth/AVRCP routing,
Pixel Watch tile, and Android Auto adapter natively — no plugin
layer between us and the platform.

Service shape (~25 LOC):
  - @AndroidEntryPoint MediaSessionService
  - @Inject PlayerFactory builds ExoPlayer in onCreate
  - onGetSession returns the live MediaSession to any binding
    controller (system UI, Wear OS companion, MediaController3 clients)
  - onTaskRemoved keeps playing while audio is active (standard
    media-app behavior); otherwise stopSelf so notification clears
  - onDestroy releases session + player

Compare with flutter_client/lib/player/audio_handler.dart's 1000+ LOC
across MinstrelAudioHandler + the soft-teardown / stall-watchdog /
recovery machinery. Media3 owns most of that natively; we'll get to
the small portions we still need (queue management, position
reporting facade) in 6.3.

Manifest registration: foregroundServiceType="mediaPlayback" +
MediaSessionService intent-filter. MediaButtonReceiver is registered
by the Media3 library; no manual receiver class needed (Flutter's
manifest had to declare audio_service's receiver explicitly).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-23 12:26:47 -04:00
parent 327ecb6757
commit 85b8452b78
2 changed files with 72 additions and 1 deletions
+8 -1
View File
@@ -31,6 +31,13 @@
</intent-filter>
</activity>
<!-- Media3 MediaSessionService is registered in Phase 6 (Task 6.2). -->
<service
android:name=".player.MinstrelPlayerService"
android:exported="true"
android:foregroundServiceType="mediaPlayback">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService" />
</intent-filter>
</service>
</application>
</manifest>