中断后AudioSessionSetActive失败

时间:2011-10-27 21:06:03

标签: iphone objective-c audioqueue interruption

我试图弄清楚几周内实际发生了什么,我不知道为什么我不能在中断后继续播放,所以你们可能知道答案。 AudioSessionSetActive(TRUE)总是返回'!cat',这是kAudioSessionIncompatibleCategory,重新激活,如果我的应用程序在后台播放,我在不同的应用程序。虽然它工作正常并且如果我在我的应用程序中发现中断时继续播放。

原始代码实际上包含所有包含在宏中的AudioSession和AudioQueue调用,如果它意味着错误,则打印OSStatus,但我删除了它以获得更好的可读性。另外,[self pause]只是暂停,所以基本上它会在upause时调用AudioQueueStart(audioQueue,NULL)但是如果AudioSession失败则它不起作用。

音频会话初始化代码:

AudioSessionInitialize(NULL, NULL, _audioSessionInterruptionListener, self);
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, _audioSessionPropertyListener, self);
AudioSessionSetActive(TRUE);

中断处理程序代码:

- (void)handleInterruptionChangeToState:(AudioQueuePropertyID)inInterruptionState 
{
    if(inInterruptionState == kAudioSessionBeginInterruption)
    {

        NSLog(@"+Interruption"); 

        if(self.state == NX_STATE_PLAY) 
        {
            [self pause];
            AudioSessionSetActive(FALSE);

            isPausedByInterruption = YES;
        }
    }
    else if(inInterruptionState == kAudioSessionEndInterruption) 
    {
        if(isPausedByInterruption) 
        {
            AudioSessionSetActive(TRUE);
            [self pause];

            isPausedByInterruption = FALSE;
        }

        NSLog(@"-Interruption");
    }
}

这个流媒体源代码可以在https://bitbucket.org/and/amaudiostreamer/src/122de41fe6c0/AMAudioStreamer/AMAudioStreamer/Classes/NxAudioStreamer.m找到,如果它能以某种方式帮助解决问题..

6 个答案:

答案 0 :(得分:3)

如果您使用的是AudioQueue API,则需要执行一些取决于某些因素的额外步骤。我从来没有这样做过,所以我会把解释留给专家:
Apple开发人员网站上有关于该主题的视频,其中涵盖了该问题。 WWDC 2010会议412 iPhone OS第1部分的音频开发大约在第45分钟你就此问题得到了很好的解释。

答案 1 :(得分:2)

我遇到了问题,当应用程序运行期间出现警报时,用户只需按下设备电源按钮即可进入睡眠状态。然后,从睡眠状态恢复后,我的AudioSessionSetActive失败并显示“this audiosession type can't be used”之类的内容。我尝试在Interruptionlistener中set audiosession之前添加AudioSessionSetActive(true)属性,但没有运气。 最后我添加了

retry(~1000 times :) 

ftw)

AudioSessionSetActive(true), 

它解决了我的问题。

答案 2 :(得分:0)

尝试在 else if 条件下激活AudioSession,如下所示:

AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error = nil;

[session setCategory: AVAudioSessionCategoryPlayback error: &error];
if (error != nil)
    NSLog(@"Failed to set category on AVAudioSession");

// AudioSession and AVAudioSession calls can be used interchangeably
OSStatus result = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, RouteChangeListener, self);
if (result) NSLog(@"Could not add property listener! %d\n", result);

BOOL active = [session setActive: YES error: nil];
if (!active)
    NSLog(@"Failed to set category on AVAudioSession");

但是我相信这可能行不通,因为在我的情况下发生的事情是当我在后台时它没有得到任何会话。但是,请尝试分析Apple的aurioTouch example并仅浏览AppDelegate文件并尝试分析解释同一问题的(void)rioInterruptionListener方法。

您使用的是直播音频吗?那么我建议你浏览我的question's answer,通过处理我的答案中给出的错误来解决队列启动问题。

希望这对你有帮助。

答案 3 :(得分:0)

kAudioSessionEndInterruption可能会或可能不会打到您的代码,它不是控制播放状态的可靠方法,只是不要在代码中关闭音频会话,一旦它再次获得控制权,它将恢复会话,你的情况,只需注释掉AudioSessionSetActive(FALSE)就可以帮到你。

答案 4 :(得分:0)

如果您查看Audio Session Programming Guide cookbook section中的Listing 7-16 An interruption listener callback function,代码示例(似乎与您的情况兼容,使用kAudioSessionCategory_MediaPlayback)实际上并不执行

AudioSessionSetActive(FALSE);

kAudioSessionBeginInterruption

的情况下打电话
AudioSessionSetActive(TRUE);

kAudioSessionEndInterruption的情况下打电话。我真的不认为你应该这样做。 This post似乎也解释了这个问题(得到一个kAudioSessionIncompatibleCategory)。如果你注释掉这两个电话怎么办?

当你的应用程序在后台,而不是前景是一个谜时,问题发生的原因。你应该跟踪状态(你似乎正在使用NX_STATE_PLAY),然后有两种不同的方法([self pause]和[self play]),因为[self pause](切换播放状态)可能被称为意外的次数。

答案 5 :(得分:0)

我知道了如何为我工作,你可以尝试冒风险。

在功能

void _audioSessionInterruptionListener(void *inClientData, UInt32 inInterruptionState)

删除

[(NxAudioStreamer*)inClientData handleInterruptionChangeToState:inInterruptionState];

handleInterruptionChangeToState,因为audioSessionInterruptionListeneraudioSessionInterruptionListener作为参数,因此无法在inInterruptionState中直接处理audioSessionInterruptionListener。因此请将您修改为void _audioSessionInterruptionListener(void *inClientData, UInt32 inInterruptionState) { if(inInterruptionState == kAudioSessionBeginInterruption)     {         NSLog(@"+Interruption");         if(self.state == NX_STATE_PLAY)         {             [self pause];             AudioSessionSetActive(FALSE);             isPausedByInterruption = YES;         }     }     else if(inInterruptionState == kAudioSessionEndInterruption)     {         if(isPausedByInterruption)         {             AudioSessionSetActive(TRUE);             [self pause];             isPausedByInterruption = FALSE;         }         NSLog(@"-Interruption");     } }

{{1}}