Audio not resume after switch to another app

I import FMOD from Unity Asset Store, version 2.01.07.

  • Build and run in iPhone, switch your app to another app, which can play audio/video like YouTube.
  • Then switch back to your app, audio will not resume.
  • It will be fixed about 30s later or never.

I think is a bug for iOS AVAudioSessionInterruptionNotification in the file “platform_ios”.

I try to fix it with 2 new notifications, or someone else can feed me back with a better way.

// platform_ios.mm
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

void (*gSuspendCallback)(bool suspend);

extern "C" void RegisterSuspendCallback(void (*callback)(bool))
{
    if (!gSuspendCallback)
    {
        gSuspendCallback = callback;
        
        [[NSNotificationCenter defaultCenter] addObserverForName:AVAudioSessionInterruptionNotification object:nil queue:nil usingBlock:^(NSNotification *notification)
         {  
            bool began = [[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] intValue] == AVAudioSessionInterruptionTypeBegan;
            
            if (!began)
            {
                [[AVAudioSession sharedInstance] setActive:TRUE error:nil];
            }
            
            if (gSuspendCallback)
            {
                gSuspendCallback(began);
            }
        }];
        
        [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:nil queue:nil usingBlock:^(NSNotification *notification)
         {  
            [[AVAudioSession sharedInstance] setActive:FALSE error:nil];
            
            if (gSuspendCallback)
            {
                gSuspendCallback(1);
            }
        }];
        
        [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:nil usingBlock:^(NSNotification *notification)
         {  
            [[AVAudioSession sharedInstance] setActive:TRUE error:nil];
            
            if (gSuspendCallback)
            {
                gSuspendCallback(0);
            }
        }];
    }
}

In 2.01.08, we changed platform_ios.mm to address similar issues. This version is available on our website, not currently via the unity store. Below is a copy of the updated platform_ios.mm file.

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

void (*gSuspendCallback)(bool suspend);
bool gIsSuspended = false;

extern "C" void RegisterSuspendCallback(void (*callback)(bool))
{
    if (!gSuspendCallback)
    {
        gSuspendCallback = callback;
        
        [[NSNotificationCenter defaultCenter] addObserverForName:AVAudioSessionInterruptionNotification object:nil queue:nil usingBlock:^(NSNotification *notification)
        {
            bool began = [[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] intValue] == AVAudioSessionInterruptionTypeBegan;
            
            if (began == gIsSuspended)
            {
                return;
            }
            if (@available(iOS 10.3, *))
            {
                if (began && [[notification.userInfo valueForKey:AVAudioSessionInterruptionWasSuspendedKey] boolValue])
                {
                    return;
                }
            }
            
            gIsSuspended = began;
            if (!began)
            {
                [[AVAudioSession sharedInstance] setActive:TRUE error:nil];
            }
            if (gSuspendCallback)
            {
                gSuspendCallback(began);
            }
        }];
        
        [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:nil usingBlock:^(NSNotification *notification)
        {
#ifndef TARGET_OS_TV
            if (!gIsSuspended)
            {
                return;
            }
#else
            if (gSuspendCallback)
            {
                gSuspendCallback(true);
            }
#endif
            [[AVAudioSession sharedInstance] setActive:TRUE error:nil];
            if (gSuspendCallback)
            {
                gSuspendCallback(false);
            }
            gIsSuspended = false;
        }];
    }
}