Reputation: 940
I am writing an application that uses the AVAudioRecorder
class. It works great except for when a phone call comes in. I am handling this per apple's guidelines of using the AVAudioRecorderDelegate methods
– (void) audioRecorderBeginInterruption:
– (void) audioRecorderEndInterruption:
It works great until the interruption ends and I attempt to "resume" the recording by calling the record method again (per the documentation). However it does not resume my recording but instead throws out the old one and starts up an entirely new one in its place. I have not been able to find a solution to this problem, if anyone has figured this out, or if it is a bug with apple's AVAudioRecorder
please let me know. I really hope I do not have to write this using AudioQueues
.
thanks
Upvotes: 8
Views: 3159
Reputation: 87
There isn't actually a bug (at least not anymore). The current documentation (2023) for the method states that calling .record()
will implicitly call .prepareToRecord()
which creates a NEW file at the specified URL. Apple's docs clearly state that if a file exists at the URL it will be overwritten. In other words, "resuming" recording is impossible with the provided APIs. The only way to achieve this with AVAudioRecorder is to create multiple files and merge them. It should be noted that Apple's documentation of AVAudioRecorder.record()
is misleading as it does in fact say "Starts or resumes audio recording".
https://developer.apple.com/documentation/avfaudio/avaudiorecorder/1388252-record https://developer.apple.com/documentation/avfaudio/avaudiorecorder/1389435-preparetorecord
Upvotes: 2
Reputation: 241
My solution was:
Start record on temp file
Watch for AVAudioSessionInterruptionNotificatio
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(audioSessionInterruptionNotification:)
name:AVAudioSessionInterruptionNotification
object:audioSession];
-(void)audioSessionInterruptionNotification:(NSNotification*)notification {
NSString* seccReason = @"";
//Check the type of notification, especially if you are sending multiple AVAudioSession events here
NSLog(@"Interruption notification name %@", notification.name);
NSError *err = noErr;
if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
seccReason = @"Interruption notification received";
//Check to see if it was a Begin interruption
if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
seccReason = @"Interruption began";
NSLog(@"Interruption notification name %@ audio pause", notification.name);
dispatch_time_t restartTime = dispatch_time(DISPATCH_TIME_NOW,
0.01 * NSEC_PER_SEC);
dispatch_after(restartTime, dispatch_get_global_queue(0, 0), ^{
AVAudioRecorder *recorder = [[self recorderPool] objectForKey:lastRecID];
if (recorder) {
if(recorder.isRecording) {
[recorder stop];
NSLog(@"Interruption notification name Pauseing recording %@", lastRecID);
} else {
NSLog(@"Interruption notification name Already Paused %@", lastRecID);
}
}else {
NSLog(@"Interruption notification name recording %@ not found", lastRecID);
}
NSLog(@"Interruption notification Pauseing recording status %d",recorder.isRecording);
});
} else if([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeEnded]]){
seccReason = @"Interruption ended!";
NSLog(@"Interruption notification name %@ audio resume", notification.name);
//Start New Recording
dispatch_time_t restartTime = dispatch_time(DISPATCH_TIME_NOW,
0.1 * NSEC_PER_SEC);
dispatch_after(restartTime, dispatch_get_global_queue(0, 0), ^{
AVAudioRecorder *recorder = [[self recorderPool] objectForKey:lastRecID];
NSLog(@"Interruption notification Resumeing recording status %d",recorder.isRecording);
if (recorder) {
if(!recorder.isRecording) {
NSString *filePath = [[self orgFileNames] objectForKey:lastRecID];
NSArray * fileNames =[[self fileNames] objectForKey:lastRecID];
NSString *tmpFileName = [self gnrTempFileName:filePath AndNumber:fileNames.count];
[[[self fileNames] objectForKey:lastRecID] addObject:tmpFileName];
NSURL *url = [NSURL fileURLWithPath:tmpFileName];
NSError *error = nil;
recorder = [[AVAudioRecorder alloc] initWithURL:url settings:recordSetting error:&error];
if (![recorder record]) {
NSLog(@"Interruption notification Error Resumeing recording %@",tempRecorder);
return;
}
[[self recorderPool] setObject:recorder forKey:lastRecID];
NSLog(@"Interruption notification nameResumeing recording %@",lastRecID);
}else {
NSLog(@"Interruption notification Already Recording %d",recorder.isRecording);
}
}else {
NSLog(@"Interruption notification name recording %@ not found",lastRecID);
}
});
}
}
}
Upvotes: 1
Reputation: 940
Looks like its a bug with apple's API. Great fun....
This was the response we received from a support ticket.
"The behavior you described is a bug and unfortunately there's nothing in the API that you can change to work around to actually append to the original recording. The interruption is resulting in capturing only the audio recorded after the interruption. You could try and stop the recording after the interruption then creating a new file after which would at least not cause the user to loose any information, but the result would be two separate files.
Please file a bug report at for this issue since bugs filed by external developers are critical when iOS engineering is evaluating critical features of fixes to address. It's easily reproducible but if you have a test app you can include please do, iOS engineering like having apps that show the bug directly. "
Upvotes: 9
Reputation: 129
You will try by using this piece of code
-(IBAction)pauseandplay:(id)sender
{
BOOL status= [player isPlaying];
if(status)
{
[pauseplay setImage:[UIImage imageNamed:@"play.png"]];
[player pause];
}
else
{
[pauseplay setImage:[UIImage imageNamed:@"icon-pause.png"]];
[player play];
updateTimer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:@selector(updateCurrentTime) userInfo:player repeats:YES];
}
}
Upvotes: -4