On Android 14+ (targetSdk 34) the app could fail to run at all on newer devices
(Pixel 10, onn HD stick). Root cause: the always-on WebSocketService called the
2-arg startForeground(), which claims EVERY foreground-service type declared in
the manifest - including mediaProjection. Android 14 rejects starting a
mediaProjection-typed FGS without a MediaProjection consent token, so the core
service threw on launch and the player never came up. Matches the reporter's
"screen recording policy" hunch - via the FGS type, not the capture trigger.
Fixes:
- WebSocketService now claims ONLY mediaPlayback (explicit
startForeground(..., FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK), API>=29 guarded;
2-arg on older). Manifest type narrowed to mediaPlayback.
- New MediaProjectionService (manifest type mediaProjection), started only AFTER
the user grants consent. It enters the foreground with the mediaProjection type
BEFORE getMediaProjection() (required on 14+), then drives ScreenCaptureService.
The consent Activity now hands the result to this service instead of calling
getMediaProjection() directly (an Activity can't hold that FGS type).
- ScreenCaptureService: register the MediaProjection.Callback BEFORE
createVirtualDisplay() (Android 14 throws IllegalStateException otherwise).
Verified: Kotlin compiles, manifest merges (WebSocketService=mediaPlayback,
MediaProjectionService=mediaProjection), signed debug APK builds. NOT yet
verified on-device - needs a Pixel 10 / onn-stick run + logcat to confirm the
exact crash is resolved.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ScreenTinker - open source digital signage management software.
MIT License, all features included, no license gates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>