flutter-examples中的本地通知:flutter_local_notifications详解
在移动应用开发中,本地通知(Local Notification)是提升用户体验的重要功能,它允许应用在无需服务器推送的情况下,直接在设备上触发通知提醒。本文将以flutter-examples项目中的push_notifications模块为基础,详细介绍如何在Flutter应用中集成和使用本地通知功能。
本地通知与远程推送的区别
本地通知和远程推送(Push Notification)是移动应用中两种常见的消息提醒方式,它们的主要区别如下:
| 特性 | 本地通知 | 远程推送 |
|---|---|---|
| 触发方式 | 应用本地代码直接触发 | 第三方服务器(如Firebase Cloud Messaging)发送 |
| 网络依赖 | 无需网络 | 需要网络连接 |
| 使用场景 | 定时提醒、事件通知、离线消息 | 实时消息、服务通知、跨设备同步 |
| 权限要求 | 基础通知权限 | 额外需要推送权限配置 |
在flutter-examples项目中,push_notifications模块展示了基于Firebase Cloud Messaging的远程推送实现,其核心代码位于lib/main.dart文件中。
本地通知实现方案
Flutter生态中,实现本地通知的主流插件包括:
- flutter_local_notifications:功能全面的本地通知插件,支持Android和iOS双平台
- local_notifications:轻量级插件,专注于基础通知功能
- awesome_notifications:支持富媒体通知和交互功能的高级插件
其中,flutter_local_notifications是最受欢迎的选择,它提供了以下核心能力:
- 基础通知的创建、调度和取消
- 自定义通知图标、声音和振动模式
- 支持通知点击事件处理
- 定时和周期性通知
- 前台和后台通知管理
集成flutter_local_notifications的步骤
1. 添加依赖
在项目的pubspec.yaml文件中添加flutter_local_notifications依赖:
dependencies:
flutter_local_notifications: ^15.1.1
2. 平台配置
Android配置
在android/app/src/main/AndroidManifest.xml中添加必要权限和服务声明:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application ...>
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
</application>
iOS配置
在ios/Runner/Info.plist中添加通知权限描述:
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>NSUserNotificationUsageDescription</key>
<string>需要发送通知以提醒您重要事件</string>
3. 初始化通知服务
在应用入口处初始化通知服务,创建lib/main.dart中的通知管理器实例:
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> initializeNotifications() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
final InitializationSettings initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onDidReceiveNotificationResponse: onNotificationTapped);
}
void onNotificationTapped(NotificationResponse notificationResponse) {
// 处理通知点击事件
print('通知被点击,有效载荷: ${notificationResponse.payload}');
}
4. 发送基本通知
使用以下代码发送简单的本地通知:
Future<void> showBasicNotification() async {
const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
'basic_channel', // 渠道ID
'基础通知', // 渠道名称
importance: Importance.max,
priority: Priority.high,
showWhen: false,
);
const NotificationDetails details = NotificationDetails(android: androidDetails);
await flutterLocalNotificationsPlugin.show(
0, // 通知ID
'新消息', // 标题
'您有一条未读消息', // 内容
details,
payload: 'basic_notification_payload', // 可选有效载荷
);
}
5. 发送定时通知
创建一个5秒后触发的定时通知:
Future<void> scheduleNotification() async {
const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
'scheduled_channel',
'定时通知',
importance: Importance.defaultImportance,
);
const NotificationDetails details = NotificationDetails(android: androidDetails);
await flutterLocalNotificationsPlugin.zonedSchedule(
1,
'定时提醒',
'这是一个5秒后触发的定时通知',
DateTime.now().add(const Duration(seconds: 5)),
details,
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
);
}
通知点击事件处理
在lib/main.dart中,我们可以看到通知点击事件的处理逻辑:
// this function will be called when a push notification is recieved and show as alert dialog along with
// title and message body
Future notification(
BuildContext context, String title, String messageText) async {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
buttonPadding: EdgeInsets.all(10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)),
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0),
),
SizedBox(
height: 15.0,
),
Text(
messageText,
style: TextStyle(fontSize: 16.0),
)
],
),
actions: [
FlatButton(
onPressed: () => Navigator.pop(context), child: Text('Ok'))
],
);
});
}
对于本地通知,我们可以通过onDidReceiveNotificationResponse回调处理点击事件,实现页面跳转或其他交互逻辑。
调试与常见问题
通知不显示的排查步骤
- 检查权限:确保应用已获得通知权限
- 渠道配置:Android 8.0+ 必须配置通知渠道
- 日志分析:通过
adb logcat查看Android通知相关日志 - 插件版本:确保使用最新版插件,避免已知bug
常见问题解决方案
| 问题 | 解决方案 |
|---|---|
| Android通知权限被拒绝 | 在代码中添加权限请求逻辑,引导用户开启权限 |
| iOS通知在后台不触发 | 检查AppDelegate.swift中的通知处理代码 |
| 通知图标显示异常 | 确保图标资源符合平台规范,使用透明背景的图标 |
| 定时通知在设备重启后失效 | 实现BOOT_COMPLETED广播接收器,重新注册定时通知 |
总结与扩展
通过本文的介绍,我们了解了如何在Flutter应用中集成和使用本地通知功能。flutter-examples项目中的push_notifications模块虽然主要展示了远程推送实现,但我们可以基于其架构扩展本地通知功能。
进阶学习建议:
- 探索富媒体通知:添加图片、视频等多媒体内容
- 实现通知交互:通过按钮直接在通知中完成简单操作
- 通知样式定制:适配不同Android版本的通知样式
- 结合本地存储:记录通知历史和用户交互状态
完整的本地通知实现代码可以参考Flutter官方文档和flutter_local_notifications插件的示例项目,进一步丰富你的应用通知体验。
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00- QQwen3-Coder-Next2026年2月4日,正式发布的Qwen3-Coder-Next,一款专为编码智能体和本地开发场景设计的开源语言模型。Python00
xw-cli实现国产算力大模型零门槛部署,一键跑通 Qwen、GLM-4.7、Minimax-2.1、DeepSeek-OCR 等模型Go06
PaddleOCR-VL-1.5PaddleOCR-VL-1.5 是 PaddleOCR-VL 的新一代进阶模型,在 OmniDocBench v1.5 上实现了 94.5% 的全新 state-of-the-art 准确率。 为了严格评估模型在真实物理畸变下的鲁棒性——包括扫描伪影、倾斜、扭曲、屏幕拍摄和光照变化——我们提出了 Real5-OmniDocBench 基准测试集。实验结果表明,该增强模型在新构建的基准测试集上达到了 SOTA 性能。此外,我们通过整合印章识别和文本检测识别(text spotting)任务扩展了模型的能力,同时保持 0.9B 的超紧凑 VLM 规模,具备高效率特性。Python00
KuiklyUI基于KMP技术的高性能、全平台开发框架,具备统一代码库、极致易用性和动态灵活性。 Provide a high-performance, full-platform development framework with unified codebase, ultimate ease of use, and dynamic flexibility. 注意:本仓库为Github仓库镜像,PR或Issue请移步至Github发起,感谢支持!Kotlin08
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00