AVAudioRecorder not recording in background after

2019-02-07 04:04发布

I am recording audio in my app, both in foreground and in background. I also handle AVAudioSessionInterruptionNotification to stop recording when interruption begins and start again when it ends. Although in foreground it works as expected, when app is recording in background and I receive a call it doesn't start again recording after call ends. My code is the following:

        - (void)p_handleAudioSessionInterruptionNotification:(NSNotification *)notification
        {
            NSUInteger interruptionType = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];

            if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
                if (self.isRecording && !self.interruptedWhileRecording) {

                    [self.recorder stop];

                    self.interruptedWhileRecording = YES;
                    return;
                }
            }

            if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
                if (self.interruptedWhileRecording) {
                    NSError *error = nil;
                    [[AVAudioSession sharedInstance] setActive:YES error:&error];

                    NSDictionary *settings = @{
                                       AVEncoderAudioQualityKey: @(AVAudioQualityMax),
                                       AVSampleRateKey: @8000,
                                       AVFormatIDKey: @(kAudioFormatLinearPCM),
                                       AVNumberOfChannelsKey: @1,
                                       AVLinearPCMBitDepthKey: @16,
                                       AVLinearPCMIsBigEndianKey: @NO,
                                       AVLinearPCMIsFloatKey: @NO
                                       };

                    _recorder = [[AVAudioRecorder alloc] initWithURL:fileURL settings:settings error:nil];

                    [self.recorder record];

                    self.interruptedWhileRecording = NO;
                    return;
                }
            }
        }

Note that fileURL points to new caf file in a NSDocumentDirectory subdirectory. Background mode audio is configured. I also tried voip and play silence, both to no success.

The NSError in AVAudioSessionInterruptionTypeEnded block is a OSStatus error 560557684 which I haven't found how to tackle.

Any help would be much appreciated.

2条回答
Emotional °昔
2楼-- · 2019-02-07 04:11

I added the following

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

before configuring AVAudioSession and it worked. Still don't know what bugs may appear.

查看更多
混吃等死
3楼-- · 2019-02-07 04:13

Error 560557684 is for AVAudioSessionErrorCodeCannotInterruptOthers. This happens when your background app is trying to activate an audio session that doesn't mix with other audio sessions. Background apps cannot start audio sessions that don't mix with the foreground app's audio session because that would interrupt the audio of the app currently being used by the user.

To fix this make sure to set your session category to one that is mixable, such as AVAudioSessionCategoryPlayback. Also be sure to set the category option AVAudioSessionCategoryOptionMixWithOthers (required) and AVAudioSessionCategoryOptionDuckOthers (optional). For example:

// background audio *must* mix with other sessions (or setActive will fail)
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
                                 withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDuckOthers
                                       error:&sessionError];
if (sessionError) {
    NSLog(@"ERROR: setCategory %@", [sessionError localizedDescription]);
}

The error code 560557684 is actually 4 ascii characters '!int' in a 32 bit integer. The error codes are listed in the AVAudioSession.h file (see also AVAudioSession):

    @enum AVAudioSession error codes
    @abstract   These are the error codes returned from the AVAudioSession API.
...
    @constant   AVAudioSessionErrorCodeCannotInterruptOthers
        The app's audio session is non-mixable and trying to go active while in the background.
        This is allowed only when the app is the NowPlaying app.

typedef NS_ENUM(NSInteger, AVAudioSessionErrorCode)
{
...
    AVAudioSessionErrorCodeCannotInterruptOthers = '!int', /* 0x21696E74, 560557684 */
...
查看更多
登录 后发表回答