Search Unity

Problem with mute button iOS (silent button)

Discussion in 'Audio & Video' started by Sly88, Feb 22, 2016.

  1. Sly88

    Sly88

    Joined:
    Feb 22, 2016
    Posts:
    73
    Hi, I have some questions about silent button on iPhone device. I have some trouble with handle music and sounds in my game. The problem occurred in unity < 5.3 (current I have 5.3.2p4) before all works great, now when I switching the button in game I don't see any change. Music still play. Do you have any idea what is happened? Is any way to handle this button from code ?

    Tested on
    iPad Air
    System version 9.2.1
     
  2. bphillips09

    bphillips09

    Joined:
    Aug 31, 2014
    Posts:
    36
    Are you sure that the volume slider on your iPad is set to mute/unmute the volume and not set to lock/unlock the device's auto-rotation?
     
  3. Sly88

    Sly88

    Joined:
    Feb 22, 2016
    Posts:
    73
    Hi, yes I'm sure.
    On device with older system app works great and the application built in unity(4.6) also works well.
     
  4. Sly88

    Sly88

    Joined:
    Feb 22, 2016
    Posts:
    73
    only I have this problem ?
     
  5. khiemdb

    khiemdb

    Joined:
    Dec 7, 2015
    Posts:
    1
    me too :(
     
  6. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
    The problem still occurs with 5.3.5p5.
     
  7. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
    I actually found a solution for the problem, though it is done in xCode directly: *click*.
    The problem is for me that I always override my xCode project, so I've got to find a solution how I can extend the UnityViewController with that code, but I tested it and it worked.

    Hope that helps. If I find a way to extend the UnityViewController I'll write again.
     
  8. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
    Ok, got it. Just in case anyone is interested in solving this issue (not sure why only so few people are complaining about it), I post the solution that worked for us:

    1.
    You have to extend the UnityAppController class of the xCode project and register to the AVAudioSession to get noticed by the change of the mute button.

    To extend the UnityAppControlller class, simply create a new class under "Assets/Plugins/iOS" and name it "MyUnityAppController.mm". NOTE: if you already have a script which extends the UnityAppController, use that one!

    AppController.png

    2.
    Copy and paste the following code into it:

    Code (CSharp):
    1. #import "UnityAppController.h"
    2. #import "AVFoundation/AVFoundation.h"
    3.  
    4. @interface MyUnityAppController: UnityAppController {}
    5.  
    6. -(void)setAudioSession;
    7.  
    8. @end
    9.  
    10. @implementation MyUnityAppController
    11.  
    12. -(void) startUnity: (UIApplication*) application
    13. {
    14.     NSLog(@"MyUnityAppController startUnity");
    15.     [super startUnity: application];  //call the super.
    16.     [self setAudioSession];
    17. }
    18.  
    19. - (void)setAudioSession
    20. {
    21.     NSLog(@"MyUnityAppController Set audiosession");
    22.     AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    23.     [audioSession setCategory:AVAudioSessionCategoryAmbient error:nil];
    24.     [audioSession setActive:YES error:nil];
    25. }
    26.  
    27. @end
    28.  
    29. IMPL_APP_CONTROLLER_SUBCLASS(MyUnityAppController)
    3.
    The file will be automatically included into your xCode project (at least from Unity 5.x. Haven't tested with 4.x). Check your xCode project if your file is present. Should be located under "Libraries/Plugins/iOS/MyApplicationController.mm". Compile and build the app. When the game starts, you should see in the xCode log output the "MyUnityAppController Set audiosession" output.

    Check if the solution worked for you too.
     
  9. rachitjain

    rachitjain

    Joined:
    Sep 30, 2016
    Posts:
    4
    Hi, I came across this post for a completely opposite reason.
    For me the mute button is functioning properly in the game, i.e. on iPad if the mute button is ON, there is no sound in the game. I am facing an issue, where we have decided to override the mute button.
    So in our game I want to not honor the mute button, how can I do this?
    I am using Unity 5.3.5f1 and xcode 7.3.

    Any help will be greatly appreciated. Thanks :)
     
  10. rachitjain

    rachitjain

    Joined:
    Sep 30, 2016
    Posts:
    4
    Is no one having solution for this?
    I really wish to keep playing the sound in my game, irrespective of the state of the mute button, as lot of our players keep getting sending us messages that "sound is not playing", and we need to constantly remind them that there side switch, which is configured to mute is On, and turning it Off will resolve the issue.

    Please, any help will be great.
     
  11. cyliax

    cyliax

    Joined:
    Feb 25, 2014
    Posts:
    18
    A lil late ... but I had the same problem today. As pahe posted, your can add your own MyUnityAppController.mm in that mentioned folder and it will copied and compiled in your exported project with Xcode. Instead of setting the category to:

    Code (CSharp):
    1. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
    2. [[AVAudioSession sharedInstance] setActive:YES error:nil];
    you're using the category:

    Code (CSharp):
    1. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    2. [[AVAudioSession sharedInstance] setActive:YES error:nil];
    Now, your Unity app still plays sound even if the silent switch is set to off. There are some pages at Apple developer, where the different modes and their behaviour in relation to the silent switch are explained.

    If you want to listen to your sound even when the app is not in focus, have a look at the background modes in your plist.

    Note: Usually the user wants to have his device silent when he is setting the switch. It can be a reason to get rejected by Apple, but it happens really rare, as far as I read. So use it with care.
     
    Last edited: Apr 10, 2017
  12. rachitjain

    rachitjain

    Joined:
    Sep 30, 2016
    Posts:
    4
    Thanks, I did it like that and it worked. :)

    But are you finding crashes because of this while launching of the app sometimes? Fabric is directing me towards this function.
     
  13. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    518
    I tried that solution but seems that doesn't work in Unity 2017.1/2/3 and xCode 9.2. Seems MyUnityAppController not loaded on app start because there is not NSLog at all. What I did is created methods to change AVAudioSession properties and that worked fine.
    Any suggestions why original approach doesn't work now?
     
  14. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
    I encountered many times the problem, that a third party plugin overwrite starting functions or classes of Unity. That caused me the most head aches to figure out.
    So, if you use 3rd party plugins, look for other scripts which may overwrite the UnityController class.
     
  15. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    518
    Make sense, thanks, will check it
     
  16. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    518
    You been right. In my case that was overriden by Vuforia
     
    pahe likes this.
  17. owiesniak

    owiesniak

    Joined:
    Jan 27, 2018
    Posts:
    6
    Facing the same issue with Vuforia here. Have you solved the problem and if yes, how?

    I moved the code from MyUnityAppController.mm to VuforiaNativeRendererController.mm and can see the NSLog statements but i still can not hear any audio when i switch on the hardware mute button.

    Code (CSharp):
    1. /*============================================================================
    2. Copyright (c) 2017 PTC Inc. All Rights Reserved.
    3.  
    4.  
    5. Copyright (c) 2014 Qualcomm Connected Experiences, Inc.
    6. All Rights Reserved.
    7. ============================================================================*/
    8. #import "UnityAppController.h"
    9. #import "UnityView.h"
    10. #import "VuforiaRenderDelegate.h"
    11. #import "AVFoundation/AVFoundation.h"
    12.  
    13. // Unity native rendering callback plugin mechanism is only supported
    14. // from version 4.5 onwards
    15. #if UNITY_VERSION>434
    16.  
    17. // Exported methods for native rendering callback
    18. extern "C" void VuforiaSetGraphicsDevice(void* device, int deviceType, int eventType);
    19. extern "C" void VuforiaRenderEvent(int marker);
    20.  
    21. #endif
    22.  
    23. // Controller to support native rendering callback
    24. @interface VuforiaNativeRendererController : UnityAppController
    25. {
    26. }
    27. - (void)shouldAttachRenderDelegate;
    28. - (void)setAudioSession;
    29. @end
    30.  
    31.  
    32. @implementation VuforiaNativeRendererController
    33.  
    34. -(void) startUnity: (UIApplication*) application
    35. {
    36.     NSLog(@"VuforiaNativeRendererController startUnity");
    37.     [super startUnity: application];  //call the super.
    38.     [self setAudioSession];
    39. }
    40.  
    41. - (void)setAudioSession
    42. {
    43.     NSLog(@"VuforiaNativeRendererController Set audiosession");
    44.     AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    45.     [audioSession setCategory:AVAudioSessionCategoryAmbient error:nil];
    46.     [audioSession setActive:YES error:nil];
    47. }
    48.  
    49. - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
    50. {
    51.     BOOL ret = [super application:application didFinishLaunchingWithOptions:launchOptions];
    52.     if (ret)
    53.     {
    54.         _unityView.backgroundColor = UIColor.clearColor;
    55.     }
    56.     return ret;
    57. }
    58.  
    59. - (void)shouldAttachRenderDelegate
    60. {
    61.     self.renderDelegate = [[VuforiaRenderDelegate alloc] init];
    62.  
    63. // Unity native rendering callback plugin mechanism is only supported
    64. // from version 4.5 onwards
    65. #if UNITY_VERSION>434
    66.     UnityRegisterRenderingPlugin(&VuforiaSetGraphicsDevice, &VuforiaRenderEvent);
    67. #endif
    68. }
    69. @end
    70.  
    71.  
    72. IMPL_APP_CONTROLLER_SUBCLASS(VuforiaNativeRendererController)
    73.  
    UPDATE

    I somehow skipped cyliax's very useful AVAudioSessionCategoryPlayback advice.

    Switching from

    Code (CSharp):
    1.     [audioSession setCategory:AVAudioSessionCategoryAmbient error:nil];
    to

    Code (CSharp):
    1.     [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
    solved the problem.

    This is what i came up with:

    VuforiaNativeRendererController.mm

    Code (CSharp):
    1. /*============================================================================
    2. Copyright (c) 2017 PTC Inc. All Rights Reserved.
    3. Copyright (c) 2014 Qualcomm Connected Experiences, Inc.
    4. All Rights Reserved.
    5. ============================================================================*/
    6. #import "UnityAppController.h"
    7. #import "UnityView.h"
    8. #import "VuforiaRenderDelegate.h"
    9. #import "AVFoundation/AVFoundation.h"
    10.  
    11. // Unity native rendering callback plugin mechanism is only supported
    12. // from version 4.5 onwards
    13. #if UNITY_VERSION>434
    14.  
    15. // Exported methods for native rendering callback
    16. extern "C" void VuforiaSetGraphicsDevice(void* device, int deviceType, int eventType);
    17. extern "C" void VuforiaRenderEvent(int marker);
    18.  
    19. #endif
    20.  
    21. // Controller to support native rendering callback
    22. @interface VuforiaNativeRendererController : UnityAppController
    23. {
    24. }
    25. - (void)shouldAttachRenderDelegate;
    26. - (void)setAudioSession;
    27. @end
    28.  
    29.  
    30. @implementation VuforiaNativeRendererController
    31.  
    32. -(void) startUnity: (UIApplication*) application
    33. {
    34.     NSLog(@"VuforiaNativeRendererController startUnity");
    35.     [super startUnity: application];  //call the super.
    36.     [self setAudioSession];
    37. }
    38.  
    39. - (void)setAudioSession
    40. {
    41.     NSLog(@"VuforiaNativeRendererController Set audiosession");
    42.     AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    43.     [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
    44.     [audioSession setActive:YES error:nil];
    45. }
    46.  
    47. - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
    48. {
    49.     BOOL ret = [super application:application didFinishLaunchingWithOptions:launchOptions];
    50.     if (ret)
    51.     {
    52.         _unityView.backgroundColor = UIColor.clearColor;
    53.     }
    54.     return ret;
    55. }
    56.  
    57. - (void)shouldAttachRenderDelegate
    58. {
    59.     self.renderDelegate = [[VuforiaRenderDelegate alloc] init];
    60.    
    61.     // Unity native rendering callback plugin mechanism is only supported
    62.     // from version 4.5 onwards
    63. #if UNITY_VERSION>434
    64.     UnityRegisterRenderingPlugin(&VuforiaSetGraphicsDevice, &VuforiaRenderEvent);
    65. #endif
    66. }
    67. @end
    68.  
    69.  
    70. IMPL_APP_CONTROLLER_SUBCLASS(VuforiaNativeRendererController)
    71.  
    72.  
     
    Last edited: Apr 26, 2018
    ina, Riddik and codestage like this.
  18. korypse

    korypse

    Joined:
    Sep 16, 2017
    Posts:
    4
    The 3-step turoriel does not work for me. Do you know another solution?
     
  19. HidingGlass

    HidingGlass

    Joined:
    Apr 29, 2015
    Posts:
    25
  20. MartinG

    MartinG

    Joined:
    Apr 17, 2013
    Posts:
    16
    Hi,

    we now run in the same problem using Vuforia. And the solution is very simple.

    Don´t extend the UnityAppController or change the VuforiaNativeRendererController. Just add a native iOS script, which does the same and this in a more simple way:

    For example let´s name it:

    AudioSessionSetter.mm

    Include the code:

    #import "AVFoundation/AVFoundation.h"


    Code (CSharp):
    1. @implementation AudioSessionSetter
    2.  
    3. extern "C" {
    4.    void _SetAudioSession()
    5.    {
    6.        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    7.        [[AVAudioSession sharedInstance] setActive:YES error:nil];
    8.    }
    9. }
    10.  
    11. @end
    Put the file in Unity to Assets/Plugins/iOS or something like Assets/our_custom_library_with_cool_scripts/Plugins/iOS

    Or even better ../Plugins/AudioSessionSetter/iOS

    Then you need a C# Script to call the native script. Let´s name it AudioSessionSetter.cs and put it one folder above the mm-file (in our case in ../Plugins/AudioSessionSetter):

    Code (CSharp):
    1. using System.Runtime.InteropServices;
    2. using UnityEngine;
    3.  
    4. namespace YourCompany.Plugins
    5. {
    6.     public class AudioSessionSetter : MonoBehaviour
    7.     {
    8.  
    9.         // -------------------------------------------------------------------------
    10.         // MonoBehaviour Calls
    11.         // -------------------------------------------------------------------------
    12.  
    13.         private void Awake()
    14.         {
    15.             SetAudioSession();
    16.         }
    17.  
    18.  
    19.  
    20.         // -------------------------------------------------------------------------
    21.         // Native Code Calls
    22.         // -------------------------------------------------------------------------
    23.  
    24. #if UNITY_IOS
    25.         [DllImport("__Internal")]
    26.         private static extern void _SetAudioSession();
    27.  
    28.         // -------------------------------------------------------------------------
    29.         public static void SetAudioSession()
    30.         {
    31.             _SetAudioSession();
    32.         }
    33. #else
    34.         // -------------------------------------------------------------------------
    35.         public static void SetAudioSession()
    36.         {
    37.             //not implemented --> fallback
    38.         }
    39. #endif
    40.     }
    41. }
    As you see, the script is a MonoBehaviour. You can place it on a GameObject in your first scene and in Awake it will handle the AudioSessionSetting for you. No more coding needed. Of course, the scripts can be extended to enable or disable the feature I think. Just as you want. There is no need to fire this in an extended version of the UnityAppController --> startUnity Class and Method.

    The solution worked for us with older iOS (10.3) and the newer version also (12.2. and 12.3.x)

    Greetings,

    Martin
     
  21. Dalton-Lima

    Dalton-Lima

    Joined:
    Dec 21, 2016
    Posts:
    19
    Thanks, @MartinG for the detailed description!
    I had the same problem, and now I can put this solution into our versioning system.
     
  22. LexaMV

    LexaMV

    Joined:
    Feb 20, 2018
    Posts:
    28
    not work

    EntryPointNotFoundException: _SetAudioSession
    AudioSessionSetter.SetAudioSession () (at Assets/Plugins/iOS/AudioSessionSetter/AudioSessionSetter.cs:30)
    AudioSessionSetter.Awake () (at Assets/Plugins/iOS/AudioSessionSetter/AudioSessionSetter.cs:13)
     
  23. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
    You have the external function declared in your iOS script?
     
  24. SanSan13ss

    SanSan13ss

    Joined:
    Aug 29, 2019
    Posts:
    6
    Hi guys!

    I have a problem with sound on ios apps. I have plugin for "AVAudioSessionCategoryPlayback", but sometimes users complain about sound absence in my app.
     
    ina likes this.
  25. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,085
    hmm is there a unity not-write-own-plugin way?
     
  26. andrew_pearce_

    andrew_pearce_

    Joined:
    Nov 5, 2018
    Posts:
    169
    Thanks a lot, I can confirm that it also works on v10.2!
     
  27. Sharpdx

    Sharpdx

    Joined:
    Jan 14, 2021
    Posts:
    3
    Thanks a lot for the info!
     
  28. yesmanfree

    yesmanfree

    Joined:
    Nov 10, 2016
    Posts:
    3
    Hello, I try with IOS 14, 16 and unity version 2020.3 LTS but not work, anyone try and work recently?
     
  29. Ziulv

    Ziulv

    Joined:
    Aug 16, 2021
    Posts:
    2
    Hey! Sorry for the bump, but I have the same issue. All done right. But the solution above doesn't work.
    External function declared in my iOS script.

    EntryPointNotFoundException: _SetAudioSession assembly:<unknown assembly> type:<unknown type> member: (null)
     
  30. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
  31. Ziulv

    Ziulv

    Joined:
    Aug 16, 2021
    Posts:
    2
  32. hashammuhammad148

    hashammuhammad148

    Joined:
    Feb 19, 2021
    Posts:
    6
    for the beginers create the text file and paste

    #import "UnityAppController.h"
    #import "AVFoundation/AVFoundation.h"

    @interface MyUnityAppController: UnityAppController {}

    -(void)setAudioSession;

    @End

    @implementation MyUnityAppController

    -(void) startUnity: (UIApplication*) application
    {
    NSLog(@"MyUnityAppController startUnity");
    [super startUnity: application]; //call the super.
    [self setAudioSession];
    }

    - (void)setAudioSession
    {
    NSLog(@"MyUnityAppController Set audiosession");
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
    [audioSession setActive:YES error:nil];
    }

    @End

    IMPL_APP_CONTROLLER_SUBCLASS(MyUnityAppController)


    and save it with name MyUnityAppController.mm
    and place it under the Plugins\iOS folder