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

时间:2023-02-10 01:26:17

I created an app and I am attempting to allow the user to continue to listen to their music while playing my game, but whenever they hit "play" and the ingame sounds occur it will stop the background music. I am developing on iOS using Swift. Here is a piece of the code that initiates the ingame sounds.

我创建了一个应用程序,我试图让用户在玩我的游戏时继续听他们的音乐,但是每当他们点击“play”时,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()
    }
}

8 个解决方案

#1


38  

You need to set the AVAudioSession category, with one of the following value: https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html (AVAudioSession Class Reference).

您需要设置AVAudioSession类别,其值如下:https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html (AVAudioSession类引用)。

The default value is set to AVAudioSessionCategorySoloAmbient. As you can read :

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

[...] using this category implies that your app’s audio is nonmixable—activating your session will interrupt any other audio sessions which are also nonmixable. To allow mixing, use the AVAudioSessionCategoryAmbient category instead.

[…使用这个类别意味着你的应用程序的音频是不可混合的-激活你的会话将中断任何其他也不可混合的音频会话。为了允许混合,使用AVAudioSessionCategoryAmbient类别代替。

You have to change the category, before you play your sound. To do so :

在播放声音之前,你必须改变类别。这样做:

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

You don't need to call those line each time you play the sound. You might want to do it only once.

你不需要在每次播放声音时都调用这些线。你可能只需要做一次。

#2


11  

This is how I do it in Swift 3.0

这就是我在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  
}

You can see more of AVAudioSessionCategoryOptions here: https://developer.apple.com/reference/avfoundation/avaudiosessioncategoryoptions

您可以在这里看到更多的AVAudioSessionCategoryOptions: https://developer.apple.com/reference/avfoundation/avaudiosessioncategoryoptions。

#3


9  

Here's what I am using for Swift 2.0:

以下是我使用的Swift 2.0版本:

let sess = AVAudioSession.sharedInstance()
if sess.otherAudioPlaying {
    _ = try? sess.setCategory(AVAudioSessionCategoryAmbient, withOptions: .DuckOthers)
    _ = try? sess.setActive(true, withOptions: [])
}

Please note that you can replace .DuckOthers with [] if you don't want to lower background music and instead play on top to it.

请注意,如果不想降低背景音乐的音量,可以用[]替换. duckothers。

#4


8  

Swift 4 version:

斯威夫特4版本:

try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
try? AVAudioSession.sharedInstance().setActive(true)

#5


5  

lchamp's solution worked perfectly for me, adapted for Objective-C:

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

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

[[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryAmbient错误:nil);[[AVAudioSession sharedInstance]setActive:是的错误:nil);

#6


2  

**

* *

Updated for Swift 3.0

**

* *

The name of the sound I am playing is shatter.wav

我演奏的声音的名字是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);
    }
}

Then where ever you want to play the sound call

无论你想在哪里播放声音

shatterSound()

#7


1  

If you want to play an alert sound:

如果你想播放警报:

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

And if you want to play music:

如果你想演奏音乐:

import AVFoundation

进口AVFoundation

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

#8


1  

For Swift (Objective-C like this too)

对于Swift (Objective-C也像这样)

you can use this link for best answer and if you don't have any time for watching 10 minutes the best action is that you just copy below code in your AppDelegate in didFinishLaunchingWithOptions and then select your project's target then go to Capabilities and at last in Background modes check on Audio, AirPlay and Picture in Picture

你可以使用这个链接最好的答案,如果你没有时间看10分钟最好的行动就是你复制下面代码AppDelegate didFinishLaunchingWithOptions然后选择您的项目的目标然后去功能,最后在后台模式检查音频、播送、画中画

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 {

    }
}

#1


38  

You need to set the AVAudioSession category, with one of the following value: https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html (AVAudioSession Class Reference).

您需要设置AVAudioSession类别,其值如下:https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html (AVAudioSession类引用)。

The default value is set to AVAudioSessionCategorySoloAmbient. As you can read :

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

[...] using this category implies that your app’s audio is nonmixable—activating your session will interrupt any other audio sessions which are also nonmixable. To allow mixing, use the AVAudioSessionCategoryAmbient category instead.

[…使用这个类别意味着你的应用程序的音频是不可混合的-激活你的会话将中断任何其他也不可混合的音频会话。为了允许混合,使用AVAudioSessionCategoryAmbient类别代替。

You have to change the category, before you play your sound. To do so :

在播放声音之前,你必须改变类别。这样做:

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

You don't need to call those line each time you play the sound. You might want to do it only once.

你不需要在每次播放声音时都调用这些线。你可能只需要做一次。

#2


11  

This is how I do it in Swift 3.0

这就是我在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  
}

You can see more of AVAudioSessionCategoryOptions here: https://developer.apple.com/reference/avfoundation/avaudiosessioncategoryoptions

您可以在这里看到更多的AVAudioSessionCategoryOptions: https://developer.apple.com/reference/avfoundation/avaudiosessioncategoryoptions。

#3


9  

Here's what I am using for Swift 2.0:

以下是我使用的Swift 2.0版本:

let sess = AVAudioSession.sharedInstance()
if sess.otherAudioPlaying {
    _ = try? sess.setCategory(AVAudioSessionCategoryAmbient, withOptions: .DuckOthers)
    _ = try? sess.setActive(true, withOptions: [])
}

Please note that you can replace .DuckOthers with [] if you don't want to lower background music and instead play on top to it.

请注意,如果不想降低背景音乐的音量,可以用[]替换. duckothers。

#4


8  

Swift 4 version:

斯威夫特4版本:

try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
try? AVAudioSession.sharedInstance().setActive(true)

#5


5  

lchamp's solution worked perfectly for me, adapted for Objective-C:

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

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

[[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryAmbient错误:nil);[[AVAudioSession sharedInstance]setActive:是的错误:nil);

#6


2  

**

* *

Updated for Swift 3.0

**

* *

The name of the sound I am playing is shatter.wav

我演奏的声音的名字是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);
    }
}

Then where ever you want to play the sound call

无论你想在哪里播放声音

shatterSound()

#7


1  

If you want to play an alert sound:

如果你想播放警报:

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

And if you want to play music:

如果你想演奏音乐:

import AVFoundation

进口AVFoundation

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

#8


1  

For Swift (Objective-C like this too)

对于Swift (Objective-C也像这样)

you can use this link for best answer and if you don't have any time for watching 10 minutes the best action is that you just copy below code in your AppDelegate in didFinishLaunchingWithOptions and then select your project's target then go to Capabilities and at last in Background modes check on Audio, AirPlay and Picture in Picture

你可以使用这个链接最好的答案,如果你没有时间看10分钟最好的行动就是你复制下面代码AppDelegate didFinishLaunchingWithOptions然后选择您的项目的目标然后去功能,最后在后台模式检查音频、播送、画中画

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 {

    }
}