在移动应用开发中,通知功能就像是你和用户之间的"小纸条"。想象一下,当用户离开你的应用后,如何继续保持联系?这就是本地通知大显身手的时候了。flutter_local_notifications插件让Flutter开发者能够轻松实现这个功能,而且比你想的更强大。
我刚开始用这个插件时,以为它只能发些简单的提醒。后来发现,它不仅能显示常规通知,还能处理长文本、大图片甚至媒体播放控制。最棒的是,它完美支持Android和iOS双平台,用同一套代码就能搞定。不过要注意,两个平台的表现确实有些差异,这点我们后面会详细说。
首先,把插件添加到你的项目里。打开pubspec.yaml文件,或者直接在终端运行:
bash复制flutter pub add flutter_local_notifications
别忘了iOS需要额外配置。打开ios/Runner/Info.plist,添加这些权限声明:
xml复制<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
Android的配置稍微复杂些。确保你的android/app/src/main/AndroidManifest.xml里有这些权限:
xml复制<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
初始化是很多新手容易踩坑的地方。我建议创建一个单独的NotificationHelper类来管理通知逻辑。下面是我的初始化代码模板:
dart复制Future<void> initialize() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
const DarwinInitializationSettings initializationSettingsIOS =
DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
final InitializationSettings initializationSettings =
InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
await _notificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (details) {
// 处理通知点击事件
},
);
}
特别注意:Android 13+需要动态请求通知权限。我建议在应用启动时就处理:
dart复制Future<void> requestPermissions() async {
if (Platform.isAndroid) {
await _notificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.requestPermission();
}
}
发送一个基础通知其实很简单,但有几个关键参数需要注意:
dart复制Future<void> showBasicNotification() async {
const AndroidNotificationDetails androidDetails =
AndroidNotificationDetails(
'channel_id',
'频道名称',
channelDescription: '频道描述',
importance: Importance.max,
priority: Priority.high,
showWhen: true,
);
const DarwinNotificationDetails iosDetails =
DarwinNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
);
const NotificationDetails platformDetails =
NotificationDetails(
android: androidDetails,
iOS: iosDetails,
);
await _notificationsPlugin.show(
0, // 通知ID,必须是唯一的
'这是标题',
'这是内容正文',
platformDetails,
);
}
这里有几个实用技巧:
定时通知特别适合提醒类应用。我推荐使用timezone包处理时区问题:
dart复制flutter pub add timezone
然后初始化时区信息:
dart复制tz.initializeTimeZones();
final location = tz.getLocation('Asia/Shanghai');
实现一个定时通知:
dart复制Future<void> scheduleNotification() async {
final scheduledTime = tz.TZDateTime.now(location).add(Duration(minutes: 30));
await _notificationsPlugin.zonedSchedule(
1,
'预定通知',
'这是30分钟后触发的通知',
scheduledTime,
const NotificationDetails(
android: AndroidNotificationDetails(
'channel_id',
'频道名称',
channelDescription: '频道描述',
),
),
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
androidAllowWhileIdle: true, // 即使设备休眠也触发
);
}
周期通知也很实用,比如每日提醒:
dart复制await _notificationsPlugin.periodicallyShow(
2,
'每日提醒',
'这是你的每日提醒',
RepeatInterval.daily,
const NotificationDetails(
android: AndroidNotificationDetails(
'reminder_channel',
'提醒频道',
),
),
);
Android支持丰富的通知样式。长文本通知特别适合新闻类应用:
dart复制final bigTextStyle = BigTextStyleInformation(
'这里是长文本内容,可以包含多行文字。'
'当内容超过一定长度时,通知会自动展开显示完整内容。'
'非常适合显示文章摘要或详细通知内容。',
htmlFormatBigText: true,
contentTitle: '展开后的标题',
htmlFormatContentTitle: true,
summaryText: '摘要文本',
htmlFormatSummaryText: true,
);
final androidDetails = AndroidNotificationDetails(
'big_text_channel',
'长文本频道',
styleInformation: bigTextStyle,
);
大图片通知则能吸引更多注意力:
dart复制final bigPictureStyle = BigPictureStyleInformation(
FilePathAndroidBitmap('path/to/image.jpg'),
largeIcon: FilePathAndroidBitmap('path/to/icon.jpg'),
contentTitle: '图片标题',
summaryText: '图片描述',
);
final androidDetails = AndroidNotificationDetails(
'big_picture_channel',
'大图频道',
styleInformation: bigPictureStyle,
);
音乐播放器类应用会用到媒体控制通知:
dart复制final mediaStyle = MediaStyleInformation(
showWhen: false,
showCancelButton: true,
cancelButtonIcon: AndroidResource(name: 'ic_cancel'),
actions: [
MediaAction(
action: MediaAction.play,
icon: AndroidResource(name: 'ic_play'),
),
MediaAction(
action: MediaAction.pause,
icon: AndroidResource(name: 'ic_pause'),
),
],
);
final androidDetails = AndroidNotificationDetails(
'media_channel',
'媒体频道',
styleInformation: mediaStyle,
);
进度条通知适合文件下载场景:
dart复制final progress = 75; // 进度百分比
final androidDetails = AndroidNotificationDetails(
'progress_channel',
'进度频道',
showProgress: true,
maxProgress: 100,
progress: progress,
indeterminate: false,
);
iOS的通知样式相对受限,但也能实现一些定制:
dart复制final iosDetails = DarwinNotificationDetails(
attachments: [
DarwinNotificationAttachment(
'path/to/image.jpg',
identifier: 'image1',
),
],
threadIdentifier: 'thread1',
summaryArgument: '3条新消息',
categoryIdentifier: 'message',
);
经过多个项目实践,我总结了这些主要差异点:
| 特性 | Android | iOS |
|---|---|---|
| 通知样式 | 支持多种样式 | 样式有限 |
| 通知分组 | 支持 | 需要特殊处理 |
| 通知优先级 | 有多个级别 | 只有普通和重要 |
| 通知声音 | 可自定义 | 有限制 |
| 通知图标 | 必须使用透明背景 | 使用应用图标 |
问题1:通知不显示
问题2:通知点击无响应
问题3:Android通知图标显示为白色方块
问题4:iOS通知声音不工作