web-dev-qa-db-fra.com

Comment puis-je permettre à la musique de fond de continuer à jouer alors que mon application lit toujours ses sons tout en utilisant Swift

J'ai créé une application et j'essaie de permettre à l'utilisateur de continuer à écouter sa musique tout en jouant à mon jeu, mais chaque fois qu'il clique sur "play" et que les sons du jeu se produisent, la musique de fond est arrêtée. Je développe sur iOS en utilisant Swift. Voici une partie du code qui initie les sons 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()
    }
}
34
Nathan Harper

Vous devez définir la catégorie AVAudioSession avec l'une des valeurs suivantes: https://developer.Apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html (Référence de la classe AVAudioSession).

La valeur par défaut est définie sur AVAudioSessionCategorySoloAmbient. Comme vous pouvez le lire:

[...] l’utilisation de cette catégorie implique que le son de votre application est non mélangeable; l’activation de votre session interrompt toute session audio également non mélangeable. Pour permettre le mélange, utilisez plutôt la catégorie AVAudioSessionCategoryAmbient.

Vous devez changer de catégorie avant de jouer votre son. Faire cela :

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

Vous n'avez pas besoin d'appeler cette ligne à chaque fois que vous jouez le son. Vous voudrez peut-être ne le faire qu'une fois.

43
lchamp

Swift 4 version:

try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
try? AVAudioSession.sharedInstance().setActive(true)
14
Milan Nosáľ

Voici comment je le fais dans 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  
}

Vous pouvez voir plus de AVAudioSessionCategoryOptions ici: https://developer.Apple.com/reference/avfoundation/avaudiosessioncategoryoptions

12
Setera

Voici ce que j'utilise pour Swift 2.0:

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

Veuillez noter que vous pouvez remplacer .DuckOthers par [] si vous ne voulez pas baisser la musique d’arrière-plan, mais plutôt jouer dessus.

9
sameer

la solution de lchamp a parfaitement fonctionné pour moi, adaptée pour Objective-C:

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

5
itnAAnti

**

Mis à jour pour Swift 3.0

**

Le nom du son que je joue est 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);
    }
}

Alors, où que vous vouliez jouer l'appel sonore

shatterSound()
2
Timmy Sorensen

Si vous voulez jouer une alerte sonore:

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

Et si vous voulez jouer de la musique:

importer 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
Amr

Pour Swift (Objective-C comme ça aussi)

vous pouvez utiliser this link pour la meilleure réponse et si vous n'avez pas le temps de regarder 10 minutes, la meilleure chose à faire est de changer simplement le code copy ci-dessous dans votre AppDelegate dans didFinishLaunchingWithOptions puis de sélectionner votre project's target puis d'aller à Capabilities enfin dans Background modes vérifier sur 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
shor67

Je ne pensais pas que le fait de définir AVAudioSession sur AVAudioSessionCategoryOptions.duckOthers fonctionnerait, mais cela a fonctionné. Voici mon code complet pour aider les recrues comme moi. 

Swift 4 - Exemple complet:

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

Je dois encore comprendre setActive ( Je regardais ce billet de blog ), mais le son cesse de baisser lorsque je quitte l'application, donc cela fonctionne pour mon application. 

0
Joshua Dance