我不知道为什么我的自定义声音(大约 29 秒长)在通知触发后大约 8 秒后消失了。我应该调整哪些设置才能确保通知保持活动状态并发出 29 秒的声音?我需要修改 AppDelegate.swift 或 info.plist 吗?
NotificationChannel(
channelKey: "alarm_Category",
channelName: "alarm_Category",
channelDescription: 'Notification tests as alerts',
defaultColor: Colors.blue,
ledColor: Colors.white,
playSound: true,
onlyAlertOnce: false,
importance: NotificationImportance.Max,
soundSource: 'resource://raw/notification_sound',
criticalAlerts: true,
enableVibration: true,
enableLights: true,
ledOnMs: 1000,
ledOffMs: 500,
locked: true,
),
await AwesomeNotifications().createNotification(
content: NotificationContent(
category: NotificationCategory.Alarm,
fullScreenIntent: true,
backgroundColor: Colors.black,
id: subId,
channelKey: "alarm_Category",
title: DateFormat('yyyy.MM.dd HH:mm').format(currentNotificationTime),
body: 'Alarm Memo: ${schedule.enteredText}',
payload: {
'subId': subId.toString(),
'enteredText': schedule.enteredText,
'categoryIdentifier': "alarm_Category",
'identifier': "alarm_Category",
'channelKey': "alarm_Category",
'category': "alarm_Category",
},
displayOnForeground: true,
displayOnBackground: true,
autoDismissible: false,
locked: true,
icon: 'resource://drawable/ic_launcher',
customSound: 'resource://raw/notification_sound',
showWhen: true,
wakeUpScreen: true,
criticalAlert: true,
),
schedule: NotificationCalendar(
repeats: true,
preciseAlarm: true,
year: currentNotificationTime.year,
month: currentNotificationTime.month,
day: currentNotificationTime.day,
hour: currentNotificationTime.hour,
minute: currentNotificationTime.minute,
second: currentNotificationTime.second,
),
);
import UIKit
import Flutter
import UserNotifications
import AVFoundation
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Configure notification settings
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
let options: UNAuthorizationOptions = [
.alert,
.badge,
.sound,
.criticalAlert // Add critical alert permission
]
UNUserNotificationCenter.current().requestAuthorization(
options: options,
completionHandler: { _, _ in }
)
}
// Configure audio session
do {
try AVAudioSession.sharedInstance().setCategory(
.playback,
mode: .default,
options: [.mixWithOthers]
)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Failed to set audio session category: \(error)")
}
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
// Add UNNotificationSoundName extension
extension UNNotificationSoundName {
static let customSound = UNNotificationSoundName("notification_sound.wav")
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Other existing entries -->
<!-- Add background modes -->
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>fetch</string>
<string>remote-notification</string>
</array>
<!-- Add critical alerts entitlement -->
<key>com.apple.developer.usernotifications.critical-alerts</key>
<true/>
<!-- Add notification service extension -->
<key>com.apple.developer.usernotifications.time-sensitive</key>
<true/>
<!-- Configure audio session -->
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
</dict>
</plist>
import 'package:awesome_notifications/awesome_notifications.dart';
Future<void> initializeNotifications() async {
await AwesomeNotifications().initialize(
null,
[
NotificationChannel(
channelKey: "alarm_Category",
channelName: "Alarm Category",
channelDescription: 'Long duration alarm notifications',
defaultColor: Colors.blue,
ledColor: Colors.white,
playSound: true,
soundSource: 'resource://raw/notification_sound',
importance: NotificationImportance.Max,
criticalAlerts: true,
enableVibration: true,
enableLights: true,
locked: true,
// Add these settings for iOS
defaultRingtoneType: DefaultRingtoneType.Alarm,
channelShowBadge: true,
),
],
debug: true,
);
}
Future<void> scheduleAlarmNotification({
required int subId,
required DateTime scheduledTime,
required String memoText,
}) async {
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: subId,
channelKey: "alarm_Category",
title: DateFormat('yyyy.MM.dd HH:mm').format(scheduledTime),
body: 'Alarm Memo: $memoText',
category: NotificationCategory.Alarm,
notificationLayout: NotificationLayout.Default,
criticalAlert: true,
fullScreenIntent: true,
wakeUpScreen: true,
autoDismissible: false,
locked: true,
displayOnForeground: true,
displayOnBackground: true,
customSound: 'resource://raw/notification_sound',
// Add iOS specific settings
timeoutAfter: Duration(seconds: 30), // Extend timeout
payload: {
'sound_duration': '29', // Add sound duration info
'critical': 'true', // Mark as critical
},
),
schedule: NotificationCalendar(
repeats: true,
preciseAlarm: true,
allowWhileIdle: true,
year: scheduledTime.year,
month: scheduledTime.month,
day: scheduledTime.day,
hour: scheduledTime.hour,
minute: scheduledTime.minute,
second: scheduledTime.second,
),
);
}
在 Xcode 中创建新的通知服务扩展目标:
// NotificationService.swift
import UserNotifications
import AVFoundation
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
var audioPlayer: AVAudioPlayer?
override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Configure sound
if let soundDuration = request.content.userInfo["sound_duration"] as? String,
let soundPath = Bundle.main.path(forResource: "notification_sound", ofType: "wav") {
let soundUrl = URL(fileURLWithPath: soundPath)
bestAttemptContent.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "notification_sound.wav"))
// Setup audio session
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
audioPlayer = try AVAudioPlayer(contentsOf: soundUrl)
audioPlayer?.prepareToPlay()
audioPlayer?.play()
} catch {
print("Error setting up audio: \(error)")
}
}
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
if let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
ffmpeg -i input.mp3 -acodec pcm_s16le -ac 2 -ar 44100 notification_sound.wav
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.usernotifications.critical-alerts</key>
<true/>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>
// Check sound file properties
void validateSoundFile() {
final file = File('notification_sound.wav');
if (file.lengthSync() > 5 * 1024 * 1024) {
print('Warning: Sound file too large');
}
}
Future<bool> checkNotificationPermissions() async {
final status = await AwesomeNotifications().isNotificationAllowed();
if (!status) {
// Request permissions
return await AwesomeNotifications().requestPermissionToSendNotifications();
}
return status;
}
void testNotification() async {
final now = DateTime.now();
await scheduleAlarmNotification(
subId: 1,
scheduledTime: now.add(Duration(seconds: 5)),
memoText: 'Test notification',
);
}
记住:
您希望我更详细地解释任何部分吗?