我的iPad声音应用程序(iOS 7.1)能够在后台录制。只要录制在后台不中断,一切都可以。例如,如果有人(愚蠢的?)想法在录制内容时开始听音乐。
我尝试以不同方式管理这种中断,但没有成功。问题是
- (void)audioRecorderEndInterruption:(AVAudioPlayer *)p withOptions:(NSUInteger)flags
当应用程序在后台发生中断时,永远不会被触发。然后,我尝试在另一个解决方案中实现AVAudioSessionInterruptionNotification和handleInterruption:方法
- (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));
}
}
在这种情况下,handleInterruption:在中断开始时被触发,但不是在中断结束时(在中断类型设置为AVAudioSessionInterruptionTypeEnded时触发)
为了避免这个问题,我决定在中断开始时设置一个标志( interruptionBeganWhileInBackgroundMode ),让应用程序通知前台时发生了中断。这样我就可以管理中断的结束。
看起来很聪明,但事实并非如此!这就是为什么......
我尝试了两种实现。
解决方案1 。在handleInterruption中设置[记录器暂停]:当中断开始时,并在设置中断标志时在comingForeground:方法中管理[记录器记录]。 在这种情况下,当应用程序返回到前台时,记录立即进行, BUT而不是恢复,记录器擦除文件并重新开始新的记录,以便在中断之前记录的所有内容都丢失。 / p>
解决方案2 。在handleInterruption中放置[记录器停止]:当中断开始时,保存文件,以确保保存记录的数据。保存此记录,但是当应用程序即将到来时,它会停止大约十秒钟,然后用户才能再次进行交互,就好像有一个进程(文件保存?)使UI保持冻结状态。
最后一点:我在此应用程序的iPhone版本中遇到了完全相同的问题:当应用程序处于前台并且发生电话呼叫时,一切正常。但是当我的应用程序处于后台时出现电话时,我会看到与iPad版本相同的不良行为。
我注意到iOS7中Apple的语音备忘录应用程序正确管理这些后台中断(它停止并保存录制),尽管它在前景时显示文件长度为00:00:00 。 iTalk 应用程序可以完美地管理它,在前景时自动恢复录制。
有没有人找到针对背景录制应用的音频中断管理的解决方法?我发现很多人在很多开发者网站上都在寻找,但没有答案......谢谢!
答案 0 :(得分:2)
我自己也经历过同样的问题。似乎iOS7 AVAudioRecorder中存在一个如何处理中断的错误。而不是暂停,因为我认为文档说应该,它关闭文件。当它回到前台时,我无法弄清楚什么阻碍了应用程序。在我的情况下,我会看到AVAudioRecorder在10秒后完成(成功标志设置为NO)。
我最终使用音频队列重写了录音机。我在这里找到了一些示例代码(git@github.com:vecter / Audio-Queue-Services-Example.git),它帮助在Objective-C环境中进行设置,Apple SpeakHere演示有一些代码来处理中断通知
基本上,我在中断开始时停止录制,并为用户打开警报以保存文件。如果在应用程序处于后台时中断开始,则会传递此警报,直到UIApplicationDidBecomeActiveNotification为止。
另外需要注意的是,音频队列中似乎存在一个小错误,即AudioQueueStart方法有时会返回-50。如果你添加
AudioSessionInitialize(NULL, NULL,nil,(__bridge void *)(self));
UInt32 sessionCategory = kAudioSessionCategory_PlayAndRecord;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
sizeof(sessionCategory),
&sessionCategory
);
AudioSessionSetActive(true);
在任何AudioQueue方法之前,错误消失了。这些方法被标记为已弃用,但似乎是必要的。
答案 1 :(得分:0)
不知道/认为这与该主题的原作者有关,但这是我的经验:
由于AVAudioSessionInterruptionNotification的缘故,我最终到了这里; .began的味道和预期的一样,但是那个没有。 在我的情况下,它发生是因为我使用了两个AVPlayer实例:一个用于播放音乐,另一个用于播放静音,而第一个用于开始流式传输新曲目(否则iOS会在后台暂停我的应用,如果下一个曲目加载速度不够快。)
原来这不是最聪明的解决方案,它以某种方式弄乱了通知系统。放弃第二个AVPlayer(沉默播放一个)导致按预期触发。 当然,我找到了通知问题的答案/解决方案,但我现在离开了旧的......: - )