v2.55.3 — Code-Review-Fixes: foregroundServiceType (Android 14+), POST_NOTIFICATIONS-Check, FG-Service-Notification-Channel, try/catch _zeigeSyncNotification
CRITICAL: - AndroidManifest: foregroundServiceType="dataSync" für BackgroundService (Android 14+ MissingForegroundServiceTypeException) - main.dart: notificationChannelId + initialNotificationTitle + foregroundServiceTypes für FlutterBackgroundService (fehlende FG-Notification → ANR/crash nach 5s) MEDIUM: - sync_service.dart: POST_NOTIFICATIONS-Permission-Check vor _starteForegroundService (Android 13+) - sync_service.dart: try/catch um _zeigeSyncNotification (plugin-dispose-Sicherheit) flutter analyze: clean | flutter test: 194/194 passed
This commit is contained in:
@@ -77,12 +77,33 @@ void main() async {
|
||||
?.createNotificationChannel(syncChannel);
|
||||
|
||||
// ── Background Service initialisieren (Issue #3) ──
|
||||
// v2.55.3: Foreground-Service-Notification-Channel konfigurieren.
|
||||
// Ohne notificationChannelId zeigt der Service eine Default-Notification
|
||||
// ohne eigenen Channel — auf Android 14+ Pflicht.
|
||||
const fgChannel = AndroidNotificationChannel(
|
||||
'de.baka.melo.fg_service',
|
||||
'Melo Hintergrunddienst',
|
||||
description: 'Hält Melo im Hintergrund aktiv (Sync, Downloads)',
|
||||
importance: Importance.low,
|
||||
playSound: false,
|
||||
enableVibration: false,
|
||||
showBadge: false,
|
||||
);
|
||||
await notificationsPlugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin>()
|
||||
?.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],
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -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<void> _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) {
|
||||
|
||||
Reference in New Issue
Block a user