Commits
506157f
.forgejo
app
gradle
.dockerignore 459 B
.gitignore 102 B
build.gradle.kts 343 B
Dockerfile 4.8 KiB
gradle.properties 136 B
gradlew 8.5 KiB
gradlew.bat 2.8 KiB
LICENSE.md 33.9 KiB
README.md 3.5 KiB
settings.gradle.kts 533 B

Scropple (Android)

CI status latest release license install org.neiam.scropple.app top language

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.

Build & run

./gradlew :app:assembleDebug            # build debug APK
./gradlew :app:installDebug             # install on a connected device/emulator
./gradlew :app:testDebugUnitTest        # run the timing-engine unit tests

APK: app/build/outputs/apk/debug/app-debug.apk. Requires local.properties with sdk.dir=... (already present).

First-run setup

  1. 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.
  2. Backends → Add → configure Last.fm / ListenBrainz / HTTP.
  3. 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_SECRET in backend/LastfmBackend.kt (register at https://www.last.fm/api/account/create).

Architecture

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)

Status

  • M1 detection — built, verified on device.
  • M2 timing engine — built, 6 unit tests passing (ScrobbleSessionTest).
  • M3 Last.fm — built; needs API credentials plugged in (see above).
  • M4 queue/retry — built (Room + WorkManager).
  • M5 ListenBrainz + HTTP — built; fan-out to all enabled backends.
  • M6 UI — built (functional, not yet polished).

Known gaps / next steps

  • 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.