如何在 iOS 10 中播放声音,当应用程序处于后台且 Swift 3

How to play sounds in iOS 10 when app is in the background with Swift 3

我正在开发一个锻炼应用程序,该应用程序需要能够在应用程序进入后台以及屏幕锁定时播放声音。我还需要允许其他应用程序播放声音(例如音乐),同时还允许我的音效通过。

我在 iOS 9 中通过使用 AVAudioSessionCategoryAmbient 实现了此功能,但是一旦我的应用程序变为非活动状态或屏幕锁定,声音就会停止。

这是我在演示应用程序中的代码的简化版本:

import UIKit
import AVFoundation

class ViewController: UIViewController {

var session: AVAudioSession = AVAudioSession.sharedInstance()
var timer = Timer()
let countdownSoundFile = "154953__keykrusher__microwave-beep"
let countdownSoundExt = "wav"
var audioPlayer = AVAudioPlayer()

override func viewDidLoad() {
    super.viewDidLoad()

    activateAudio()

}

func activateAudio() {
        _ = try? session.setCategory(AVAudioSessionCategoryAmbient, with: [])
        _ = try? session.setActive(true, with: [])
}

@IBAction func play() {
    timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(ViewController.playSound), userInfo: nil, repeats: true)
}

func playSound() {

    if let soundURL = Bundle.main.url(forResource: countdownSoundFile, withExtension: countdownSoundExt) {
        do {

            print("sound playing")
            try audioPlayer = AVAudioPlayer(contentsOf: soundURL)
            audioPlayer.prepareToPlay()
            audioPlayer.play()
        } catch {
            print("no sound found")
        }
    }

}
}

我还检查了后台模式中的 Audio, Airplay, and Picture in Picture 功能,它向我的 plist 添加了必需的后台模式。

我正在设备上对此进行测试,一旦我锁定屏幕或按下主页按钮,我的声音就会停止,一旦我的应用程序再次激活它们就会恢复。

我找到了一个解决方法:

var mySound: SystemSoundID = 0
AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
AudioServicesPlaySystemSound(mySound);

但这不允许更改声音的音量,而且我还需要使用 AVSpeechSynthesizer,而此解决方法对此不起作用。

关于我可以做些什么来完成这项工作有什么想法吗?

编辑:

我将类别行更改为 _ = try? session.setCategory(AVAudioSessionCategoryPlayback, with: [.mixWithOthers]),这允许在应用 运行 时播放音乐,但是当屏幕锁定或进入后台时,声音仍然停止。我需要声音在这些场景中继续播放。

编辑:

正如答案所指出的,当我的应用程序处于后台时我无法播放声音,但使用 _ = try? session.setCategory(AVAudioSessionCategoryPlayback, with: [.mixWithOthers]) 确实允许在屏幕关闭时播放声音并与其他应用程序的声音(音乐)混合。

您不能使用环境音频会话类别在后台播放。您的类别必须是播放。

要允许来自其他应用程序的声音播放,请使用混合选项修改您的播放类别 (.mixWithOthers)。

(另外请记住,您可以随时更改您的类别。您可以在大多数时间将其设置为环境,但当您知道您将要进入后台时切换到播放,这样您就可以继续玩。)

EDIT 我还想到还有另一个可能需要澄清的误解。在后台时,您不能(轻易地)启动新声音。背景音频允许您做的就是当您的应用程序进入后台时继续播放当前声音。一旦声音停止(在后台),您的应用程序就会暂停,这就是结束。

在此处查看详细信息。您还需要从应用程序设置中启用音频模式。

do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)
print("AVAudioSession Category Playback OK")
do {
    try AVAudioSession.sharedInstance().setActive(true)
    print("AVAudioSession is Active")
} catch {
    print(error)
}
} catch {
print(error)
}