Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

how do I the Audio Settings Category?

Discussion in 'iOS and tvOS' started by sinjimonkey, Jul 5, 2018.

  1. sinjimonkey

    sinjimonkey

    Joined:
    Jul 31, 2013
    Posts:
    72
    Hello!

    Been dealing with an ongoing issue with sound not playing on some iOS devices. I've been writing this off as device specific or user error but my boss insisted I looked into it.

    I found this thread from 5 years ago;
    https://forum.unity.com/threads/ios-no-audio.88351/

    and it looks like I was partially right.

    The TL;DR is that I need to set the Audio Sessions Category to AudioPlayback (which is the correct setting for our app - sound only plays when the user is actively looking at an Augmented Reality target image)

    Has Unity put this functionality into the program yet - or do I still need to write a plugin to do this? Can someone provide such a plugin or talk me through in simple terms how I would do this? I have no XCODE knowledge - it's a huge black box to me I'm only vaguely aware that I can stick .mm files in the code and they'll copy over but I have no idea how such a file should be structured.

    Thanks for any insight you might be able to provide!

    EDIT:
    Will this do the trick?
    https://assetstore.unity.com/packages/tools/integration/ios-native-pro-119175
     
    Last edited: Jul 5, 2018
    bhunterd likes this.
  2. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    823
    If you want to do it absolutely correct you would need to set the audio setting, before the game starts. You could do this in UnityAppController.mm:
    Code (CSharp):
    1. - (BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary*)launchOptions
    2. {
    3.     AVAudioSession *session = [AVAudioSession sharedInstance];
    4.     NSError *setCategoryError = nil;
    5.     if (![session setCategory:AVAudioSessionCategoryPlayback
    6.                         error:&setCategoryError]) {
    7.         // handle error
    8.     }
    9.     return YES;
    10. }
    Otherwise, if it is not that important in the startup (if you have no problem with muting other audio sources or something like that) you can write your own plugin. Here is the snippet I made once for my app:

    Code (CSharp):
    1. #import <Foundation/Foundation.h>
    2. #import <AVFoundation/AVFoundation.h>
    3.  
    4.  
    5.  
    6. void muteOtherSources(BOOL mute)
    7. {
    8.     AVAudioSession *session = [AVAudioSession sharedInstance];
    9.     NSError *setCategoryError = nil;
    10.    
    11.     if(mute)
    12.     {
    13.         //NSLog(@"Muting other sources is true");
    14.         if (![session setCategory:AVAudioSessionCategorySoloAmbient
    15.                             error:&setCategoryError]) {
    16.             // handle error
    17.         }
    18.     }
    19.     else
    20.     {
    21.         //NSLog(@"Muting other sources is false");
    22.         if (![session setCategory:AVAudioSessionCategoryAmbient
    23.                             error:&setCategoryError]) {
    24.             // handle error
    25.         }
    26.     }
    27. }
    28.  
    29. // When native code plugin is implemented in .mm / .cpp file, then functions
    30. // should be surrounded with extern "C" block to conform C function naming rules
    31. extern "C" {
    32.    
    33.     void _MuteOtherSources(bool mute)
    34.     {
    35.         muteOtherSources(mute);
    36.     }
    37.    
    38. }
    39.  
    Should give you a good starting point :)
     
    bhunterd and sinjimonkey like this.
  3. sinjimonkey

    sinjimonkey

    Joined:
    Jul 31, 2013
    Posts:
    72
    Where is Unity App controller. Mm? I didn't see this in the project settings. Is this something in the final XCode output? If so doesn't that mean I have to change it literally every time I make a new build?

    I was doing that for info.plist keys too for a bit before I stumbled on a way to get them to build automatically.

    Thanks for this info regardless it might help me get going in the right direction regardless. I'm not at the computer today but maybe when I look at it again when I get home what you wrote will be self-evident
     
  4. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    823
    sinjimonkey likes this.
  5. sinjimonkey

    sinjimonkey

    Joined:
    Jul 31, 2013
    Posts:
    72
    Okay I tried the first thing and It didn't seem to work - my boss still had to turn the ringer on on her phone for the audio to work (I don't have an iPhone so can't test myself)

    The second bit I'm not sure what do do with. Is this something I'd need to call from within Unity C#? What class would I call it on?
     
  6. sinjimonkey

    sinjimonkey

    Joined:
    Jul 31, 2013
    Posts:
    72
    I found a tutorial video... looks like I need do something line;
    Code (csharp):
    1.  
    2. [DllImport("__Internal")]
    3. private static extern void _MuteOtherSources(bool  mute)
    4.  
    5. public static void MuteOtherSources(bool mute)
    6. {
    7.   _MuteOtherSources(mute);
    8. }
    9.  
    does that look right?
     
    bhunterd likes this.
  7. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    823
    Yep pretty much, here is the snippet from my code:

    Code (CSharp):
    1. public static class NativeMethods
    2.     {
    3.         #region AudioSources
    4.  
    5. #if UNITY_IOS
    6.         [DllImport("__Internal")]
    7.         private static extern void _MuteOtherSources(bool mute);
    8. #endif
    9.  
    10.         /// <summary>
    11.         /// Define if other audio sources should be muted (supported by iOS)
    12.         /// </summary>
    13.         /// <param name="mute">Mute other sources</param>
    14.         public static void MuteOtherSources(bool mute)
    15.         {
    16. #if UNITY_IOS && !UNITY_EDITOR
    17.             _MuteOtherSources(mute);
    18. #else
    19.             Debug.Log("Muting audio source is not supported on this platform");
    20. #endif
    21.         }
    22.         #endregion
    23.     }
     
    bhunterd and sinjimonkey like this.
  8. sinjimonkey

    sinjimonkey

    Joined:
    Jul 31, 2013
    Posts:
    72
    Thank you so much! I got it working last night!

    For future posterity I wound up having to combine both of the methods you wrote above plus using this video tutorial on creating XCode plugins;


    Setting the category on startup didn't seem to work so I wound up using the 'mute other sources' bit you have and pasted that code in there. Then I used the plugin I created using that tutorial to call the function whenever I wanted to play a sound (whenever our app detects the Augmented Reality target)

    Also I found out that you can stick .mm files in the Plugins/iOS/ folder and they will copy over into the XCode project automatically.
     
    bhunterd likes this.
  9. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    823
    Nice, good job!

    Hm, putting the code in AppController should actually work. For us it was necessary since when you disable Unity Audio the checkbox Mute other audio sources is ignored completly and will always mute other audio sources. This means that even if we set the correct setting at an awake method, the user will have to go back to their podcast app or whatever they were listening to and continue playing, since iOS will pause the other audio that was playing.

    Anyways, congrats on getting it working, I remember my hustle getting the first plugin working :)
     
    sinjimonkey likes this.
  10. sinjimonkey

    sinjimonkey

    Joined:
    Jul 31, 2013
    Posts:
    72
    Hmm.. I haven't run into interactions between other audio sources (such as a podcast) when using our app. I'll keep some of that in mind when we get to that.

    Our app is largely event-based - as in the user is physically at an event (like a convention or a street fair) looking at art through the camera that will animate on screen. I'm not sure that conflict is something that will come up much in our use case.
     
  11. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    823
    Yep, good thing to keep in mind, but as long as you use normal unity audio the checkbox for mute other audio sources works as expected. Onlay when you use an external FMOD or Wwise and want to get rid of the normal audio, since it is useless overhead, then you might need to go down that path. :)
     
    sinjimonkey likes this.