在接听来电后无法重新开始录制

时间:2017-09-04 14:21:38

标签: ios core-audio objective-c++ avaudiosession audiounit

我在录制音频时添加了一个观察员来获取中断通知。

这在拨打电话,接听来电和应答,Siri等时工作正常。

现在我的应用程序在后台运行,屏幕顶部有红色条,并且继续以上述状态进行录制不是问题。

但是当我真正接听来电时。我收到了另一个AVAudioSessionInterruptionTypeBegan通知,然后当我停止通话时,我从不获得通知AVAudioSessionInterruptionTypeEnded类型。

我已尝试使用CTCallCenter来检测呼叫何时开始,但我无法从该回调中重新开始录制。

有谁知道如何让中断机制与实际得到应答的来电一起工作?

这是我正在使用的代码的一部分;

CFNotificationCenterAddObserver(
                CFNotificationCenterGetLocalCenter(),
                this,
                &handle_interrupt,
                (__bridge CFStringRef) AVAudioSessionInterruptionNotification,
                NULL,
                CFNotificationSuspensionBehaviorDeliverImmediately );

...

static void handle_interrupt( CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo )
{
    au_recorder *recorder = static_cast<au_recorder*>( observer );

    NSNumber* interruptionType = [( ( __bridge  NSDictionary* ) userInfo ) objectForKey:AVAudioSessionInterruptionTypeKey];
    switch ( [interruptionType unsignedIntegerValue] )
    {
        case AVAudioSessionInterruptionTypeBegan:
        {
            // pause recorder without stopping recording (already done by OS)
            recorder->pause();
            break;
        }
        case AVAudioSessionInterruptionTypeEnded:
        {
            NSNumber* interruptionOption = [( ( __bridge  NSDictionary* ) userInfo ) objectForKey:AVAudioSessionInterruptionOptionKey];

            if ( interruptionOption.unsignedIntegerValue == AVAudioSessionInterruptionOptionShouldResume )
            {
                recorder->resume();
            }
            break;
        }
    }
}

我已尝试将通知绑定到AppDelegate,UIViewController和单独的类,但这似乎没有帮助。

修改 这是我尝试使用CTCallCenter,但这非常不稳定。当从回调中调用recorder->resume()时,它会起作用,剧烈崩溃或根本不做任何事情,直到应用程序再次手动放回到前台。

callCenter = [[CTCallCenter alloc] init];
callCenter.callEventHandler = ^(CTCall *call)
{
   if ([call.callState isEqualToString:CTCallStateDisconnected])
   {
      recorder->resume();
   }
};

1 个答案:

答案 0 :(得分:2)

<强>更新
如果你匆匆等待一秒左右,你可以从你的callEventHandler重新开始录音(虽然你还没有描述过你的暴力事件,但对我来说这很好):

if ([call.callState isEqualToString:CTCallStateDisconnected])
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        self.recorder->resume();
    });
}

这都没有后台任务或更改为独占音频会话。延迟解决了在Phone.app停用其音频会话之前呼叫结束通知进入的问题。 1秒似乎小到足以落入某种背景去安抚宽限期。我已经忘记了在这里假设了多少实现细节,所以也许你想阅读

似乎由文档支持的解决方案:

N.B 虽然有&#34;暗示&#34;的链接该解决方案的文档,主要是由这两个错误弹出及其随附的注释在头文件中引导:

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.

AVAudioSessionErrorInsufficientPriority
   The app was not allowed to set the audio category because another app (Phone, etc.) is controlling it.

您尚未显示AVAudioSession的配置方式,但您未收到AVAudioSessionInterruptionTypeEnded通知这一事实表明您未使用独家音频会话(即你正在设置&#34;与他人混合&#34;):

[session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];

过时的CTCallCenter和更新的CXCallObserver回调似乎发生得太早,在中断结束之前,也许通过一些进一步的工作,您可以找到一种方法来运行重启记录的后台任务a电话结束后不久(我最初的尝试失败了)。

所以现在,我知道在接到电话后重启录音的唯一方法是:

使用独占音频会话(这会让您终止中断):

if (!([session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]
      && [session setActive:YES error:&error])) {
    NSLog(@"Audio session error: %@", error);
}

并与&#34;正在播放&#34;整合(不是开玩笑,这是解决方案的结构部分):

MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
[commandCenter.playCommand addTargetWithHandler:^(MPRemoteCommandEvent *event) {
    NSLog(@"PLAY");
    return MPRemoteCommandHandlerStatusSuccess;
}];

[commandCenter.pauseCommand addTargetWithHandler:^(MPRemoteCommandEvent *event) {
    NSLog(@"PAUSE");
    return MPRemoteCommandHandlerStatusSuccess;
}];
// isn't this mutually exclusive with mwo? or maybe that's remote control keys
// not seeing anything. maybe it needs actual playback?
NSDictionary* nowPlaying = @{
    MPMediaItemPropertyTitle: @"foo",
    MPMediaItemPropertyArtist: @"Me",
    MPMediaItemPropertyAlbumTitle: @"brown album",
};

[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = nowPlaying;

这个解决方案的部分是从Audio Guidelines for User-Controlled Playback and Recording Apps文档中挑选出来的。

P.S。也许锁定屏幕集成或非独占音频会话是您的交易破坏者,但在其他情况下,您永远不会得到结束中断,例如启动另一个独家应用程序,如音乐(虽然这可能不是mixWithOthers的问题,所以也许你应该使用代码嗅觉延迟解决方案。

相关问题