如何为Flutter本地通知设置基于任务名称的自定义语音提示音
实现动态任务名称语音通知方案
针对你开发的视障人群任务管理App,要实现通知提示音随任务名称动态变化,核心是为每个任务生成专属语音文件,并在通知触发时调用对应文件。以下是具体修改方案:
1. 依赖准备
添加path_provider依赖用于获取应用私有存储路径(避免权限问题),在pubspec.yaml中添加:
dependencies: path_provider: ^2.1.2
2. 修改任务添加逻辑,生成唯一语音文件
在AddTasksscreen的onDoubleTap方法中,为每个任务生成唯一语音文件,并将文件路径存入数据库:
onDoubleTap: () async { // 生成唯一文件名(用时间戳避免重复) String soundFileName = "task_${DateTime.now().millisecondsSinceEpoch}.mp3"; // 获取应用私有存储目录 Directory appDir = await getApplicationDocumentsDirectory(); String soundFilePath = "${appDir.path}/$soundFileName"; // 生成任务名称的语音文件 await Tts.synthesizeToFile(titleController.text, soundFilePath); // 插入任务时同步存储音频文件名 int response = await sqlDb.insertdataToDatabase(''' INSERT INTO tasks ( title , description , date, sound_file ) VALUES ("${titleController.text}","${descriptionController.text}","${dateController.text}","$soundFileName") '''); if (response > 0) { Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (context) => TasksListScreen()), (route) => false); // 调用通知服务时传入音频文件路径 NotificationService().scheduleNotification( id: bookcubit.get(context).id, title: titleController.text, body: descriptionController.text, soundFilePath: soundFilePath, DataTime: DateTime.parse(dateController.text)); } }
3. 更新NotificationService,支持动态声音
修改NotificationService类,让通知配置可以接收动态音频文件路径,适配Android和iOS平台:
class NotificationService { final FlutterLocalNotificationsPlugin notificationsPlugin = FlutterLocalNotificationsPlugin(); Future<void> initNotification() async { AndroidInitializationSettings initializationSettingsAndroid = const AndroidInitializationSettings('appicon'); var initializationSettingsIOS = DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, onDidReceiveLocalNotification: (int id, String? title, String? body, String? payload) async {}); var initializationSettings = InitializationSettings( android: initializationSettingsAndroid, iOS: initializationSettingsIOS); await notificationsPlugin.initialize(initializationSettings, onDidReceiveNotificationResponse: (NotificationResponse notificationResponse) async {}); } // 动态生成通知配置,支持传入音频路径 Future<NotificationDetails> notificationDetails({String? soundFilePath}) async { AndroidNotificationDetails androidDetails; if (soundFilePath != null) { // Android使用Uri指向应用内存储的音频文件 androidDetails = AndroidNotificationDetails( 'channelId', 'channelName', importance: Importance.max, sound: UriAndroidNotificationSound(Uri.parse(soundFilePath)), ); } else { androidDetails = const AndroidNotificationDetails( 'channelId', 'channelName', importance: Importance.max, ); } DarwinNotificationDetails iosDetails; // iOS建议利用系统VoiceOver自动播报通知内容,自定义声音需满足格式/目录要求 iosDetails = DarwinNotificationDetails( subtitle: title, // VoiceOver会自动播报通知标题和内容 sound: soundFilePath?.split('/').last, // 需将文件放到Library/Sounds目录才生效 ); return NotificationDetails(android: androidDetails, iOS: iosDetails); } Future showNotification( {int id = 0, String? title, String? body, String? payLoad, String? soundFilePath}) async { SqlDb db = SqlDb(); await db.deleteDatabase('DELETE FROM tasks WHERE id = $id'); return notificationsPlugin.show( id, title, body, await notificationDetails(soundFilePath: soundFilePath)); } Future scheduleNotification({ int? id, String? title, String? body, String? payload, required DateTime DataTime, String? soundFilePath, }) async { return notificationsPlugin.zonedSchedule( id!, title, body, tz.TZDateTime.from( DataTime, tz.local, ), await notificationDetails(soundFilePath: soundFilePath), androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime); } }
4. 数据库结构调整
需要给tasks表新增sound_file字段,用于存储音频文件名:
ALTER TABLE tasks ADD COLUMN sound_file TEXT;
5. 可选:清理过期音频文件
为避免存储冗余,删除任务时同步删除对应的语音文件:
Future<void> deleteTaskWithSound(int taskId, String soundFileName) async { SqlDb db = SqlDb(); await db.deleteDatabase('DELETE FROM tasks WHERE id = $taskId'); Directory appDir = await getApplicationDocumentsDirectory(); String soundFilePath = "${appDir.path}/$soundFileName"; File soundFile = File(soundFilePath); if (await soundFile.exists()) { await soundFile.delete(); } }
注意事项
- Android平台:动态生成的音频文件存储在应用私有目录,无需额外权限
- iOS平台:自定义通知声音需满足格式(.aiff/.wav/.caf)、大小(≤30秒),且需放到
Library/Sounds目录;更推荐依赖系统VoiceOver自动播报通知内容,无需额外生成音频
内容的提问来源于stack exchange,提问作者Amar Mira
相关产品推荐
相关产品推荐

