Weird audio interruption behaviour in iOS 11

Hi,


I'm very confused by changes in audio interruption brought in by the newest version of iOS.


Audio Interruption Began/Ended callbacks used to be called by events like alarming notification and incoming phone call.

Since iOS 11, interruptions will also be triggered when suspending/resuming the app,

and occasionally the InterruptionBegan event comes after the DidBecomeActive event, without a proper InterruptionEnded following.


This really bugs me since I use the audio interruption event to handle the BGM's play/pause in my app,

and such behaviour leads to a resumed app without the BGM playing.


I understand that the InterruptionEnded is not guaranteed to happen,

but what is the purpose to trigger an interruption when resuming an app?


Is there a proper way to handle the play/pause behaviour, or to resolve my problem?


Here is the code to reproduce the problem.

by turning the phone to sleep/awake mode repeatedly,

Sometimes the debug output will stop at

----

...

[DEBUG] applicationDidBecomeActive

[DEBUG] audioSessionInterruption - Began

----

when the app is resumed, with the music been stopped.



#import "AppDelegate.h"
#import <AudioToolbox/AudioServices.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
@interface AppDelegate ()
@end
@implementation AppDelegate {
    NSString *soundFilePath;
    NSURL *soundFileUrl;
    AVAudioPlayer *player;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSNotificationCenter*   notificationCenter = [NSNotificationCenter defaultCenter];

    /* register interruption event callback */
    [notificationCenter addObserver:self
                           selector:@selector(audioSessionInterruption:)
                               name:AVAudioSessionInterruptionNotification
                             object:nil
    ];
    [notificationCenter addObserver:self
                           selector:@selector(audioSessionMediaServicesWereReset:)
                               name:AVAudioSessionMediaServicesWereResetNotification
                             object:nil
    ];

    /* init the player */
    soundFilePath=[NSString stringWithFormat:@"%@/some_music.mp3", [[NSBundle mainBundle] resourcePath]];
    soundFileUrl = [NSURL fileURLWithPath:soundFilePath];
    player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileUrl fileTypeHint:nil error:nil];
    player.numberOfLoops = -1;

    return YES;
}
- (void)audioSessionInterruption:(NSNotification*)notification
{
    NSNumber* number;
    NSDictionary* userInfo = notification.userInfo;

    bool wasSuspended = false;
    if (@available(iOS 10.3, *)) {
        number = [userInfo objectForKey:AVAudioSessionInterruptionWasSuspendedKey];
    }
    if (number && ([number boolValue] == TRUE)) {
        wasSuspended = true;
    }

    switch ([userInfo[AVAudioSessionInterruptionTypeKey] intValue]) {
        case AVAudioSessionInterruptionTypeBegan:
            if (wasSuspended) {
                NSLog(@"[DEBUG] audioSessionInterruption - WasSuspended");
                [player play];
            } else {
                NSLog(@"[DEBUG] audioSessionInterruption - Began");
                [player pause];
            }
            break;
        case AVAudioSessionInterruptionTypeEnded:
            NSLog(@"[DEBUG] audioSessionInterruption - Ended");
            [player play];
            break;
        default:
            NSLog(@"[DEBUG] audioSessionInterruption - not supposed to happen");
            break;
    }
}
- (void)audioSessionMediaServicesWereReset:(NSNotification*)notification
{
    NSLog(@"[DEBUG] audioSessionMediaServicesWereReset");
    [player play];
}
- (void)applicationWillResignActive:(UIApplication *)application {
    NSLog(@"[DEBUG] applicationWillResignActive");
    [player pause];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
    NSLog(@"[DEBUG] applicationDidBecomeActive");
    [player play];
}
- (void)applicationWillTerminate:(UIApplication *)application {
    [player stop];
}
@end

Replies

Same issue!


AVAudioSessionInterruptionTypeBegan is sent even if there is no interruption (incoming calls etc...)

Do you guys found any solution? I am also getting the interruption event without any actual event happened. The dictionary says:
For Began event - { AVAudioSessionInterruptionTypeKey = 1; AVAudioSessionInterruptionWasSuspendedKey = 1; }
For End event - { AVAudioSessionInterruptionOptionKey = 0; AVAudioSessionInterruptionTypeKey = 0; }

Audio is being suspended of no cause. UIBackgroundModes are set for music play etc. It is happening from 11.3