J.Doe
J.Doe

Reputation: 1552

AVAudioSession is playing ontop of the system sounds

Hey so I have this code below. I am just trying to get it so that if their is any music, podcasts, etc is playing from another app inside of the OS that all sounds are muted. However I have tried setting its category, and it won't work! Am I not using the right category? Perhaps not in the right place?

The goal is that the user can listen to their own tunes while using the app.

sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("GameMusic9", ofType: "mp3")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("GameMusicRP", ofType: "mp3")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Death", ofType: "mp3")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Tap", ofType: "wav")!)!)

        //Monsters
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Blue", ofType: "wav")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Brown", ofType: "wav")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Green", ofType: "wav")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Orange", ofType: "wav")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Purple", ofType: "wav")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Red", ofType: "wav")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Tan", ofType: "wav")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Yellow", ofType: "wav")!)!)
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Correct", ofType: "wav")!)!)//12
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Cowbell", ofType: "aiff")!)!)//13
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("12", ofType: "wav")!)!)//14
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Hybrid", ofType: "mp3")!)!)//15
        sounds.append(NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Correct", ofType: "wav")!)!)//16

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

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

        //Close or punch, or bycycle

        var error:NSError?
        for var i:Int = 0; i < sounds.count; i++
        {
            audioPlayers.append(AVAudioPlayer(contentsOfURL: sounds[i], error: &error))

            audioPlayers.last?.prepareToPlay()
        }

Upvotes: 1

Views: 1521

Answers (1)

Tam&#225;s Zahola
Tam&#225;s Zahola

Reputation: 9311

No, you're not using the right category. From the docs:

AVAudioSessionCategoryAmbient

The category for an app in which sound playback is nonprimary—that is, your app can be used successfully with the sound turned off.

This category is also appropriate for “play along” style apps, such as a virtual piano that a user plays while the Music app is playing. When you use this category, audio from other apps mixes with your audio. Your audio is silenced by screen locking and by the Silent switch (called the Ring/Silent switch on iPhone).

Try AVAudioSessionCategoryPlayback:

AVAudioSessionCategoryPlayback

The category for playing recorded music or other sounds that are central to the successful use of your app.

When using this category, your app audio continues with the Silent switch set to silent or when the screen locks. (The switch is called the Ring/Silent switch on iPhone.) To continue playing audio when your app transitions to the background (for example, when the screen locks), add the audio value to the UIBackgroundModes key in your information property list file.

By default, 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 for this category, use the AVAudioSessionCategoryOptionMixWithOthers option.

Or try AVAudioSessionCategorySoloAmbient which is like AVAudioSessionCategoryAmbient but non-mixable by default.

Edit: I misunderstood the question. The goal is to only play music if other apps are not playing anything. This can be achieved by checking the shared AVAudioSession:

[[AVAudioSession sharedInstance] isOtherAudioPlaying];

And only play your music if it returned NO. Note that since iOS 8.0, it is preferable to use another property (they have slightly different semantics):

[[AVAudioSession sharedInstance] secondaryAudioShouldBeSilencedHint];

The value is YES when another application with a non-mixable audio session is playing audio.

Applications should use this property as a hint to silence audio that is secondary to the functionality of the application. For example, a game using AVAudioSessionCategoryAmbient can use this property to decide to mute its soundtrack while leaving its sound effects unmuted.

You should also subscribe to AVAudioSessionSilenceSecondaryAudioHintNotification notifications and stop/start your music to reflect changes in secondaryAudioShouldBeSilencedHint.

NSNotificationCenter.defaultCenter().addObserverForName(AVAudioSessionSilenceSecondaryAudioHintNotification, object: nil, queue: nil) { notification in
// stat/stop music based on AVAudioSession.sharedInstance().secondaryAudioShouldBeSilencedHint
}

Upvotes: 3

Related Questions