iOS 通知声音设置

问题描述 投票:0回答:1

我不知道为什么我的自定义声音(大约 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,
        ),
      );
ios flutter notifications
1个回答
0
投票

解决方案

1.在 AppDelegate.swift 中配置 UNNotificationSound

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")
}

2.更新信息.plist

<?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>

3.更新 Flutter 通知配置

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,
    ),
  );
}

4.添加音频处理扩展

在 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)
        }
    }
}

5.声音文件要求

  1. 将声音文件转换为 WAV 格式:
ffmpeg -i input.mp3 -acodec pcm_s16le -ac 2 -ar 44100 notification_sound.wav
  1. 将声音文件添加到两者中:
  • 主要应用程序包
  • 通知服务扩展包

6.权限配置

  1. 将权利文件添加到您的项目中
  2. 启用这些功能:
    • 背景模式
    • 重要警报
    • 推送通知
<?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>

最佳实践

  1. 声音文件优化
// Check sound file properties
void validateSoundFile() {
  final file = File('notification_sound.wav');
  if (file.lengthSync() > 5 * 1024 * 1024) {
    print('Warning: Sound file too large');
  }
}
  1. 错误处理
Future<bool> checkNotificationPermissions() async {
  final status = await AwesomeNotifications().isNotificationAllowed();
  if (!status) {
    // Request permissions
    return await AwesomeNotifications().requestPermissionToSendNotifications();
  }
  return status;
}
  1. 测试
void testNotification() async {
  final now = DateTime.now();
  await scheduleAlarmNotification(
    subId: 1,
    scheduledTime: now.add(Duration(seconds: 5)),
    memoText: 'Test notification',
  );
}

记住:

  • 在真实 iOS 设备上测试
  • 请求关键警报权限
  • 正确处理音频会话
  • 优化声音文件大小
  • 考虑电池影响

您希望我更详细地解释任何部分吗?

© www.soinside.com 2019 - 2024. All rights reserved.