2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00
2026-05-18 09:37:50 +01:00

OpenVinyl — Flutter (Android)

A free clone of the OpenVinyl turntable visualizer for Android.

Project Structure

lib/
  main.dart                   ← App entry, permission check
  models/
    media_info.dart           ← Data class for now-playing track
  services/
    media_service.dart        ← Platform channel bridge (Flutter side)
  screens/
    player_screen.dart        ← Main turntable screen
    permission_screen.dart    ← Shown if Notification Access not granted
  widgets/
    vinyl_record.dart         ← Spinning record with album art + grooves
    tonearm.dart              ← Animated needle arm

android/app/src/main/
  kotlin/pt/ruifpb/openvinyl/
    MainActivity.kt           ← Platform channel setup (MethodChannel + EventChannel)
    MediaListenerService.kt   ← NotificationListenerService reads now-playing data
  res/xml/
    notification_listener_service.xml
  AndroidManifest.xml         ← Service declaration with BIND_NOTIFICATION_LISTENER

Setup

1. Package name

By default the package is pt.ruifpb.openvinyl. If you want to change it:

  • Update the package line in both .kt files
  • Update applicationId in android/app/build.gradle
  • Update the directory path under kotlin/

2. Install dependencies

flutter pub get

3. Run

flutter run

On first launch the app will show a permission screen. Tap Open Settings, find OpenVinyl in the Notification Listener list, and enable it. Return to the app — it will detect the change automatically.


Adding Home Screen Widgets (later)

The code is pre-wired for this. When you're ready:

  1. Uncomment the home_widget import and _pushToWidget() call in lib/services/media_service.dart
  2. Create a Glance widget in Kotlin: android/app/src/main/kotlin/pt/ruifpb/openvinyl/VinylWidgetReceiver.kt
  3. Add the <receiver> block in AndroidManifest.xml (stub already in the file)
  4. Add widget info XML at android/app/src/main/res/xml/vinyl_widget_info.xml

The home_widget package (already in pubspec.yaml) handles the Flutter ↔ widget data bridge via HomeWidget.saveWidgetData() and HomeWidget.updateWidget().


How the Notification Listener Works

MediaListenerService extends Android's NotificationListenerService. When any app posts a notification that carries a MediaSession.Token extra (Spotify, YouTube Music, Podcast apps, etc.), the service:

  1. Creates a MediaController from the token
  2. Reads metadata (title, artist, album art bitmap) and playback state
  3. Serialises the bitmap to JPEG bytes
  4. Pushes a Map through the EventChannel to Flutter

Flutter's MediaService receives the map, deserialises it into a MediaInfo object, and re-broadcasts it to any listener (currently PlayerScreen).

S
Description
A free spinning vinyl app that syncs with the music currently playing on your phone.
Readme 734 KiB
Languages
Dart 44.6%
Kotlin 32.9%
CMake 11.5%
C++ 7.2%
Swift 2.8%
Other 0.9%