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

问题描述 投票:36回答:10

我创建了一个应用程序,我试图让用户在玩游戏时继续听他们的音乐,但每当他们点击“播放”并且发出游戏声音时它将停止背景音乐。我正在使用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()
    }
}
ios xcode swift audio mobile
10个回答
48
投票

您需要使用以下值之一设置AVAudioSession类别:https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html(AVAudioSession类参考)。

默认值设置为AVAudioSessionCategorySoloAmbient。你可以读到:

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

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

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

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


0
投票

我不认为只是将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(I was looking at this blog post)但是当我离开应用程序时音频停止闪避,所以它适用于我的应用程序。


14
投票

Swift 4版本:

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

12
投票

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

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


9
投票

这是我用于Swift 2.0的内容:

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

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


5
投票

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

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


3
投票

**

更新了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()

2
投票

如果你想播放警报声:

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

如果你想播放音乐:

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

1
投票

对于Swift(Objective-C也是如此)

你可以使用this链接获得最佳答案,如果你没有任何时间观看10分钟,最好的动作是你只需要在copyAppDelegate下面的didFinishLaunchingWithOptions代码,然后选择你的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 {

    }
}

1
投票

因为他们似乎无法从版本到版本做出决定。这是在Swift 5.0中

do{
   try AVAudioSession.sharedInstance().setCategory(.ambient)
   try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
} catch {
   NSLog(error.localizedDescription)
}
© www.soinside.com 2019 - 2024. All rights reserved.