diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 7208d24..814a6b1 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -36,6 +36,13 @@
+
+
+
()
+ ?.createNotificationChannel(fgChannel);
+
await FlutterBackgroundService().configure(
iosConfiguration: IosConfiguration(),
androidConfiguration: AndroidConfiguration(
onStart: _onServiceStart,
autoStart: false,
isForegroundMode: true,
+ notificationChannelId: 'de.baka.melo.fg_service',
+ initialNotificationTitle: 'Melo Sync',
+ initialNotificationContent: 'Synchronisiere Musik…',
+ foregroundServiceTypes: [AndroidForegroundType.dataSync],
),
);
diff --git a/lib/services/sync_service.dart b/lib/services/sync_service.dart
index 1e5bcb9..cb955c8 100644
--- a/lib/services/sync_service.dart
+++ b/lib/services/sync_service.dart
@@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_background_service/flutter_background_service.dart';
import '../database/db_helper.dart';
import '../models/song.dart';
@@ -577,18 +578,22 @@ class SyncService {
if (!Platform.isAndroid) return;
final maxP = gesamt > 0 ? gesamt : 1;
final p = aktuell > maxP ? maxP : aktuell;
- notificationsPlugin.show(
- id: _syncNotifyId,
- title: 'Synchronisiere…',
- body: gesamt > 0 ? '$aktuell / $gesamt Songs' : body,
- notificationDetails: NotificationDetails(
- android: syncNotificationDetails(
- ongoing: true,
- progress: p,
- maxProgress: maxP,
+ try {
+ notificationsPlugin.show(
+ id: _syncNotifyId,
+ title: 'Synchronisiere…',
+ body: gesamt > 0 ? '$aktuell / $gesamt Songs' : body,
+ notificationDetails: NotificationDetails(
+ android: syncNotificationDetails(
+ ongoing: true,
+ progress: p,
+ maxProgress: maxP,
+ ),
),
- ),
- );
+ );
+ } catch (_) {
+ // Plugin kann beim App-Exit bereits disposed sein
+ }
}
/// Abschluss-Notification — tippbar (öffnet den Cloud-Tab, payload
@@ -630,9 +635,18 @@ class SyncService {
/// Startet den Foreground-Service, damit der Sync auch bei Display-aus
/// und minimierter App weiterläuft (Android-Prozess-Garantie).
+ /// v2.55.3: Prüft POST_NOTIFICATIONS-Permission (Android 13+).
+ /// Ohne diese Permission crasht der Foreground-Service innerhalb von
+ /// 5 Sekunden (Android killt Services ohne sichtbare Notification).
Future _starteForegroundService() async {
if (!Platform.isAndroid) return;
try {
+ // Android 13+: Benachrichtigungs-Berechtigung erforderlich
+ final status = await Permission.notification.status;
+ if (status.isDenied || status.isPermanentlyDenied) {
+ MeloLogger().aktion('foreground_sync_skip', {'grund': 'notification_denied'});
+ return;
+ }
final svc = FlutterBackgroundService();
final laeuft = await svc.isRunning();
if (!laeuft) {