Ios 我如何允许背景音乐继续播放,而我的应用程序在使用Swift时仍播放其声音

Ios 我如何允许背景音乐继续播放,而我的应用程序在使用Swift时仍播放其声音,ios,xcode,swift,audio,mobile,Ios,Xcode,Swift,Audio,Mobile,我创建了一个应用程序,我试图允许用户在玩我的游戏时继续听他们的音乐,但每当他们点击“播放”时,ingame声音就会停止背景音乐。我正在使用Swift开发iOS。下面是一段启动ingame声音的代码 func playSpawnedDot() { var alertSound: NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("spawnDot", ofType: "mp3")!)! var

我创建了一个应用程序,我试图允许用户在玩我的游戏时继续听他们的音乐,但每当他们点击“播放”时,ingame声音就会停止背景音乐。我正在使用Swift开发iOS。下面是一段启动ingame声音的代码

func playSpawnedDot() {
    var alertSound: NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("spawnDot", ofType: "mp3")!)!
    var error:NSError?
    audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
    audioPlayer.prepareToPlay()

    if volumeBool {
        audioPlayer.play()
    }
}

您需要使用以下值之一设置
AVAudioSession
类别:(AVAudioSession类引用)

默认值设置为
AVAudioSessionCategorySoloAmbient
。正如你所看到的:

[…]使用此类别意味着您的应用程序的音频不可混合激活您的会话将中断任何其他也不可混合的音频会话。要允许混合,请改用
AVAudioSessionCategoryAmbient
类别

在播放声音之前,您必须更改类别。为此:

AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)

你不需要在每次播放声音时都拨这些线。您可能只想执行一次。

以下是我在Swift 2.0中使用的内容:

let sess = AVAudioSession.sharedInstance()
if sess.otherAudioPlaying {
    _ = try? sess.setCategory(AVAudioSessionCategoryAmbient, withOptions: .DuckOthers)
    _ = try? sess.setActive(true, withOptions: [])
}
请注意,如果您不想降低背景音乐的音量而改为在上面播放,可以将
.DuckOthers
替换为
[]

**

更新为Swift 3.0 **

我正在播放的声音的名称是shatter.wav

func shatterSound() {
    if let soundURL = Bundle.main.url(forResource: "shatter", withExtension: "wav") {
        var mySound: SystemSoundID = 0
        AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
        AudioServicesPlaySystemSound(mySound);
    }
}
然后你想在哪里播放声音呼叫

shatterSound()

lchamp的解决方案非常适合我,适用于Objective-C:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];

我在Swift 3.0中就是这样做的

var songPlayer : AVAudioPlayer?         

func SetUpSound() {


        if let path = Bundle.main.path(forResource: "TestSound", ofType: "wav") {
            let filePath = NSURL(fileURLWithPath:path)
            songPlayer = try! AVAudioPlayer.init(contentsOf: filePath as URL)
            songPlayer?.numberOfLoops = -1 //logic for infinite loop
            songPlayer?.prepareToPlay()
            songPlayer?.play()
        }

        let audioSession = AVAudioSession.sharedInstance()
        try!audioSession.setCategory(AVAudioSessionCategoryPlayback, with: AVAudioSessionCategoryOptions.duckOthers) //Causes audio from other sessions to be ducked (reduced in volume) while audio from this session plays  
}

您可以在此处查看更多AvaudioSessionCategory选项:

如果您想播放警报声音:

public func playSound(withFileName fileName: String) {

    if let soundUrl = Bundle.main.url(forResource: fileName, withExtension: "wav") {
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, with:[.duckOthers])
            try AVAudioSession.sharedInstance().setActive(true)

            var soundId: SystemSoundID = 0

            AudioServicesCreateSystemSoundID(soundUrl as CFURL, &soundId)
            AudioServicesAddSystemSoundCompletion(soundId, nil, nil, { (soundId, clientData) -> Void in
                AudioServicesDisposeSystemSoundID(soundId)
                do {
                    // This is to unduck others, make other playing sounds go back up in volume
                    try AVAudioSession.sharedInstance().setActive(false)
                } catch {
                    DDLogWarn("Failed to set AVAudioSession to inactive. error=\(error)")
                }
            }, nil)

            AudioServicesPlaySystemSound(soundId)
        } catch {
            DDLogWarn("Failed to create audio player. soundUrl=\(soundUrl) error=\(error)")
        }
    } else {
        DDLogWarn("Sound file not found in app bundle. fileName=\(fileName)")
    }
}
如果你想播放音乐:

进口AVF基金会

var audioPlayer:AVAudioPlayer?

public func playSound(withFileName fileName: String) {

    if let soundUrl = Bundle.main.url(forResource: fileName, withExtension: "wav") {
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, with:[.duckOthers])
            try AVAudioSession.sharedInstance().setActive(true)

            let player = try AVAudioPlayer(contentsOf: soundUrl)
            player.delegate = self
            player.prepareToPlay()
            DDLogInfo("Playing sound. soundUrl=\(soundUrl)")
            player.play()
            // ensure the player does not get deleted while playing the sound
            self.audioPlayer = player
        } catch {
            DDLogWarn("Failed to create audio player. soundUrl=\(soundUrl) error=\(error)")
        }
    } else {
        DDLogWarn("Sound file not found in app bundle. fileName=\(fileName)")
    }
}

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    self.audioPlayer?.stop()
    do {
        // This is to unduck others, make other playing sounds go back up in volume
        try AVAudioSession.sharedInstance().setActive(false)
    } catch {
        DDLogWarn("Failed to set AVAudioSession inactive. error=\(error)")
    }
}

Swift 4版本:

try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
try? AVAudioSession.sharedInstance().setActive(true)
对于Swift(目标C也是这样)

您可以使用链接获得最佳答案,如果您没有时间观看10分钟,最好的做法是在
AppDelegate
复制
下面的代码
,然后选择
项目的目标
,然后转到
功能
,最后进入
背景模式
检查
音频、播放和画中画

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    let session = AVAudioSession.sharedInstance()
    do {
        try session.setCategory(AVAudioSessionCategoryPlayback)
    }
    catch {

    }
}

我不认为仅仅将AVAudioSession设置为AVAudioSessionCategoryOptions.duckOthers就行了,但它确实行了。这是我帮助像我这样的新手的全部代码

Swift 4-完整示例

var audioPlayer = AVAudioPlayer()


func playSound(sound: String){
    let path = Bundle.main.path(forResource: sound, ofType: nil)!
    let url = URL(fileURLWithPath: path)

    let audioSession = AVAudioSession.sharedInstance()
    try!audioSession.setCategory(AVAudioSessionCategoryPlayback, with: AVAudioSessionCategoryOptions.duckOthers)

    do {
        audioPlayer = try AVAudioPlayer(contentsOf: url)
        audioPlayer.play()
    } catch {
        print("couldn't load the file")
    }
}

我仍然需要弄清楚setActive(),但当我离开应用程序时,音频停止闪避,因此它适用于我的应用程序

因为他们似乎无法从一个版本到另一个版本下定决心。这里是Swift 5.0

do{
   try AVAudioSession.sharedInstance().setCategory(.ambient)
   try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
} catch {
   NSLog(error.localizedDescription)
}

Swift 5版本基于lchamp的答案

try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.ambient)
try? AVAudioSession.sharedInstance().setActive(true)

这在iOS 14.4和Swift 5上非常适合我。使用
.duckOthers
选项(如果您愿意,也可以使用
.mixWithOthers
直接与声音混合),答案与其他答案略有不同,但在播放音乐时效果非常好。它将降低音乐音量,播放“嘟嘟”声,然后将音乐音量恢复正常。如果出现问题,它还会使用Google Firebase Crashlytics捕获错误数据,并尝试将卷提高到正常水平,即使出现错误

这段代码也可以完美地在第一次和所有其他声音播放时使用,而不会停止音乐

func playSound() {
    do {
        if let path = Bundle.main.path(forResource: "beep", ofType: "mp3") {
            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: .duckOthers)
            try AVAudioSession.sharedInstance().setActive(true)
            
            let filePath = NSURL(fileURLWithPath:path)
            songPlayer = try AVAudioPlayer.init(contentsOf: filePath as URL)
            songPlayer?.numberOfLoops = 0
            songPlayer?.prepareToPlay()
            songPlayer?.play()
            
            try AVAudioSession.sharedInstance().setActive(false)
        }
    } catch (let error) {
        try? AVAudioSession.sharedInstance().setActive(false)
        Crashlytics.crashlytics().setCustomValue(error.localizedDescription, forKey: "audio_playback_error")
    }
}

“其他人”答案没有的一个重要内容是,在停用时,您需要使用.notifyOthers标志调用false:

try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)

这样做的原因是,其他在后台播放音乐的应用程序在你停用自己的应用程序时会知道何时重新打开它们的音频。否则,如果您关闭会话,您的背景音乐将无法打开。

这在swift 2.0中不再有效。是否有任何更新的代码?这对我很有效,请执行{try AVAudioSession.sharedInstance().setCategory(AvaudioSessionCategoryMBient)try AVAudioSession.sharedInstance().setActive(true)}捕获错误为NSError{print(error)}如果您在将此代码改编为较新版本的Swift时遇到问题,请尝试使用以下内容:
try?AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.ambient)
播放完声音后,不要忘记导入AVFoundation
不要忘记将
设置为false,否则,即使在播放完成后背景音乐也会保留。移动(让audioSession…)和(try!audioSession…)将行添加到if条件上方以获得更好的效果。背景音乐也不会第一次停止。(我在按钮操作中插入了func SetUpSound()代码)@Hamid Reza Ansari-您的评论挽救了我的一天。谢谢!这不会在不播放声音的情况下立即停用音频会话吗?