From 2eb9c7491d9062cd063983acd981a7e7c3af3434 Mon Sep 17 00:00:00 2001
From: fadyphil
Date: Wed, 18 Mar 2026 00:40:17 +0200
Subject: [PATCH 1/3] feat(android): implement home screen music widget
Adds a native Android Home Screen Widget with real-time state synchronization.
- Implements native MusicPlayerWidget extending HomeWidgetProvider.
- Integrates WidgetSyncService for Flutter-to-native state bridging.
- Enhances AudioHandler with library cold-start playback capability.
- Adds native RemoteViews layout matching the app's dark theme.
- Handles playback controls (play/pause, next, previous) via native MediaKey dispatch and HomeWidget interactivity.
---
android/app/src/main/AndroidManifest.xml | 20 +++
.../com/osserva/app/MusicPlayerWidget.kt | 132 ++++++++++++++++++
.../src/main/res/drawable/art_rounded_bg.xml | 5 +
.../src/main/res/drawable/ic_default_art.xml | 10 ++
.../app/src/main/res/drawable/ic_pause.xml | 11 ++
android/app/src/main/res/drawable/ic_play.xml | 10 ++
.../src/main/res/drawable/ic_play_arrow.xml | 11 ++
.../src/main/res/drawable/ic_skip_next.xml | 11 ++
.../main/res/drawable/ic_skip_previous.xml | 11 ++
.../src/main/res/drawable/play_button_bg.xml | 5 +
.../main/res/drawable/widget_background.xml | 5 +
.../app/src/main/res/layout/music_widget.xml | 105 ++++++++++++++
android/app/src/main/res/values/strings.xml | 5 +
.../src/main/res/xml/music_widget_info.xml | 12 ++
lib/core/di/init_dependencies.dart | 37 +++--
lib/core/di/modules/music_player_module.dart | 3 +-
lib/core/os_widget/os_widget_manager.dart | 24 ++++
lib/core/services/widget_sync_service.dart | 125 +++++++++++++++++
.../data/datasources/audio_handler.dart | 44 +++++-
lib/main.dart | 4 +-
pubspec.lock | 10 +-
pubspec.yaml | 2 +
22 files changed, 584 insertions(+), 18 deletions(-)
create mode 100644 android/app/src/main/kotlin/com/osserva/app/MusicPlayerWidget.kt
create mode 100644 android/app/src/main/res/drawable/art_rounded_bg.xml
create mode 100644 android/app/src/main/res/drawable/ic_default_art.xml
create mode 100644 android/app/src/main/res/drawable/ic_pause.xml
create mode 100644 android/app/src/main/res/drawable/ic_play.xml
create mode 100644 android/app/src/main/res/drawable/ic_play_arrow.xml
create mode 100644 android/app/src/main/res/drawable/ic_skip_next.xml
create mode 100644 android/app/src/main/res/drawable/ic_skip_previous.xml
create mode 100644 android/app/src/main/res/drawable/play_button_bg.xml
create mode 100644 android/app/src/main/res/drawable/widget_background.xml
create mode 100644 android/app/src/main/res/layout/music_widget.xml
create mode 100644 android/app/src/main/res/values/strings.xml
create mode 100644 android/app/src/main/res/xml/music_widget_info.xml
create mode 100644 lib/core/os_widget/os_widget_manager.dart
create mode 100644 lib/core/services/widget_sync_service.dart
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index b6583e8..5820306 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -52,6 +52,12 @@
+
+
+
+
+
+
@@ -65,6 +71,20 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/com/osserva/app/MusicPlayerWidget.kt b/android/app/src/main/kotlin/com/osserva/app/MusicPlayerWidget.kt
new file mode 100644
index 0000000..fd8423a
--- /dev/null
+++ b/android/app/src/main/kotlin/com/osserva/app/MusicPlayerWidget.kt
@@ -0,0 +1,132 @@
+package com.osserva.app
+
+import android.appwidget.AppWidgetManager
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
+import android.graphics.BitmapFactory
+import android.media.AudioManager
+import android.net.Uri
+import android.os.SystemClock
+import android.view.KeyEvent
+import android.widget.RemoteViews
+import android.app.PendingIntent
+import es.antonborri.home_widget.HomeWidgetProvider
+import es.antonborri.home_widget.HomeWidgetLaunchIntent
+
+class MusicPlayerWidget : HomeWidgetProvider() {
+
+ companion object {
+ private const val ACTION_PLAY_PAUSE = "com.osserva.app.WIDGET_PLAY_PAUSE"
+ private const val ACTION_NEXT = "com.osserva.app.WIDGET_NEXT"
+ private const val ACTION_PREV = "com.osserva.app.WIDGET_PREV"
+ }
+
+ override fun onUpdate(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetIds: IntArray,
+ widgetData: SharedPreferences
+ ) {
+ for (widgetId in appWidgetIds) {
+ updateWidget(context, appWidgetManager, widgetId, widgetData)
+ }
+ }
+
+ override fun onReceive(context: Context, intent: Intent) {
+ super.onReceive(context, intent)
+ when (intent.action) {
+ ACTION_PLAY_PAUSE -> dispatchMediaKey(context, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)
+ ACTION_NEXT -> dispatchMediaKey(context, KeyEvent.KEYCODE_MEDIA_NEXT)
+ ACTION_PREV -> dispatchMediaKey(context, KeyEvent.KEYCODE_MEDIA_PREVIOUS)
+ }
+ }
+
+ private fun updateWidget(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ widgetId: Int,
+ widgetData: SharedPreferences
+ ) {
+ val title = widgetData.getString("song_title", "") ?: ""
+ val artist = widgetData.getString("artist", "") ?: ""
+ val isPlaying = widgetData.getBoolean("is_playing", false)
+ val isShuffle = widgetData.getBoolean("is_shuffle", false)
+ val artPath = widgetData.getString("art_path", "") ?: ""
+
+ val views = RemoteViews(context.packageName, R.layout.music_widget)
+
+ // Text
+ views.setTextViewText(R.id.widget_song_title, if (title.isEmpty()) "Not Playing" else title)
+ views.setTextViewText(R.id.widget_artist, artist)
+
+ // Album art
+ if (artPath.isNotEmpty()) {
+ val bitmap = BitmapFactory.decodeFile(artPath)
+ if (bitmap != null) {
+ views.setImageViewBitmap(R.id.widget_album_art, bitmap)
+ } else {
+ views.setImageViewResource(R.id.widget_album_art, R.drawable.ic_default_art)
+ }
+ } else {
+ views.setImageViewResource(R.id.widget_album_art, R.drawable.ic_default_art)
+ }
+
+ // Play/Pause icon
+ val playPauseIcon = if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play
+ views.setImageViewResource(R.id.widget_btn_play_pause, playPauseIcon)
+
+ // Shuffle tint (active = accent color, inactive = white with opacity)
+ val shuffleTint = if (isShuffle) 0xFF1DB954.toInt() else 0x99FFFFFF.toInt()
+ views.setInt(R.id.widget_btn_shuffle, "setColorFilter", shuffleTint)
+
+ // Button intents
+ views.setOnClickPendingIntent(
+ R.id.widget_btn_play_pause,
+ broadcastIntent(context, ACTION_PLAY_PAUSE, widgetId),
+ )
+ views.setOnClickPendingIntent(
+ R.id.widget_btn_next,
+ broadcastIntent(context, ACTION_NEXT, widgetId),
+ )
+ views.setOnClickPendingIntent(
+ R.id.widget_btn_prev,
+ broadcastIntent(context, ACTION_PREV, widgetId),
+ )
+ // Shuffle -> launches Flutter via HomeWidget URI
+ views.setOnClickPendingIntent(
+ R.id.widget_btn_shuffle,
+ shuffleLaunchIntent(context),
+ )
+
+ appWidgetManager.updateAppWidget(widgetId, views)
+ }
+
+ private fun broadcastIntent(context: Context, action: String, widgetId: Int): PendingIntent {
+ val intent = Intent(context, MusicPlayerWidget::class.java).apply {
+ this.action = action
+ }
+ return PendingIntent.getBroadcast(
+ context,
+ widgetId,
+ intent,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
+ )
+ }
+
+ private fun shuffleLaunchIntent(context: Context): PendingIntent {
+ val intent = HomeWidgetLaunchIntent.getActivity(
+ context,
+ MainActivity::class.java,
+ Uri.parse("audiography://widget/shuffle")
+ )
+ return intent
+ }
+
+ private fun dispatchMediaKey(context: Context, keyCode: Int) {
+ val am = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
+ val eventTime = SystemClock.uptimeMillis()
+ am.dispatchMediaKeyEvent(KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyCode, 0))
+ am.dispatchMediaKeyEvent(KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyCode, 0))
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/res/drawable/art_rounded_bg.xml b/android/app/src/main/res/drawable/art_rounded_bg.xml
new file mode 100644
index 0000000..ca0e439
--- /dev/null
+++ b/android/app/src/main/res/drawable/art_rounded_bg.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/drawable/ic_default_art.xml b/android/app/src/main/res/drawable/ic_default_art.xml
new file mode 100644
index 0000000..14d0f6e
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_default_art.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/drawable/ic_pause.xml b/android/app/src/main/res/drawable/ic_pause.xml
new file mode 100644
index 0000000..d804594
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_pause.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/android/app/src/main/res/drawable/ic_play.xml b/android/app/src/main/res/drawable/ic_play.xml
new file mode 100644
index 0000000..f037022
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_play.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/drawable/ic_play_arrow.xml b/android/app/src/main/res/drawable/ic_play_arrow.xml
new file mode 100644
index 0000000..6fa1247
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_play_arrow.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/android/app/src/main/res/drawable/ic_skip_next.xml b/android/app/src/main/res/drawable/ic_skip_next.xml
new file mode 100644
index 0000000..6688eff
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_skip_next.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/android/app/src/main/res/drawable/ic_skip_previous.xml b/android/app/src/main/res/drawable/ic_skip_previous.xml
new file mode 100644
index 0000000..56db98c
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_skip_previous.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/android/app/src/main/res/drawable/play_button_bg.xml b/android/app/src/main/res/drawable/play_button_bg.xml
new file mode 100644
index 0000000..3d8471f
--- /dev/null
+++ b/android/app/src/main/res/drawable/play_button_bg.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/drawable/widget_background.xml b/android/app/src/main/res/drawable/widget_background.xml
new file mode 100644
index 0000000..6f98adc
--- /dev/null
+++ b/android/app/src/main/res/drawable/widget_background.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/layout/music_widget.xml b/android/app/src/main/res/layout/music_widget.xml
new file mode 100644
index 0000000..94f2cc2
--- /dev/null
+++ b/android/app/src/main/res/layout/music_widget.xml
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..2bcdf2c
--- /dev/null
+++ b/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,5 @@
+
+
+ Osserva
+ Osserva music controls
+
\ No newline at end of file
diff --git a/android/app/src/main/res/xml/music_widget_info.xml b/android/app/src/main/res/xml/music_widget_info.xml
new file mode 100644
index 0000000..f13d7fc
--- /dev/null
+++ b/android/app/src/main/res/xml/music_widget_info.xml
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/lib/core/di/init_dependencies.dart b/lib/core/di/init_dependencies.dart
index d280618..828059b 100644
--- a/lib/core/di/init_dependencies.dart
+++ b/lib/core/di/init_dependencies.dart
@@ -11,6 +11,7 @@ import 'package:osserva/core/di/modules/onboarding_module.dart';
import 'package:osserva/core/di/modules/playlists_module.dart';
import 'package:osserva/core/di/modules/profile_module.dart';
import 'package:osserva/core/router/app_router.dart';
+import 'package:osserva/core/services/widget_sync_service.dart';
import 'package:osserva/features/analytics/data/datasources/audio_analytics_tracker.dart';
import 'package:osserva/features/background_notification/data/datasources/audio_handler.dart';
import 'package:osserva/features/home/presentation/bloc/home_bloc/home_bloc.dart';
@@ -32,19 +33,8 @@ Future initDependencies() async {
serviceLocator.registerSingleton(audioPlayer);
serviceLocator.registerSingleton(AppRouter());
- final audioHandler = await AudioService.init(
- builder: () => MusicPlayerHandler(player: audioPlayer),
- config: const AudioServiceConfig(
- androidNotificationChannelId: 'com.osserva.app.channel.audio',
- androidNotificationChannelName: 'Music Playback',
- androidNotificationOngoing: true,
- androidShowNotificationBadge: false,
- ),
- );
- serviceLocator.registerSingleton(audioHandler);
-
// =========================================================
- // 2. Features
+ // 2. Features (Must register before AudioHandler if it depends on them)
// =========================================================
registerLocalMusicDependencies(serviceLocator);
registerMusicPlayerDependencies(serviceLocator);
@@ -55,13 +45,36 @@ Future initDependencies() async {
registerFavoritesDependencies(serviceLocator);
registerArtistsDependencies(serviceLocator);
+ final audioHandler = await AudioService.init(
+ builder:
+ () => MusicPlayerHandler(
+ player: audioPlayer,
+ getLocalSongsUseCase: serviceLocator(),
+ ),
+ config: const AudioServiceConfig(
+ androidNotificationChannelId: 'com.osserva.app.channel.audio',
+ androidNotificationChannelName: 'Music Playback',
+ androidNotificationOngoing: true,
+ androidShowNotificationBadge: false,
+ ),
+ );
+ serviceLocator.registerSingleton(audioHandler);
+
// Home has no repository — registered inline, no module needed
serviceLocator.registerFactory(
() => HomeBloc(musicRepository: serviceLocator()),
);
+ serviceLocator.registerLazySingleton(
+ () => WidgetSyncService(
+ playerBloc: serviceLocator(),
+ audioQuery: serviceLocator(),
+ ),
+ );
+
// =========================================================
// 3. Post-registration init
// =========================================================
serviceLocator().init();
+ serviceLocator().init();
}
diff --git a/lib/core/di/modules/music_player_module.dart b/lib/core/di/modules/music_player_module.dart
index 5a08391..c7e1760 100644
--- a/lib/core/di/modules/music_player_module.dart
+++ b/lib/core/di/modules/music_player_module.dart
@@ -8,5 +8,6 @@ void registerMusicPlayerDependencies(GetIt sl) {
sl.registerLazySingleton(
() => AudioPlayerRepositoryImpl(sl()),
);
- sl.registerFactory(() => MusicPlayerBloc(sl(), sl(), sl()));
+ // registerFactory → registerLazySingleton
+ sl.registerLazySingleton(() => MusicPlayerBloc(sl(), sl(), sl()));
}
diff --git a/lib/core/os_widget/os_widget_manager.dart b/lib/core/os_widget/os_widget_manager.dart
new file mode 100644
index 0000000..5722737
--- /dev/null
+++ b/lib/core/os_widget/os_widget_manager.dart
@@ -0,0 +1,24 @@
+import 'dart:async';
+import 'package:audio_service/audio_service.dart';
+import 'package:home_widget/home_widget.dart';
+
+class OsWidgetManager {
+ static Future initialize(AudioHandler audioHandler) async {
+ HomeWidget.registerInteractivityCallback((uri) async {
+ if (uri == null) return;
+
+ if (uri.host == 'playPause') {
+ final playing = audioHandler.playbackState.value.playing;
+ if (playing) {
+ await audioHandler.pause();
+ } else {
+ await audioHandler.play();
+ }
+ } else if (uri.host == 'next') {
+ await audioHandler.skipToNext();
+ } else if (uri.host == 'previous') {
+ await audioHandler.skipToPrevious();
+ }
+ });
+ }
+}
diff --git a/lib/core/services/widget_sync_service.dart b/lib/core/services/widget_sync_service.dart
new file mode 100644
index 0000000..0196e47
--- /dev/null
+++ b/lib/core/services/widget_sync_service.dart
@@ -0,0 +1,125 @@
+import 'dart:async';
+import 'dart:io';
+
+import 'package:flutter/material.dart';
+import 'package:home_widget/home_widget.dart';
+import 'package:on_audio_query/on_audio_query.dart';
+import 'package:osserva/features/music_player/presentation/bloc/music_player_bloc.dart';
+import 'package:osserva/features/music_player/presentation/bloc/music_player_event.dart';
+import 'package:osserva/features/music_player/presentation/bloc/music_player_state.dart';
+import 'package:path_provider/path_provider.dart';
+
+/// Bridges MusicPlayerBloc state → Android home screen widget.
+/// Register as a singleton in DI and call [init] after the BLoC is ready.
+class WidgetSyncService {
+ String? _lastSongTitle;
+ bool? _lastIsPlaying;
+ bool? _lastIsShuffle;
+ final MusicPlayerBloc _playerBloc;
+ final OnAudioQuery _audioQuery;
+
+ StreamSubscription? _stateSub;
+ StreamSubscription? _clickSub;
+
+ static const _androidWidgetName = 'MusicPlayerWidget';
+
+ WidgetSyncService({
+ required MusicPlayerBloc playerBloc,
+ required OnAudioQuery audioQuery,
+ }) : _playerBloc = playerBloc,
+ _audioQuery = audioQuery;
+
+ void init() {
+ // Register background callback (required by home_widget even if unused)
+ HomeWidget.registerInteractivityCallback(_widgetBackgroundCallback);
+
+ // Handle shuffle button taps (other controls go direct via MediaKey)
+ _clickSub = HomeWidget.widgetClicked.listen(_onWidgetClicked);
+
+ // Sync state changes to the widget
+ _stateSub = _playerBloc.stream.listen(_onPlayerStateChanged);
+
+ // Push the current state immediately on init
+ _onPlayerStateChanged(_playerBloc.state);
+ }
+
+ Future _onPlayerStateChanged(MusicPlayerState state) async {
+ final title = state.currentSong?.title;
+ final isPlaying = state.isPlaying;
+ final isShuffle = state.isShuffling;
+
+ // Skip if nothing meaningful changed
+ if (title == _lastSongTitle &&
+ isPlaying == _lastIsPlaying &&
+ isShuffle == _lastIsShuffle) {
+ return;
+ }
+
+ _lastSongTitle = title;
+ _lastIsPlaying = isPlaying;
+ _lastIsShuffle = isShuffle;
+ debugPrint(
+ '[WidgetSync] song=${state.currentSong?.title}, playing=${state.isPlaying}',
+ );
+
+ await Future.wait([
+ HomeWidget.saveWidgetData(
+ 'song_title',
+ state.currentSong?.title ?? '',
+ ),
+ HomeWidget.saveWidgetData(
+ 'artist',
+ state.currentSong?.artist ?? '',
+ ),
+ HomeWidget.saveWidgetData('is_playing', state.isPlaying),
+ HomeWidget.saveWidgetData('is_shuffle', state.isShuffling),
+ ]);
+
+ if (state.currentSong != null) {
+ await _saveArtwork(state.currentSong!.id);
+ } else {
+ await HomeWidget.saveWidgetData('art_path', '');
+ }
+
+ await HomeWidget.updateWidget(androidName: _androidWidgetName);
+ }
+
+ Future _saveArtwork(int songId) async {
+ try {
+ final art = await _audioQuery.queryArtwork(
+ songId,
+ ArtworkType.AUDIO,
+ size: 200,
+ quality: 90,
+ );
+ if (art != null && art.isNotEmpty) {
+ final dir = await getApplicationSupportDirectory();
+ final file = File('${dir.path}/widget_art.png');
+ await file.writeAsBytes(art);
+ await HomeWidget.saveWidgetData('art_path', file.path);
+ return;
+ }
+ } catch (_) {}
+ await HomeWidget.saveWidgetData('art_path', '');
+ }
+
+ void _onWidgetClicked(Uri? uri) {
+ if (uri == null) return;
+ if (uri.host == 'shuffle') {
+ _playerBloc.add(const MusicPlayerEvent.toggleShuffle());
+ }
+ }
+
+ void dispose() {
+ _stateSub?.cancel();
+ _clickSub?.cancel();
+ }
+}
+
+/// Background callback — runs in a separate isolate when the app is not active.
+/// Shuffle is handled in the foreground via [_onWidgetClicked].
+/// Play/Pause/Next/Prev are handled natively via MediaKey, so nothing needed here.
+@pragma('vm:entry-point')
+Future _widgetBackgroundCallback(Uri? uri) async {
+ // intentionally empty — see architecture comment above
+}
diff --git a/lib/features/background_notification/data/datasources/audio_handler.dart b/lib/features/background_notification/data/datasources/audio_handler.dart
index 85041b0..e366357 100644
--- a/lib/features/background_notification/data/datasources/audio_handler.dart
+++ b/lib/features/background_notification/data/datasources/audio_handler.dart
@@ -3,19 +3,25 @@ import 'dart:developer';
import 'package:audio_service/audio_service.dart';
import 'package:just_audio/just_audio.dart';
+import 'package:osserva/core/usecases/usecase.dart';
+import 'package:osserva/features/local_music/domain/usecases/get_local_songs_use_case.dart';
// This class isolates the "Background Service" logic from the rest of the app.
// It is the Single Source of Truth for the OS.
class MusicPlayerHandler extends BaseAudioHandler
with QueueHandler, SeekHandler {
final AudioPlayer _player;
+ final GetLocalSongsUseCase _getLocalSongsUseCase;
/// the [_subscriptions] variable to manage add/dispose of streams
/// it holds a list of subscriptions
final _subscriptions = [];
- MusicPlayerHandler({AudioPlayer? player})
- : _player = player ?? AudioPlayer() {
+ MusicPlayerHandler({
+ required AudioPlayer player,
+ required GetLocalSongsUseCase getLocalSongsUseCase,
+ }) : _player = player,
+ _getLocalSongsUseCase = getLocalSongsUseCase {
_init();
}
@@ -257,7 +263,39 @@ class MusicPlayerHandler extends BaseAudioHandler
}
@override
- Future play() => _player.play();
+ Future play() async {
+ if (_player.sequence == null || _player.sequence!.isEmpty) {
+ final result = await _getLocalSongsUseCase.call(NoParams());
+ await result.fold(
+ (failure) async => log("Failed to load library on play: $failure"),
+ (songs) async {
+ if (songs.isNotEmpty) {
+ final items = songs.asMap().entries.map(
+ (entry) {
+ final index = entry.key;
+ final s = entry.value;
+ return MediaItem(
+ id: s.id.toString(),
+ album: s.album,
+ title: s.title,
+ artist: s.artist,
+ duration: Duration(milliseconds: s.duration.toInt()),
+ artUri: s.albumId != null
+ ? Uri.parse(
+ "content://media/external/audio/albumart/${s.albumId}",
+ )
+ : null,
+ extras: {'url': s.path, 'uniqueId': '${s.id}_$index'},
+ );
+ },
+ ).toList();
+ await setQueueItems(items: items, initialIndex: 0);
+ }
+ },
+ );
+ }
+ return _player.play();
+ }
@override
Future pause() => _player.pause();
diff --git a/lib/main.dart b/lib/main.dart
index 97706ae..8c232e0 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -65,7 +65,9 @@ class _MyAppState extends State {
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
- BlocProvider(create: (_) => serviceLocator()),
+ // BlocProvider.value → GetIt owns the instance, BlocProvider just exposes it
+ BlocProvider.value(value: serviceLocator()),
+ // BlocProvider(create: (_) => serviceLocator()),
BlocProvider(
create: (_) =>
serviceLocator()
diff --git a/pubspec.lock b/pubspec.lock
index 18659c0..64222bf 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -560,6 +560,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.2"
+ home_widget:
+ dependency: "direct main"
+ description:
+ name: home_widget
+ sha256: d794a73894012459a4c63b94a6dc2cb3ccaa6eb08fb15b974aa7ac642594aed5
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.9.0"
hooks:
dependency: transitive
description:
@@ -963,7 +971,7 @@ packages:
source: hosted
version: "1.9.1"
path_provider:
- dependency: transitive
+ dependency: "direct main"
description:
name: path_provider
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
diff --git a/pubspec.yaml b/pubspec.yaml
index 7becd17..b7dc59d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -66,6 +66,8 @@ dependencies:
stream_transform: ^2.1.1
media_store_plus: ^0.1.3
audiotags: ^1.1.3
+ home_widget: ^0.9.0
+ path_provider: ^2.1.5
#flutter_launcher_icons: ^0.14.4
dev_dependencies:
From f2e84be89d7944ea3cdf8434e67ffb2ac7512d32 Mon Sep 17 00:00:00 2001
From: fadyphil
Date: Wed, 18 Mar 2026 00:50:45 +0200
Subject: [PATCH 2/3] fix(widget): ensure immediate playback and fix analysis
issues
- Updates native Android widget to use explicit MediaButton intents for instant wake-up.
- Removes redundant null checks in AudioHandler as reported by flutter analyze.
- Updates unit tests for MusicPlayerHandler to include required GetLocalSongsUseCase dependency.
---
.../com/osserva/app/MusicPlayerWidget.kt | 31 ++++++++++++-------
ios/Runner/GeneratedPluginRegistrant.m | 7 +++++
.../data/datasources/audio_handler.dart | 2 +-
.../music_player_handler_test.dart | 10 +++++-
4 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/android/app/src/main/kotlin/com/osserva/app/MusicPlayerWidget.kt b/android/app/src/main/kotlin/com/osserva/app/MusicPlayerWidget.kt
index fd8423a..a332e96 100644
--- a/android/app/src/main/kotlin/com/osserva/app/MusicPlayerWidget.kt
+++ b/android/app/src/main/kotlin/com/osserva/app/MusicPlayerWidget.kt
@@ -36,12 +36,28 @@ class MusicPlayerWidget : HomeWidgetProvider() {
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
when (intent.action) {
- ACTION_PLAY_PAUSE -> dispatchMediaKey(context, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)
- ACTION_NEXT -> dispatchMediaKey(context, KeyEvent.KEYCODE_MEDIA_NEXT)
- ACTION_PREV -> dispatchMediaKey(context, KeyEvent.KEYCODE_MEDIA_PREVIOUS)
+ ACTION_PLAY_PAUSE -> sendMediaButton(context, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)
+ ACTION_NEXT -> sendMediaButton(context, KeyEvent.KEYCODE_MEDIA_NEXT)
+ ACTION_PREV -> sendMediaButton(context, KeyEvent.KEYCODE_MEDIA_PREVIOUS)
}
}
+ private fun sendMediaButton(context: Context, keyCode: Int) {
+ val eventTime = SystemClock.uptimeMillis()
+
+ // ACTION_DOWN
+ val downIntent = Intent(Intent.ACTION_MEDIA_BUTTON)
+ downIntent.setClassName(context.packageName, "com.ryanheise.audioservice.MediaButtonReceiver")
+ downIntent.putExtra(Intent.EXTRA_KEY_EVENT, KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyCode, 0))
+ context.sendBroadcast(downIntent)
+
+ // ACTION_UP
+ val upIntent = Intent(Intent.ACTION_MEDIA_BUTTON)
+ upIntent.setClassName(context.packageName, "com.ryanheise.audioservice.MediaButtonReceiver")
+ upIntent.putExtra(Intent.EXTRA_KEY_EVENT, KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyCode, 0))
+ context.sendBroadcast(upIntent)
+ }
+
private fun updateWidget(
context: Context,
appWidgetManager: AppWidgetManager,
@@ -122,11 +138,4 @@ class MusicPlayerWidget : HomeWidgetProvider() {
)
return intent
}
-
- private fun dispatchMediaKey(context: Context, keyCode: Int) {
- val am = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
- val eventTime = SystemClock.uptimeMillis()
- am.dispatchMediaKeyEvent(KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyCode, 0))
- am.dispatchMediaKeyEvent(KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyCode, 0))
- }
-}
\ No newline at end of file
+}
diff --git a/ios/Runner/GeneratedPluginRegistrant.m b/ios/Runner/GeneratedPluginRegistrant.m
index bf3c4eb..87d9799 100644
--- a/ios/Runner/GeneratedPluginRegistrant.m
+++ b/ios/Runner/GeneratedPluginRegistrant.m
@@ -36,6 +36,12 @@
@import flutter_native_splash;
#endif
+#if __has_include()
+#import
+#else
+@import home_widget;
+#endif
+
#if __has_include()
#import
#else
@@ -80,6 +86,7 @@ + (void)registerWithRegistry:(NSObject*)registry {
[AudiotagsPlugin registerWithRegistrar:[registry registrarForPlugin:@"AudiotagsPlugin"]];
[FPPDeviceInfoPlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"FPPDeviceInfoPlusPlugin"]];
[FlutterNativeSplashPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterNativeSplashPlugin"]];
+ [HomeWidgetPlugin registerWithRegistrar:[registry registrarForPlugin:@"HomeWidgetPlugin"]];
[FLTImagePickerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTImagePickerPlugin"]];
[JustAudioPlugin registerWithRegistrar:[registry registrarForPlugin:@"JustAudioPlugin"]];
[OnAudioQueryPlugin registerWithRegistrar:[registry registrarForPlugin:@"OnAudioQueryPlugin"]];
diff --git a/lib/features/background_notification/data/datasources/audio_handler.dart b/lib/features/background_notification/data/datasources/audio_handler.dart
index e366357..dade636 100644
--- a/lib/features/background_notification/data/datasources/audio_handler.dart
+++ b/lib/features/background_notification/data/datasources/audio_handler.dart
@@ -264,7 +264,7 @@ class MusicPlayerHandler extends BaseAudioHandler
@override
Future play() async {
- if (_player.sequence == null || _player.sequence!.isEmpty) {
+ if (_player.sequence.isEmpty) {
final result = await _getLocalSongsUseCase.call(NoParams());
await result.fold(
(failure) async => log("Failed to load library on play: $failure"),
diff --git a/test/features/background-notification-feature/data/datasources/music_player_handler_test.dart b/test/features/background-notification-feature/data/datasources/music_player_handler_test.dart
index a0e965a..b9e66fd 100644
--- a/test/features/background-notification-feature/data/datasources/music_player_handler_test.dart
+++ b/test/features/background-notification-feature/data/datasources/music_player_handler_test.dart
@@ -3,14 +3,18 @@ import 'package:mocktail/mocktail.dart';
import 'package:just_audio/just_audio.dart';
import 'package:audio_service/audio_service.dart';
import 'package:osserva/features/background_notification/data/datasources/audio_handler.dart';
+import 'package:osserva/features/local_music/domain/usecases/get_local_songs_use_case.dart';
class MockAudioPlayer extends Mock implements AudioPlayer {}
+class MockGetLocalSongsUseCase extends Mock implements GetLocalSongsUseCase {}
+
class FakeAudioSource extends Fake implements AudioSource {}
void main() {
late MusicPlayerHandler handler;
late MockAudioPlayer mockPlayer;
+ late MockGetLocalSongsUseCase mockGetLocalSongsUseCase;
setUpAll(() {
registerFallbackValue(FakeAudioSource());
@@ -19,6 +23,7 @@ void main() {
setUp(() {
mockPlayer = MockAudioPlayer();
+ mockGetLocalSongsUseCase = MockGetLocalSongsUseCase();
// Helper to allow void callbacks
when(
() => mockPlayer.playbackEventStream,
@@ -63,7 +68,10 @@ void main() {
),
).thenAnswer((_) async => null);
- handler = MusicPlayerHandler(player: mockPlayer);
+ handler = MusicPlayerHandler(
+ player: mockPlayer,
+ getLocalSongsUseCase: mockGetLocalSongsUseCase,
+ );
});
group('MusicPlayerHandler', () {
From d963bf4cece90d0f1659281b03f7beadebb12bfc Mon Sep 17 00:00:00 2001
From: fadyphil
Date: Wed, 18 Mar 2026 00:56:13 +0200
Subject: [PATCH 3/3] docs(widget): document android home screen widget
Adds technical overview and updates the README with new feature details and screenshots. Includes comprehensive guide to the widget architecture and cold-start mechanism.
---
README.md | 4 +++
assets/screenshots/os-widget.jpg | Bin 0 -> 205357 bytes
docs/features/android_widget.md | 47 +++++++++++++++++++++++++++++++
3 files changed, 51 insertions(+)
create mode 100644 assets/screenshots/os-widget.jpg
create mode 100644 docs/features/android_widget.md
diff --git a/README.md b/README.md
index d7d3caa..b446738 100644
--- a/README.md
+++ b/README.md
@@ -29,12 +29,15 @@ Play counts, activity heatmaps, time-of-day distributions, per-artist breakdowns
+
## Features
### Playback
- Seamless background playback with lock-screen and notification controls
+- **Android Home Screen Widget:** Real-time state synchronization (title, artist, album art, play/pause state)
+- **Cold Start Support:** Start playback directly from the widget even if the app is closed
- Full-screen player with queue manager and sleep timer
- Android 13+ permission handling (`READ_MEDIA_AUDIO`)
@@ -82,6 +85,7 @@ Each feature owns its own `data`, `domain`, and `presentation` layers. Cross-fea
| Dependency Injection | `get_it` | Service locator; features register their own modules |
| Navigation | `auto_route` | Strongly-typed, declarative routing |
| Audio Playback | `just_audio` + `audio_service` | Core engine + background service handler |
+| OS Widget | `home_widget` | Bridge for Android Home Screen Widget state |
| Media Querying | `on_audio_query` (forked) | Optimized local media retrieval |
| Database | `sqflite` | SQLite for analytics (star schema, daily rollups) |
| Error Handling | `fpdart` | `Either` types throughout the domain layer |
diff --git a/assets/screenshots/os-widget.jpg b/assets/screenshots/os-widget.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..346b53e0e8ce3c2162648910913967b7a08d5f9d
GIT binary patch
literal 205357
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