Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
572 views
in Technique[技术] by (71.8m points)

ios - AVAudioRecorder not recording in background after audio session interruption ended

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 */
...

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...