Search Unity

Setting MediaPlayback audio session category?

Discussion in 'iOS and tvOS' started by OwenG, Oct 24, 2013.

  1. OwenG

    OwenG

    Joined:
    Sep 30, 2013
    Posts:
    20
    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
     
  2. OwenG

    OwenG

    Joined:
    Sep 30, 2013
    Posts:
    20
    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:
    Code (csharp):
    1. #import <AVFoundation/AVFoundation.h>
    2.  
    3. void iOSAudio_setupAudioSession()
    4. {
    5.     // We want to make sure all audio stops from other apps, and we want to
    6.     // ignore the ringer/mute switch.
    7.     UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
    8.     OSStatus result = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
    9.    
    10.     result = AudioSessionSetActive(YES);
    11.     // Can check result if you want...
    12. }
    In my Unity C# code that runs on launch, I do this to declare the extern function:

    Code (csharp):
    1. #if UNITY_IOS
    2.     [DllImport ("__Internal")]
    3.     private static extern void iOSAudio_setupAudioSession();
    4. #endif
    5.  
    And then call it on launch:

    Code (csharp):
    1. #if UNITY_IOS
    2.         // Check that it's actually an iOS device/simulator, not the Unity Player.
    3.         if (Application.platform == RuntimePlatform.IPhonePlayer)
    4.         {
    5.             iOSAudio_setupAudioSession();
    6.         }
    7. #endif
    8.  
    Hope that helps, if someone else is trying to do the same thing. :)
    Owen
     
  3. asura1234

    asura1234

    Joined:
    Feb 28, 2014
    Posts:
    1
    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.
     
  4. 39thstreet

    39thstreet

    Joined:
    Jan 30, 2012
    Posts:
    104
    Way down the road, but this appears to work as a replacement:


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

    Source:
    http://stackoverflow.com/questions/...in-ios-7-0-so-how-set-kaudiosessionproperty-o
     
  5. fherbst

    fherbst

    Joined:
    Jun 24, 2012
    Posts:
    802
    ... and for anyone needing this, here's a package containing the .m iOS plugin and a script accessing it (assembled from the previous posts).
     

    Attached Files:

    sinjimonkey and whrthsdwlknds like this.
  6. whrthsdwlknds

    whrthsdwlknds

    Joined:
    Jan 20, 2017
    Posts:
    2
    Thanks @fherbst ! how do i run this script upon starting my app? does it all just need to be in the Plugins/iOS folder?
     
  7. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    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?
     
    Annopolus likes this.
  8. Annopolus

    Annopolus

    Joined:
    Apr 15, 2015
    Posts:
    18
  9. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Hi @Annopolus
    Yep, I did go with including the setting in UnityAppController.mm in the iOS project. I changed the behavior of willFinishLaunchingWithOptions:

    Code (CSharp):
    1. - (BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary*)launchOptions
    2. {
    3.     AVAudioSession *session = [AVAudioSession sharedInstance];
    4.     NSError *setCategoryError = nil;
    5.     if (![session setCategory:AVAudioSessionCategoryAmbient
    6.                         error:&setCategoryError]) {
    7.         // handle error
    8.     }
    9.     return YES;
    10. }
    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 :)
    Still using Unity 5.6, so maybe the function has changed, but the idea should still work.
     
  10. Annopolus

    Annopolus

    Joined:
    Apr 15, 2015
    Posts:
    18
    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.... :-(

    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<AudioSource>();
    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.......
     
    Horum_developer likes this.
  11. Horum_developer

    Horum_developer

    Joined:
    Mar 25, 2020
    Posts:
    1


    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.