【问题标题】:Local notification sound not playing while app in background - Swift应用程序在后台时本地通知声音不播放 - Swift
【发布时间】:2021-10-11 13:08:09
【问题描述】:

我正在制作一个闹钟应用程序,并且我已确认我的闹钟通知被正确触发,但声音并不总是按我预期的那样播放。

例如,当手机处于静音模式时,通知会成功播放声音(好的,太好了!)。但是,当手机处于静音模式时,声音不会播放,即使应用程序仍在后台运行(不太好......)。

我知道静音模式应该使所有通知声音静音,但我已经从 App Store 下载了其他闹钟应用程序(如 Alarmy),即使手机也能以某种方式播放通知声音只要应用程序仍在后台运行,就处于静音模式。只有当应用程序完全退出时,静音模式才会生效。

有谁知道如何实现这个结果?我需要在我的代码或 plist 文件中声明一些设置或选项吗?我已经搜索了互联网,但没有找到任何关于这个特定问题的信息......

我设置 AVAudioSession 类别的代码:

private func setAudioCategory() {
    do {
        // Enable sound (even while in silent mode) as long as app is in foreground.
        try AVAudioSession.sharedInstance().setCategory(.playback)
    }
    catch {
        print(error.localizedDescription)
    }
}

我设置通知的代码:

/// Sets a local user notification for the provided `Alarm` object.
static func set(_ alarm: Alarm) {

    // Configure the notification's content.
    let content = UNMutableNotificationContent()
    content.title = NSString.localizedUserNotificationString(forKey: K.Keys.notificationTitle, arguments: nil)
    content.body = NSString.localizedUserNotificationString(forKey: K.Keys.notificationBody, arguments: nil)

    // Get sound name
    let soundName: String = UserDefaultsManager.getAlarmSound().fileNameFull
        
    // Set sound
    content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: soundName))
    content.categoryIdentifier = "Alarm"

    // Configure the time the notification should occur.
    var date = DateComponents()
    date.hour = alarm.hour
    date.minute = alarm.minute

    // Create the trigger & request
    let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: false)
    let request = UNNotificationRequest(identifier: alarm.notifID, content: content, trigger: trigger)

    // Schedule the request with the system.
    let notificationCenter = UNUserNotificationCenter.current()
    notificationCenter.add(request, withCompletionHandler: { error in
        if error != nil {
            // TODO: Show Alert for Error
            return
        }
    })
}

【问题讨论】:

  • 事实上,您冒着被 Apple 在审核期间拒绝您的应用程序的风险,因为框架不允许您的应用程序在静音模式下运行声音。但如果你仍然想冒险,看看这个:andrewmarinov.com/building-an-alarm-app-on-ios
  • 不幸的是,将音频会话设置为 .playAndRecord 并在 .plist 文件中为 Required Background Modes 启用音频似乎不起作用...(来自链接文章中的“麦克风方法”)。
  • 声音文件长度不能超过30秒。
  • @Ramis 指出。该文件在不处于静音模式时已经正确播放,所以这不是问题。
  • @Climbatize 感谢您的贡献。如果您好奇我是如何解决的,请查看下面的答案。

标签: ios swift nsnotificationcenter avaudiosession usernotifications


【解决方案1】:

所以我发现了一些东西。

正如问题所述,当手机处于静音模式时,目前无法在本地通知中播放声音。

不过,好消息!

实际上有一个不同的方法可以达到相同的结果; Alarmy 之类的应用就是这样做的。

注意:我(终于)从this wonderful SO answer 发现了这个解决方案,但我会在此总结以供参考。

简而言之,本地通知不会播放声音,而是应用会播放它(在后台)。

步骤

  1. 您必须启用该应用才能在后台播放声音。为此,导航到您的.plist 文件并将字符串值App plays audio or streams audio/video using AirPlay 添加到数组键Required background modes。 (这也可以在您的应用程序的Capabilities 中实现 - 它做同样的事情)。

  2. 在您的 App Delegate 中,将 AVAudioSession 的类别设置为 .playBack,这样即使手机处于锁定状态或在后台,声音仍会播放。

do {
    try AVAudioSession.sharedInstance().setCategory(.playAndRecord)
    try AVAudioSession.sharedInstance().setActive(true)
} catch {
    print(error.localizedDescription)
}
  1. 在您希望播放的时间启动您的 AVAudioPlayer(在我的情况下,在我的本地通知时)。​​
let timeInterval = 60.0 // 60.0 would represent 1 minute from now
let timeOffset = audioPlayer.deviceCurrentTime + timeInverval
audioPlayer.play(atTime: timeOffset) // This is the magic function

// Note: the `timeInterval` must be added to the audio player's 
// `.deviceCurrentTime` to calculate a correct `timeOffset` value.

总之,正如我在上面链接的 SO 答案如此恰当地总结的那样:

这不会在后台播放静音,这违反了Apple的规则。它实际上启动了播放器,但音频只会在正确的时间开始。我认为这可能是 Alarmy 实现警报的方式,因为它不是触发音频的远程通知,也不是本地通知播放的音频(因为它不限于 30 秒或被铃声开关静音)。

【讨论】:

  • 很好,很高兴您终于解决了您的问题,请小心提交 AppStore ;)
  • 这不会停止用户正在播放的任何其他音频吗?说他们是否在听音乐
  • @MorBlau 当然,当闹钟响起时,这不是您想要的吗?但是,如果您想要不同的音频结果(例如.mixWithOthers.duckOthers等),您可以在设置应用程序的AVAudioSession类别时配置other options
猜你喜欢
  • 1970-01-01
  • 2017-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-20
  • 1970-01-01
  • 1970-01-01
  • 2013-04-22
相关资源
最近更新 更多