Jak mogę zezwolić na odtwarzanie muzyki w tle, gdy moja aplikacja nadal odtwarza dźwięki podczas korzystania z Swift

Utworzyłem aplikację i próbuję pozwolić użytkownikowi na kontynuowanie słuchania muzyki podczas grania w moją grę, ale za każdym razem, gdy naciśnie "play" i pojawi się dźwięk w grze, zatrzyma muzykę w tle. Rozwijam się na iOS za pomocą Swift. Oto fragment kodu, który inicjuje dźwięki w grze.

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()
    }
}
Author: Praveen Gowda I V, 2015-03-13

9 answers

Należy ustawić kategorię AVAudioSession z jedną z następujących wartości: https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html (odwołanie do klasy AVAudioSession).

Wartość domyślna jest ustawiona na AVAudioSessionCategorySoloAmbient. Jak można przeczytać:

[...] korzystanie z tej kategorii oznacza, że dźwięk w Twojej aplikacji nie jest miksowalny-aktywacja sesji spowoduje przerwanie innych sesji audio, które również nie są miksowalne. Aby umożliwić mieszając, użyj zamiast tego kategorii AVAudioSessionCategoryAmbient.

Musisz zmienić kategorię, zanim odtworzysz swój dźwięk. Aby to zrobić:

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

nie musisz dzwonić na tę linię za każdym razem, gdy odtwarzasz dźwięk. Możesz chcieć to zrobić tylko raz.

 40
Author: lchamp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-30 12:03:55

Tak to robię w 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  
}

Możesz Zobaczyć Więcej AVAudioSessionCategoryOptions tutaj: https://developer.apple.com/reference/avfoundation/avaudiosessioncategoryoptions

 11
Author: Setera,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-04 21:27:21

Oto czego używam do Swift 2.0:

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

Pamiętaj, że możesz zastąpić .DuckOthers przez [], jeśli nie chcesz obniżać muzyki w tle i zamiast tego odtwarzać ją na górze.

 9
Author: sameer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-20 04:33:37

Wersja Swift 4:

try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
try? AVAudioSession.sharedInstance().setActive(true)
 9
Author: Milan Nosáľ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-03 15:00:17

Rozwiązanie Lchampa zadziałało dla mnie idealnie, przystosowane do Objective-C:

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

 5
Author: itnAAnti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-15 01:08:07

**

Aktualizacja dla Swift 3.0

**

Nazwa dźwięku, który gram jest 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()
 2
Author: Timmy Sorensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-22 04:42:31

Jeśli chcesz odtworzyć dźwięk alarmu:

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

A jeśli chcesz grać muzykę:

Import 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
Author: Amr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-07 04:00:37

Dla Swift (Objective-C jak to też)

Możesz użyć tego linku, aby uzyskać najlepszą odpowiedź i jeśli nie masz czasu na oglądanie 10 minut najlepszą akcją jest to, że po prostu copy poniżej kodu w swoim AppDelegate w didFinishLaunchingWithOptions, a następnie wybierz swój project's target, Następnie przejdź do Capabilities i w końcu w Background modes sprawdź na Audio, AirPlay and Picture in Picture {9]}

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
Author: shor67,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-28 17:49:31

Nie myślałem, że po prostu ustawienie AVAudioSession do AVAudioSessionCategoryOptions.Kaczory by zadziałały, ale tak się stało. Oto mój pełny kod, aby pomóc żółtodziobom takim jak ja.

Swift 4-Pełny Przykład :

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

Nadal muszę dowiedzieć się setActive (patrzyłem na ten wpis na blogu), ale dźwięk przestaje się uchylać, gdy opuszczam aplikację, więc działa dla mojej aplikacji.

 0
Author: Joshua Dance,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-27 05:51:24