How can I set AVAudioSession for iOS apps to allow device/apps to continue audio playback?

In a UE4 project, is it possible to set the AVAudioSession category as described here ? Or perhaps something else that has a similar result? I’d like my iOS app NOT to take over the audio session when launched, but to allow background audio to continue (podcasts etc). Currently when I launch my UE4 iOS apps, that app causes all currently playing audio to stop.

Hey there, So i figured out your issue. This fix only works if you are building from source though. This is with 4.23.1 in mind just incase things changed from previous engine versions but it will be the same for most versions.

So the file you need is IOSAppDelegate.CPP

The location of the file is (Folder Where Source Built Engine Is) -> (Engine) -> (Source) -> (Runtime) -> (ApplicationCore) -> (Private) -> (IOS) -> IOSAppDelegate.cpp

You can use the search function as well to find it quickly. Once you open it, you can go down to line 976 where it mentions “didFinishLaunchingWithOptions”. Right underneath that, copy and paste this line of code:

[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];

Thats it. Compile and Build your game. I tested this in a fully production ready game and my sounds, voices, and background music were all fine to play like normal but when I opened the game, it definitely didn’t stop my music from playing. It also still obeys the mute button on the iPhone so the music will still play but your game music will stay quiet. You actually helped me figure out this 2 year long issue so I figured I would return the favor.

Hopefully it helps others as well.

Here is a picture of the code just in case.

2 Likes

Thanks very much for this! VERY much appreciated.
I have been meaning to follow this up for some time and intended to raise it as a bug for those of us who are not compiling from source. I’ll try and get my act together and post back here if I hear back from Epic bug reports.

2 Likes

Hi, is it not possible to create a plugin to create a new AppDelegate and override the “didFinishLaunchingWithOptions” ? I want to avoid editing and rebuilding the engine.

No Problem at all Lone. Your questions helped me figure it out.

I am not sure. I believe this is an option in 4.24 now but I heard it is a mobile nightmare so i haven’t upgraded. I don’t know much about C++ coding either. Its not too hard to read but writing it is beyond me. This was the only way could figure out though that didn’t break all of my sound in game.

i just found a way to invoke that function without modifying the engine, by using an observer ios class.

any chance you can tell us how you did it?:eek:

For those needing an answer regarding the observer ios class, im pasting a template code




@implementation NotificationObserver

static NotificationObserver* NotificationObserverInstance = nil;

-(id)init
{
    self = [super init];
    return self;
}

+(void)load
{
    [super load];

    if (NotificationObserverInstance == nil)
    {
        NotificationObserverInstance = [NotificationObserver alloc] init];
        [NotificationObserverInstance registerLifeCycleListener];
    }
}

+(NotificationObserver*)sharedInstance
{
    if (NotificationObserverInstance == nil)
    {
        [NotificationObserver load];
    }

    return NotificationObserverInstance;
}

-(void)registerLifeCycleListener
{
    [NSNotificationCenter defaultCenter] addObserver:self    selector : @selector(didFinishLaunching : )    name:UIApplicationDidFinishLaunchingNotification object : nil];


    [NSNotificationCenter defaultCenter] addObserver:self    selector : @selector(appWillResignActive : )    name:UIApplicationWillResignActiveNotification object : nil];
    [NSNotificationCenter defaultCenter] addObserver:self    selector : @selector(appDidBecomeActive : )    name:UIApplicationDidBecomeActiveNotification object : nil];

}



+(void)unregisterObserver
{
    if (NotificationObserverInstance != nil)
    {
        [NSNotificationCenter defaultCenter] removeObserver:self name : UIApplicationDidFinishLaunchingNotification object : nil];
        [NSNotificationCenter defaultCenter] removeObserver:self name : UIApplicationWillResignActiveNotification object : nil];
        [NSNotificationCenter defaultCenter] removeObserver:self name : UIApplicationDidBecomeActiveNotification object : nil];
    }
}


-(void)appDidBecomeActive:(NSNotification*)notification
{
}

-(void)appWillResignActive : (NSNotification*)notification
{

}



-(void)didFinishLaunching:(NSNotification*)notification
{
    [NotificationObserver requestAuthorization];
}

+(void)requestAuthorization
{


}

@end


Then in the plugin’s startupmodule() function, paste the below :

[NotificationObserver load];

Calling it in the startupmodule() function ensures the observer is called right at the start of the game launch.

I just came across this in the 4.24 release notes:

**New: *Added audio options that provide greater control over how audio behaves on iOS using AVAudioSession, which can be enabled using -SetFeature:Active on IOSAppDelegate or through a config setting. These include: * Microphone/speaker usage during VOIP. Enabling/disabling background audio. * Enabling/disabling audio mixing with other applications.

But I still haven’t figured out what that config setting is.

Did you manage to figure out how to turn it on?

I also ran into this problem. I didn’t want to build a custom engine, and the code given by codehawk64 above didn’t work for me.

In the end I’ve managed to get this working for me. Here’s some code:

// In includes section
#if PLATFORM_IOS
#include "IOSAppDelegate.h"
#endif

//...

        // Call somewhere during startup (e.g. from StartupModule() or similar)
        // This is Objective-C code which you can insert anywhere as long as you put it inside #if PLATFORM_IOS
	#if PLATFORM_IOS
	[[IOSAppDelegate GetDelegate] SetFeature:EAudioFeature::Playback Active:true]; 
	#endif

This is calling into Unreal’s IOSAppDelegate class and asking it to enable the “Playback” feature which corresponds to AVAudioSessionCategoryPlayback. Other features are available, if in doubt refer to IOSAppDelegate.h/.cpp in the engine source.

enum class EAudioFeature : uint8
{
	Playback, // Audio Not affected by the ringer switch
	Record, // Recording only, unless Playback or VoiceChat is also set

	DoNotMixWithOthers, // Do not mix audio with other applications

	VoiceChat, // set AVAudioSessionModeVoiceChat when both Playback and Record are enabled
	UseReceiver, // use receiver instead of speaker when both Playback and Record are enabled. Headsets will still be preferred if they are present
	DisableBluetoothSpeaker, // disable the use of Bluetooth A2DP speakers when both Playback and Record are enabled

	BluetoothMicrophone, // enable the use of Bluetooth HFP headsets when Record is enabled

	BackgroundAudio, // continue to play audio in the background. Requires an appropriate background mode to be set in Info.plist

	NumFeatures,
};

Thanks @Maximilian.Hunt1, really helpful.

I added this in an empty plugin in the StartupModule() method, but the audio still cuts out when it goes into the background.

void FMyModuleName::StartupModule()
{
    #if PLATFORM_IOS
    [[IOSAppDelegate GetDelegate] SetFeature:EAudioFeature::Playback Active:true];
    [[IOSAppDelegate GetDelegate] SetFeature:EAudioFeature::BackgroundAudio Active:true];
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];Active:true];
    #endif
}

I also set Project Settings > Platforms - iOS > Extra PList Data > Additional Plist Data, with the following entry:
<key>UIBackgroundModes</key><array><string>audio</string></array>

However, if I set the Playback mode instead of BackgroundAudio, it does work.

More info: https://forum.unity.com/threads/how-do-i-get-the-audio-running-in-background-ios.319602/

Would you have any other suggestions for BackgroundAudio on iOS?

So what if I want to do the reverse?

My game does not stop background music and I want it to do that?
I’m using Engine 4.27.2 and I’m building for Android and iOS