[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-notifiche-locali-in-flutter-con-flutter-local-notifications-guida-pratica":3,"comments-article-notifiche-locali-in-flutter-con-flutter-local-notifications-guida-pratica":21},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"video_url":10,"status":11,"published_at":12,"meta_title":13,"meta_description":14,"category":15,"author":19},48,"Notifiche locali in Flutter con flutter_local_notifications: guida pratica","notifiche-locali-in-flutter-con-flutter-local-notifications-guida-pratica","Impara a mostrare notifiche locali programmate e istantanee in Flutter con flutter_local_notifications: configurazione Android\u002FiOS, scheduling con timezone e gestione dei tap.","## Introduzione\n\nLe notifiche locali sono avvisi generati direttamente dal dispositivo, senza bisogno di un server remoto. Sono perfette per promemoria, timer, allarmi e notifiche legate a eventi che l'app conosce in anticipo. A differenza delle notifiche push (che richiedono FCM e un backend), le notifiche locali funzionano completamente offline.\n\nIn questa guida vediamo come integrare il pacchetto `flutter_local_notifications`, configurarlo su Android e iOS, mostrare notifiche immediate e programmate, e gestire i tap dell'utente.\n\n## Installazione e dipendenze\n\nAggiungi le dipendenze al `pubspec.yaml`:\n\n```yaml\ndependencies:\n  flutter_local_notifications: ^17.2.3\n  timezone: ^0.9.4\n```\n\nIl pacchetto `timezone` è necessario per programmare notifiche in un fuso orario specifico, evitando comportamenti imprevisti con l'ora legale.\n\n## Configurazione Android\n\nSu Android 13+ è necessario il permesso per le notifiche. Aggiungi nell'`AndroidManifest.xml`:\n\n```xml\n\u003Cuses-permission android:name=\"android.permission.POST_NOTIFICATIONS\"\u002F>\n\u003Cuses-permission android:name=\"android.permission.SCHEDULE_EXACT_ALARM\"\u002F>\n\u003Cuses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\"\u002F>\n```\n\nLe ultime due servono per le notifiche programmate precise che sopravvivono al riavvio del dispositivo.\n\n## Configurazione iOS\n\nSu iOS, nel file `AppDelegate.swift`, assicurati di registrare il plugin. Il permesso viene richiesto a runtime tramite il codice Dart che vedremo tra poco.\n\n## Inizializzazione del servizio\n\nÈ buona pratica incapsulare la logica in una classe dedicata:\n\n```dart\nimport 'package:flutter_local_notifications\u002Fflutter_local_notifications.dart';\nimport 'package:timezone\u002Ftimezone.dart' as tz;\nimport 'package:timezone\u002Fdata\u002Flatest.dart' as tzdata;\n\nclass NotificationService {\n  static final _plugin = FlutterLocalNotificationsPlugin();\n\n  static Future\u003Cvoid> init() async {\n    tzdata.initializeTimeZones();\n\n    const androidSettings =\n        AndroidInitializationSettings('@mipmap\u002Fic_launcher');\n    const iosSettings = DarwinInitializationSettings(\n      requestAlertPermission: true,\n      requestBadgePermission: true,\n      requestSoundPermission: true,\n    );\n\n    const settings = InitializationSettings(\n      android: androidSettings,\n      iOS: iosSettings,\n    );\n\n    await _plugin.initialize(\n      settings,\n      onDidReceiveNotificationResponse: _onTap,\n    );\n  }\n\n  static void _onTap(NotificationResponse response) {\n    final payload = response.payload;\n    if (payload != null) {\n      \u002F\u002F Naviga o gestisci il payload\n      print('Notifica toccata: $payload');\n    }\n  }\n}\n```\n\nChiama `NotificationService.init()` nel `main()` prima di `runApp()`.\n\n## Richiedere i permessi\n\nSu Android 13+ e iOS occorre richiedere esplicitamente il permesso:\n\n```dart\nstatic Future\u003Cvoid> requestPermissions() async {\n  final android = _plugin.resolvePlatformSpecificImplementation\u003C\n      AndroidFlutterLocalNotificationsPlugin>();\n  await android?.requestNotificationsPermission();\n\n  final ios = _plugin.resolvePlatformSpecificImplementation\u003C\n      IOSFlutterLocalNotificationsPlugin>();\n  await ios?.requestPermissions(alert: true, badge: true, sound: true);\n}\n```\n\n## Mostrare una notifica immediata\n\n```dart\nstatic Future\u003Cvoid> showNow({\n  required String title,\n  required String body,\n}) async {\n  const androidDetails = AndroidNotificationDetails(\n    'canale_generale',\n    'Notifiche generali',\n    channelDescription: 'Canale per avvisi generici',\n    importance: Importance.max,\n    priority: Priority.high,\n  );\n\n  const details = NotificationDetails(\n    android: androidDetails,\n    iOS: DarwinNotificationDetails(),\n  );\n\n  await _plugin.show(0, title, body, details, payload: 'home');\n}\n```\n\nSu Android il concetto di **canale** (channel) è obbligatorio dalla versione 8.0: raggruppa le notifiche per tipologia e consente all'utente di gestirne le preferenze.\n\n## Programmare una notifica\n\nPer inviare una notifica in un momento futuro si usa `zonedSchedule`:\n\n```dart\nstatic Future\u003Cvoid> scheduleReminder({\n  required int id,\n  required String title,\n  required String body,\n  required DateTime dateTime,\n}) async {\n  await _plugin.zonedSchedule(\n    id,\n    title,\n    body,\n    tz.TZDateTime.from(dateTime, tz.local),\n    const NotificationDetails(\n      android: AndroidNotificationDetails(\n        'canale_promemoria',\n        'Promemoria',\n        importance: Importance.max,\n        priority: Priority.high,\n      ),\n      iOS: DarwinNotificationDetails(),\n    ),\n    androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,\n    matchDateTimeComponents: DateTimeComponents.time,\n  );\n}\n```\n\nAlcune note importanti:\n\n- `AndroidScheduleMode.exactAllowWhileIdle` garantisce che la notifica scatti all'orario preciso anche in modalità Doze.\n- `matchDateTimeComponents: DateTimeComponents.time` rende la notifica ricorrente ogni giorno alla stessa ora. Ometti questo parametro per una notifica singola.\n\n## Annullare le notifiche\n\n```dart\n\u002F\u002F Annulla una notifica specifica\nstatic Future\u003Cvoid> cancel(int id) => _plugin.cancel(id);\n\n\u002F\u002F Annulla tutte le notifiche programmate\nstatic Future\u003Cvoid> cancelAll() => _plugin.cancelAll();\n```\n\n## Gestire il tap all'avvio dell'app\n\nSe l'utente tocca una notifica mentre l'app è terminata, puoi recuperare i dettagli al lancio:\n\n```dart\nstatic Future\u003Cvoid> checkLaunchDetails() async {\n  final details = await _plugin.getNotificationAppLaunchDetails();\n  if (details?.didNotificationLaunchApp ?? false) {\n    final payload = details!.notificationResponse?.payload;\n    \u002F\u002F Gestisci la navigazione iniziale\n  }\n}\n```\n\n## Best practice\n\n- **Usa ID univoci** per ogni notifica programmata, così da poterle annullare selettivamente.\n- **Crea canali distinti** per categorie diverse (promemoria, offerte, avvisi): l'utente potrà gestirli separatamente nelle impostazioni di sistema.\n- **Non abusare delle notifiche**: un numero eccessivo porta l'utente a disattivarle o a disinstallare l'app.\n- **Testa su dispositivi reali**: gli emulatori possono comportarsi in modo diverso, soprattutto con le notifiche programmate e il risparmio energetico.\n\n## Conclusione\n\n`flutter_local_notifications` è la soluzione di riferimento per gestire avvisi generati localmente in Flutter. Con una corretta gestione dei canali, dei permessi e del timezone puoi realizzare promemoria affidabili e ricorrenti che funzionano anche offline. Per notifiche inviate da un server, invece, la strada è quella delle push con FCM.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002F46a47d4b-a545-4a92-98c1-c7ba3c64f2f8.jpg",null,"published","2026-07-22T04:00:41+00:00","Notifiche locali in Flutter con flutter_local_notifications","Guida pratica alle notifiche locali in Flutter: configurazione Android\u002FiOS, scheduling con timezone, permessi e gestione dei tap con flutter_local_notifications.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1785219596917]