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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29024320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 05:11:15  来源:igfitidea点击:

How can I allow background music to continue playing while my app still plays its sounds while using Swift

iosxcodeswiftaudiomobile

提问by Nathan Harper

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.

我创建了一个应用程序,我试图让用户在玩我的游戏时继续听他们的音乐,但是每当他们点击“播放”并且游戏中的声音出现时,它就会停止背景音乐。我正在使用 Swift 在 iOS 上进行开发。这是一段启动游戏声音的代码。

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

回答by lchamp

You need to set the AVAudioSessioncategory, 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 AVAudioSessionCategoryAmbientcategory 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.

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

回答by Milan Nosá?

Swift 4version:

斯威夫特 4版本:

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

回答by Setera

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

回答by sameer

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 .DuckOtherswith []if you don't want to lower background music and instead play on top to it.

请注意,如果您不想降低背景音乐而是在上面播放.DuckOthers[]则可以替换为。

回答by itnAAnti

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];

回答by Timmy Sorensen

**

**

Updated for Swift 3.0

为 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()

回答by Matt

Since they can't seem to make up their minds from version to version. Here it is in Swift 5.0

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

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

回答by Amr

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

回答by shor67

For Swift (Objective-C like this too)

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

you can use thislink for best answer and if you don't have any time for watching 10 minutes the best action is that you just copybelow code in your AppDelegatein didFinishLaunchingWithOptionsand then select your project's targetthen go to Capabilitiesand at last in Background modescheck on Audio, AirPlay and Picture in Picture

你可以使用这个链接,最好的答案,如果你没有任何时间收看10分钟,最好的行动就是你刚才copy下面的代码在你AppDelegatedidFinishLaunchingWithOptions,然后选择你project's target,然后去Capabilities,最后在Background modes支票上Audio, AirPlay and Picture in Picture

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 {

    }
}

回答by Joshua Dance

I didn't think that just setting the AVAudioSession to AVAudioSessionCategoryOptions.duckOthers would work, but it did. Here is my full code to help the rookies like myself.

我不认为只是将 AVAudioSession 设置为 AVAudioSessionCategoryOptions.duckOthers 会起作用,但确实如此。这是我的完整代码,可以帮助像我这样的菜鸟。

Swift 4 - Full Example:

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

I still need to figure out setActive (I was looking at this blog post) but the audio stops ducking when I leave the app, so it works for my app.

我仍然需要弄清楚 setActive (我正在看这篇博客文章)但是当我离开应用程序时音频停止闪避,所以它适用于我的应用程序。