Reads media playback via the system MediaSessionManager and scrobbles to
Last.fm, ListenBrainz, and any number of custom HTTP backends. Kotlin ·
Jetpack Compose · Room · WorkManager.
./gradlew :app:assembleDebug # build debug APK
./gradlew :app:installDebug # install on a connected device/emulator
./gradlew :app:testDebugUnitTest # run the timing-engine unit testsAPK: app/build/outputs/apk/debug/app-debug.apk. Requires local.properties
with sdk.dir=... (already present).
- Launch the app → Home → Grant access → enable Scropple under the
system Notification access screen. This is what unlocks
MediaSessionManager; it cannot be granted programmatically. Scropple does not read notification content — only structured media metadata. - Backends → Add → configure Last.fm / ListenBrainz / HTTP.
- Play music in any audio app; Home shows now-playing, History shows the queue (pending vs delivered).
Last.fm needs app credentials: set
API_KEY/API_SECRETinbackend/LastfmBackend.kt(register at https://www.last.fm/api/account/create).
| Package | Role |
|---|---|
service |
ScroppleListenerService (notification-listener) + MediaSessionWatcher — detection (M1) |
engine |
Track, AppFilter (video filtering), ScrobbleSession/ScrobbleEngine — timing state machine (M2) |
backend |
ScrobblerBackend + Last.fm / ListenBrainz / HTTP impls, BackendRegistry, Dispatcher (M3, M5) |
data |
Room dispatch queue, BackendConfigStore (encrypted), AppPrefsStore (M4) |
work |
QueueDrainWorker — offline retry with backoff (M4) |
ui |
Compose screens: Home / Backends / History / Settings (M6) |
- M1 detection — built (needs on-device verification of the grant + session callbacks).
- M2 timing engine — built, 6 unit tests passing (
ScrobbleSessionTest). - M3 Last.fm — built; plug in API credentials and verify auth on device.
- M4 queue/retry — built (Room + WorkManager).
- M5 ListenBrainz + HTTP — built; fan-out to all enabled backends.
- M6 UI — built (functional, not yet polished).
- Verify end-to-end on a physical device (emulators rarely run real players).
- Last.fm web-auth token flow (currently username/password
getMobileSession). - Per-app allow/deny UI lists running players (Settings shows the deny-list only).
- OEM battery-optimization guidance. An opt-in persistent (IMPORTANCE_MIN) status notification exists (Settings → "Persistent notification"); promoting it to a true foreground service would further help survival on aggressive OEMs.
- Spotify metadata edge-cases; podcast/audiobook filtering.