8

我试图弄清楚几周以来实际发生的事情,但我不知道为什么在中断后我无法继续播放,所以你们可能知道答案。如果我的应用程序在后台播放并且我在不同的应用程序中,则在重新激活时,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如果它会以某种方式帮助解决问题..

4

6 回答 6

3

如果您使用的是 AudioQueue API,您需要根据某些因素执行一些额外的步骤。我从来没有这样做过,所以我将把解释留给专家:
Apple Developer 网站上有一个关于该主题的视频,涵盖了这个确切的问题。WWDC 2010 会议 412 iPhone OS 的音频开发第 1 部分在第 45 分钟左右你已经对这个问题有了很好的解释。

于 2011-11-04T15:34:09.887 回答
2

我有一个问题,当应用程序运行期间警报响起时,用户只需按下设备电源按钮使其进入睡眠状态。然后,从睡眠中恢复后,我的AudioSessionSetActive失败与“ this audiosession type can't be used”类似。我之前尝试在 Interruptionlistener中添加set audiosession属性,但没有运气。AudioSessionSetActive(true)最后我添加了

retry(~1000 times :) 

英尺)

AudioSessionSetActive(true), 

它解决了我的问题。

于 2012-12-13T11:19:49.730 回答
0

如果您查看音频会话编程指南食谱部分Listing 7-16 An interruption listener callback function,代码示例(似乎与您的情况兼容,使用 kAudioSessionCategory_MediaPlayback)实际上并没有执行

AudioSessionSetActive(FALSE);

在 的情况下调用kAudioSessionBeginInterruption,并且

AudioSessionSetActive(TRUE);

的情况下调用kAudioSessionEndInterruption。我真的不认为你应该这样做。这篇文章似乎也说明了这个问题(得到一个 kAudioSessionIncompatibleCategory)。如果你注释掉这两个调用会发生什么?

当您的应用程序在后台而不是前台时出现问题的原因是一个谜。您也许应该跟踪状态(就像您似乎对 NX_STATE_PLAY 所做的那样),然后有两种不同的方法([self pause] 和 [self play]),因为 [self pause](切换播放状态)可能被称为出乎意料的次数。

于 2011-11-03T23:39:23.533 回答
0

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

于 2011-11-01T12:38:45.087 回答
0

我知道了一些对我有用的方法,你可以试试你的风险。

在函数中

void _audioSessionInterruptionListener(void *inClientData, UInt32 inInterruptionState)

消除

[(NxAudioStreamer*)inClientData handleInterruptionChangeToState:inInterruptionState];

handleInterruptionChangeToState当你可以直接处理它时不需要调用它,audioSessionInterruptionListener因为audioSessionInterruptionListenerinInterruptionState作为参数。所以修改你的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");
    }
}
于 2011-11-04T13:11:01.333 回答
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示例 ,仅通过AppDelegate文件和尝试分析(void)rioInterruptionListener解释相同问题的方法。

您是否使用实时音频流媒体?那么我建议您仔细阅读我的问题的答案,通过处理我的答案中给出的错误来解决队列启动问题。

希望这对您有帮助。

于 2011-10-30T16:57:05.457 回答