Adicione um lembrete ao seu aplicativo com notificações locais flutuantes
Se você deseja adicionar um lembrete ao seu aplicativo de anotações ou a qualquer outro aplicativo, este artigo o guiará de maneira simples. Eu gostaria de criar uma demonstração simples e fácil de aplicativo de anotações, para ajudá-lo a agendar uma anotação usando 2 pacotes e plug-ins interessantes do flutter.
flutter_local_notifications: ^13.0.0 datetime_picker_formfield_new: ^2.1.0
datetime_picker_formfield me ajudou a selecionar uma data para minha pequena nota. Assim, eu poderia agendar um lembrete de nota usando o plugin flutter_local_notifications. Como a versão que estou usando exigia o agendamento de notificações de acordo com um fuso horário específico e o método de agendamento existente agora está obsoleto, também tive que usar o pacote de fuso horário. Mas você não precisa adicionar isso ao arquivo yaml porque o plugin flutter_local_notifications já usa isso.
iOS setup
Para o Swift, adicione este código ao delegado do seu aplicativo.
if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate }
Para Objective-C
if (@available(iOS 10.0, *)) { [UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self; }
Antes de fazer uma compilação de versão do Android, consulte a parte de configuração da versão de versão do plugin de notificação leia-me.
Eu criei o widget Stateless para chamar dentro do nosso runApp, outra classe como minha tela de notas que inclui 2 notas. A classe NoteThumbnail pode ser reutilizada para criar notas quantas vezes você quiser. Não usei uma lista longa com notas. Acabei de adicionar duas notas para simplificar a demonstração.
Dentro da minha miniatura criei um método para selecionar uma data e hora usando seletores de data e hora, onde também posso agendar uma notificação de acordo com a data e hora combinadas.
Você pode ver minha tela de notas sem nenhum código necessário para mostrar uma notificação.
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart'; import 'package:flutter/material.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); //TODO //notification initialization and requesting permission runApp(const NoteApp()); } class NoteApp extends StatelessWidget { const NoteApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const MaterialApp( debugShowCheckedModeBanner: false, title: "My Note Alarm Demo", home: MyNoteScreen(), ); } } class MyNoteScreen extends StatefulWidget { const MyNoteScreen({Key? key}) : super(key: key); @override _MyNoteScreenState createState() => _MyNoteScreenState(); } class _MyNoteScreenState extends State<MyNoteScreen> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: SingleChildScrollView( padding: const EdgeInsets.all(15), child: Column( children: [ Row( children: const [ Expanded( child: NoteThumbnail( id: 1, color: Color(0xFFFF9C99), title: "Note one", content: "Lorem ipsum")), SizedBox( width: 15, ), Expanded( child: NoteThumbnail( id: 2, color: Color(0xFF6fefb0), title: "Note two", content: "Lorem ipsum")), ], ) ], ), ), ); } } class NoteThumbnail extends StatefulWidget { final int id; final Color color; final String title; final String content; const NoteThumbnail( {Key? key, required this.id, required this.color, required this.title, required this.content}) : super(key: key); @override _NoteThumbnailState createState() => _NoteThumbnailState(); } class _NoteThumbnailState extends State<NoteThumbnail> { DateTime selectedDate = DateTime.now(); DateTime fullDate = DateTime.now(); Future<DateTime> _selectDate(BuildContext context) async { final date = await showDatePicker( context: context, firstDate: DateTime(1900), initialDate: selectedDate, lastDate: DateTime(2100)); if (date != null) { final time = await showTimePicker( context: context, initialTime: TimeOfDay.fromDateTime(selectedDate), ); if (time != null) { setState(() { fullDate = DateTimeField.combine(date, time); }); //TODO //schedule a notification } return DateTimeField.combine(date, time); } else { return selectedDate; } } @override Widget build(BuildContext context) { return Container( height: 300, decoration: BoxDecoration( color: widget.color, borderRadius: BorderRadius.circular(10.0), ), padding: const EdgeInsets.all(10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.title, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 20), ), const SizedBox( height: 5, ), Text(widget.content), const SizedBox( height: 80, ), Text(fullDate.toString()), const SizedBox( height: 15, ), ElevatedButton( onPressed: () => _selectDate(context), child: const Text("Add reminder")) ], ), ); } }
Antes de concluir as tarefas TODO na tela de notas, precisamos criar nosso manipulador de notificações. É melhor ter uma única classe de serviço para lidar com todo o trabalho que esperamos do plug-in de notificação de vibração.
Tarefas que eu esperava do manipulador de notificação
- Inicialize uma instância de plug-in com configurações de notificação do Android e iOS
- Inicializar os fusos horários
- Criar ação de notificação selecionada (Ex: — navegar para uma página específica)
- Solicitar permissão do iOS
- Neste caso agende uma notificação
Além desses pontos principais, também adicionei o método para mostrar as notificações.
Primeiro você precisa criar uma classe de serviço de notificação e uma instância do plug-in de notificação.
class NotificationService { final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); }
Em seguida, 1 e 2 da lista de tarefas acima.
Future<void> init() async { //Initialization Settings for Android const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); //Initialization Settings for iOS const IOSInitializationSettings initializationSettingsIOS = IOSInitializationSettings( requestSoundPermission: false, requestBadgePermission: false, requestAlertPermission: false, ); //Initializing settings for both platforms (Android & iOS) const InitializationSettings initializationSettings = InitializationSettings( android: initializationSettingsAndroid, iOS: initializationSettingsIOS); tz.initializeTimeZones(); await flutterLocalNotificationsPlugin.initialize( initializationSettings, onSelectNotification: onSelectNotification ); }
Você deve verificar suas configurações e o nome do ícone de acordo. Certifique-se de inicializar os fusos horários dentro do método init também. Para o terceiro ponto, acabei de adicionar um método vazio para que você possa adicionar a navegação a uma tela desejada.
onSelectNotification(String? payload) async { //Navigate to wherever you want }
Então você tem que adicionar um método para solicitar permissão do iOS.
requestIOSPermissions() { flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< IOSFlutterLocalNotificationsPlugin>() ?.requestPermissions( alert: true, badge: true, sound: true, ); }
Em seguida, crie a função de notificação de agendamento de acordo com a versão do plug-in que você está usando.
Future<void> scheduleNotifications({id, title, body, time}) async { tentar{ aguarde flutterLocalNotificationsPlugin.zonedSchedule( eu ia, título, corpo, tz.TZDateTime.from(hora, tz.local), const NotificationDetails( android: AndroidNotificationDetails( 'id do seu canal', 'nome do seu canal', channelDescription: 'a descrição do seu canal')), androidAllowWhileIdle: verdadeiro, uiLocalNotificationDateInterpretação: UILocalNotificationDateInterpretation.absoluteTime); }pegar(e){ imprimir(e); } }
Aqui eu dei os valores para id, title, body e date time do método select date. Eu adicionei isso dentro de um try catch porque ele dará um erro se você não selecionar uma data futura. Acabei de imprimir o erro, mas certifique-se de adicionar uma mensagem de brinde ou dar qualquer feedback antes de usar isso em um aplicativo.
Você precisa importar os seguintes para usar as funções de fuso horário.
import 'package:timezone/data/latest.dart' as tz; import 'package:timezone/timezone.dart' as tz;
Mesmo que este plug-in de fuso horário não possa fornecer o fuso horário do dispositivo, ele ajudará você a agendar uma notificação de acordo com um fuso horário específico. De acordo com o plug-in leia-me, os desenvolvedores precisam usar algum outro plug-in ou canais de método para obter o fuso horário atual em um dispositivo.
Além das tarefas acima, adicionarei o método de notificação show da seguinte forma.
Future<void> showNotifications({id, title, body, payload}) async { const AndroidNotificationDetails androidPlatformChannelSpecifics = AndroidNotificationDetails('your channel id', 'your channel name', channelDescription: 'your channel description', importance: Importance.max, priority: Priority.high, ticker: 'ticker'); const NotificationDetails platformChannelSpecifics = NotificationDetails(android: androidPlatformChannelSpecifics); await flutterLocalNotificationsPlugin.show( id, title, body, platformChannelSpecifics, payload: payload); }
Quando você juntar toda a classe, ficará assim.
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:timezone/data/latest.dart' as tz; import 'package:timezone/timezone.dart' as tz; class NotificationService { //instance of FlutterLocalNotificationsPlugin final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); Future<void> init() async { //Initialization Settings for Android const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); //Initialization Settings for iOS const IOSInitializationSettings initializationSettingsIOS = IOSInitializationSettings( requestSoundPermission: false, requestBadgePermission: false, requestAlertPermission: false, ); //Initializing settings for both platforms (Android & iOS) const InitializationSettings initializationSettings = InitializationSettings( android: initializationSettingsAndroid, iOS: initializationSettingsIOS); tz.initializeTimeZones(); await flutterLocalNotificationsPlugin.initialize( initializationSettings, onSelectNotification: onSelectNotification ); } onSelectNotification(String? payload) async { //Navigate to wherever you want } requestIOSPermissions() { flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< IOSFlutterLocalNotificationsPlugin>() ?.requestPermissions( alert: true, badge: true, sound: true, ); } Future<void> showNotifications({id, title, body, payload}) async { const AndroidNotificationDetails androidPlatformChannelSpecifics = AndroidNotificationDetails('your channel id', 'your channel name', channelDescription: 'your channel description', importance: Importance.max, priority: Priority.high, ticker: 'ticker'); const NotificationDetails platformChannelSpecifics = NotificationDetails(android: androidPlatformChannelSpecifics); await flutterLocalNotificationsPlugin.show( id, title, body, platformChannelSpecifics, payload: payload); } Future<void> scheduleNotifications({id, title, body, time}) async { try{ await flutterLocalNotificationsPlugin.zonedSchedule( id, title, body, tz.TZDateTime.from(time, tz.local), const NotificationDetails( android: AndroidNotificationDetails( 'your channel id', 'your channel name', channelDescription: 'your channel description')), androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime); }catch(e){ print(e); } } }
Agora você pode importar esta aula para sua tela de anotações e concluir as tarefas TODO.
Agora seu método principal ficará assim.
void main() async { WidgetsFlutterBinding.ensureInitialized(); await NotificationService().init(); // await NotificationService().requestIOSPermissions(); // runApp(const NoteApp()); }
Dentro da classe thumbnail você pode criar a instância do Notification Service.
final NotificationService _notificationService = NotificationService();
Se a data e a hora não forem nulas, você pode agendar a notificação.
await _notificationService.scheduleNotifications( id: widget.id, title: widget.title, body: widget.content, time: fullDate);
Ótimo!! Agora criamos uma demonstração de nota simples com notificações locais.
![]() | ![]() | ![]() |
Por favor, siga os links para os plugins mais detalhes. Você pode ler coisas mais importantes sobre o plug-in de notificação no readme.
![Dart packages](https://pub.dev/static/hash-kkipkgm3/img/flutter-logo-32x32.png)
![Dart packages](https://pub.dev/static/hash-kkipkgm3/img/flutter-logo-32x32.png)