Setting MediaPlayback audio session category?

Hi everyone,

I’m looking for a way to set the iOS audio session category to MediaPlayback on iOS. I’m working on a musical toy using Unity, and I want it to override the device mute switch and always play audio.

Is there a way to set the audio session category somewhere? Or do I need to write some plugin code to change it?

Thanks for any suggestions.
Owen

If anyone else is trying to do this, I ended up writing a simple plugin to set the audio session category.

I created a .m file called iOSAudio.m and put it in Assets/Plugins/iOS.

iOSAudio.m:

#import <AVFoundation/AVFoundation.h>

void iOSAudio_setupAudioSession()
{
	// We want to make sure all audio stops from other apps, and we want to
	// ignore the ringer/mute switch.
	UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
	OSStatus result = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
	
	result = AudioSessionSetActive(YES);
	// Can check result if you want...
}

In my Unity C# code that runs on launch, I do this to declare the extern function:

#if UNITY_IOS
	[DllImport ("__Internal")]
	private static extern void iOSAudio_setupAudioSession();
#endif

And then call it on launch:

#if UNITY_IOS
		// Check that it's actually an iOS device/simulator, not the Unity Player.
		if (Application.platform == RuntimePlatform.IPhonePlayer)
		{
			iOSAudio_setupAudioSession();
		}
#endif

Hope that helps, if someone else is trying to do the same thing. :slight_smile:
Owen

3 Likes

It turns out at the time I’m reading this, audio session is deprecated in iOS 7.0. I haven’t found a new solution yet. This is more like a FYI.

Way down the road, but this appears to work as a replacement:

AVAudioSessionsession =[AVAudioSession sharedInstance];
NSError
setCategoryError =nil;if(![session setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionMixWithOthers
error:&setCategoryError]){// handle error}

Source:
http://stackoverflow.com/questions/21682502/audiosessionsetproperty-deprecated-in-ios-7-0-so-how-set-kaudiosessionproperty-o

… and for anyone needing this, here’s a package containing the .m iOS plugin and a script accessing it (assembled from the previous posts).

2310336–155657–AudioSession.zip (1.42 KB)

2 Likes

Thanks @fherbst ! how do i run this script upon starting my app? does it all just need to be in the Plugins/iOS folder?

SetupAudioSession.cs does not need to be there, iOSAudio.m has to be there.
You will need to add SetupAudioSession.cs to a gameobject in the scene in order to run the script (runs on start, so when the gameobject gets activated).

The big problem I see here is that the session setting does not apply at the very start of the app. In my case, I want to allow other audio sources, therefore I use the category AVAudioSessionCategoryAmbient. The value applies at loading the scene and not at loading the app, so the standard setting applies in the splash screen which is AVAudioSessionCategorySoloAmbient. Therefore all playing audio sources are stopped at the start of the app. Of course they don’t start playing again when switching the mode, so the user would need to hit the play button again and then switch to the unity app.
I also tried running the script with RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad), sadly this didn’t fix the problem. I’m not that used to working with xcode directly, but is there maybe a way to set the audio session category in the settings there? Or where in the unity start files would I need to hack this into?

1 Like

Hi and thank you @Johannski ! Valuable comments. I’m facing this problem long time and looking for a solution. Unity wrote: Unity Issue Tracker - [iOS] Unity Player does not respect the &quot;Mute Other Audio Sources&quot; toggle in Player Settings that this issue was resolved in 2019.2, however it is still beta (with tons of other bugs, so I even can’t test if it is working).

Just a simple question: did you found any solution on that?

Hi @Annopolus
Yep, I did go with including the setting in UnityAppController.mm in the iOS project. I changed the behavior of willFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    AVAudioSession *session = [AVAudioSession sharedInstance];
    NSError *setCategoryError = nil;
    if (![session setCategory:AVAudioSessionCategoryAmbient
                        error:&setCategoryError]) {
        // handle error
    }
    return YES;
}

Of course you would need to change that every time you build your project. Or you could use a PostBuild script that replaces the file as I did :slight_smile:
Still using Unity 5.6, so maybe the function has changed, but the idea should still work.

Hi @Johannski !
You are the best! Thank you for this.

Definitely it works - when my app is starting, it let the background music (ie Spotify) continue to play.
One small add for all, who wants to use your fix: add at the beginning of UnityAppController.mm
#import <AVFoundation/AVFoundation.h> where the declarations for AVAudioSession exists.
Great, again - thank you!

However… :frowning:

My App has a part of audio processing. It uses Microphone to listen music to get a data for ie. visualization. On android it works well getting external or internal music data through the Mic activated:

[…]
AudioSource snd = GetComponent();
snd.clip = Microphone.Start(null, true, 1, 48000);
snd.loop = true;

WaitForMicrophone();

snd.Play();
[…]

and

IEnumerator WaitForMicrophone()
{
while (!(Microphone.GetPosition(null) > 0))
{
yield return null;
}
}

but not on iOS. Above code stops background music from Spotify (in fact stops Spotify from play).
Generally above is a signal for me that the problem is not only with AVAudioSessionCategoryAmbient wrongly set, but there is something deeper in Unity Sound system and iOS platform.

I stuck…

1 Like

Hi! Have you dealer with this problem?? The same problem in unity 2019.3.13f1 - I’m playing video via URL and have no sound in iOS platform, only in headphones.