Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Audio interruption when iOS application is recording in background

My iPad sound application (iOS 7.1) is able to record while in background. Everything is ok as far as recording is not interrupted while in background. For example if one's has the (stupid?) idea to start listening music while recording something.

I tried to manage this interruption in different ways, with no success. The problem is that the

  - (void)audioRecorderEndInterruption:(AVAudioPlayer *)p withOptions:(NSUInteger)flags

is never fired when application was in background as the interruption occurred. I then tried, in another solution, to implement the AVAudioSessionInterruptionNotification and a handleInterruption: method as

- (void) viewDidAppear:(BOOL)animated
{
......
AVAudioSession *session=[AVAudioSession sharedInstance];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(handleInterruption:)
                                             name:AVAudioSessionInterruptionNotification
                                           object:session];
.......
}
// interruption handling

- (void)handleInterruption:(NSNotification *)notification
{
    try {
        UInt8 theInterruptionType = [[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] intValue];
        NSLog(@"Session interrupted > --- %s ---\n", theInterruptionType == AVAudioSessionInterruptionTypeBegan ? "Begin Interruption" : "End Interruption");

        .... MANAGE interruption begin    
        interruptionBeganWhileInBackgroundMode = TRUE;

        }            
        if (theInterruptionType == AVAudioSessionInterruptionTypeEnded) {

        .... MANAGE interruption end

        }
    } catch (CAXException e) {
        char buf[256];
        fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
    }
}

In this case the handleInterruption: is fired when interruption begins, but it is not when interruption ends (shoulld be fired with theInterruptionType set to AVAudioSessionInterruptionTypeEnded)

To circumvent this problem, I decided to set a flag (interruptionBeganWhileInBackgroundMode) when interruption begins to get the application informed that an interruption has occurred when coming foreground. So that I can manage the end of interruption.

It may seem clever, but it is not! Here is why...

I tried two implementations.

Solution 1. Put a [recorder pause] in handleInterruption: when interruption begins, and manage a [recorder record] in the comingForeground: method when the interruption flag is set. In this situation, the recording is going on immediately when application comes back to foreground, BUT instead of resuming, the recorder erase the file and restart a new recording, so that everything recorded before interruption is lost.

Solution 2. Put a [recorder stop] in handleInterruption: when interruption begins, to save the file, to be sure to preserve the recorded data. This recording is saved, BUT when application is coming foreground, it stalls for about ten seconds before the user can interact again, as if there was a process (the file saving?) that keep the UI frozen.

Last point: I have exactly the same problems in iPhone version of this application: when application is foreground and a phone call occurs, everything goes OK. But when a phone call occurs as my application is background I see the same bad behaviour as in iPad's version.

I notice that Apple's Voice Memo app in iOS7 correctly manage these background interruptions (it stops and saves the recording) despite it displays a 00:00:00 file length when coming foreground. The iTalk application manages it perfectly, automatically resuming recording when coming foreground.

Did anybody find a workaround for the audio interruption management for backgrounded recording applications? I found plenty of people looking for that in many developer websites, but no answer... Thanks!

like image 555
Denis Avatar asked May 10 '14 20:05

Denis


People also ask

Why does music stop playing when recording?

iOS and Android devices, by default, are programmed to pause the music whenever you record a video. Why? Well, the device manufacturers figured that this is the desired behavior for the majority of users, and it wouldn't be worth the trouble to add new settings for the feature.

How can I record currently playing audio on the iPhone?

Open Control Center by swiping down from the top of your screen. If you're using an iPhone with a Home button, you'll need to swipe up from the bottom of the screen until 'Control Center' appears. To record internal audio, tap on the grey 'Record' icon; to ensure that any audio playing on the device is captured.


1 Answers

I have been going through the same issue myself. It seems as if there is a bug in the iOS7 AVAudioRecorder in how it deals with interrupts. Instead of pausing as I believe the documentation says that is should, it closes the file. I have not been able to figure out what is stalling the app when it comes back to the foreground. In my case, I would see AVAudioRecorder finish (with the success flag set to NO), after 10 seconds.

I ended up rewriting the audio recorder using Audio Queues. I found some sample code here ([email protected]:vecter/Audio-Queue-Services-Example.git) that helped with setting it up in an Objective-C environment and the Apple SpeakHere demo has some code to handle the interrupt notifications.

Essentially, I am stopping the recording on interrupt began and opening an alert for the user to save the file. This alert is deferred until UIApplicationDidBecomeActiveNotification is passed if the interrupt started while the app was in the background.

One other thing to note, there seems to be a minor bug in Audio Queues that the AudioQueueStart method will return -50 sometimes. If you add

AudioSessionInitialize(NULL, NULL,nil,(__bridge  void *)(self));
UInt32 sessionCategory = kAudioSessionCategory_PlayAndRecord;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
                        sizeof(sessionCategory),
                        &sessionCategory
                        );
AudioSessionSetActive(true);

Before any AudioQueue methods, the error goes away. These methods are marked as deprecated but seem to be necessary.

like image 169
letteka Avatar answered Oct 10 '22 11:10

letteka