Подтвердить что ты не робот

Как разрешить фоновой музыке продолжать играть, пока мое приложение все еще воспроизводит звуки при использовании Swift

Я создал приложение, и я пытаюсь разрешить пользователю продолжать слушать их музыку во время игры, но всякий раз, когда они нажимают "играть", и появляются звуки игры, это останавливает фоновую музыку. Я разрабатываю iOS с помощью Swift. Вот фрагмент кода, который инициирует игровые звуки.

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

Ответ 1

Вам нужно установить категорию 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)

Вам не нужно вызывать эту строку каждый раз, когда вы воспроизводите звук. Возможно, вы захотите сделать это только один раз.

Ответ 2

Вот что я использую для Swift 2.0:

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

Обратите внимание, что вы можете заменить .DuckOthers на [], если вы не хотите опускать фоновую музыку и вместо этого играть сверху.

Ответ 3

Вот как я это делаю в 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

Ответ 4

версия Swift 4:

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

Ответ 5

**

Обновлен для 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()

Ответ 6

lchamp решение отлично работает для меня, адаптировано для Objective-C:

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

Ответ 7

Если вы хотите воспроизвести звуковой сигнал:

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

Ответ 8

Для Swift (Objective-C как это тоже)

вы можете использовать эту ссылку для получения наилучшего ответа, и если у вас нет времени для просмотра 10 минут, лучшим действием является то, что вы просто copy ниже кода в AppDelegate в didFinishLaunchingWithOptions, а затем выберите project 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 {

    }
}