在来电之后打开al声音不播放,直到app重启

时间:2012-12-02 12:51:30

标签: objective-c ios openal audio

我正在使用OpenAL播放游戏声音,并使用标准AV播放音乐。最近我发现之后 当bg音乐仍在播放时,来电所有开放的声音都不起作用。如果我强制停止应用程序并重新开始 声音再次出现。 smbd碰巧知道在来电期间/之后发生了什么事情?

2 个答案:

答案 0 :(得分:1)

好的,我似乎找到了解决方案。 我正在使用obj-c声音管理器,所以我只是将AVAudioSession(和AVAudioPlayer)的beginInterruption和endInterruption委托方法添加到我的班级。

beginInterruption看起来像:

alcMakeContextCurrent(NULL);

和endInterruption看起来像:

    NSError * audioSessionError = NULL;
    [audioSession setCategory:soundCategory error:&audioSessionError];
    if (audioSessionError)
    {
        Log(@"ERROR - SoundManager: Unable to set the audio session category");
        return;
    }

    // Set the audio session state to true and report any errors
    audioSessionError = NULL;
    [audioSession setActive:YES error:&audioSessionError];
    if (audioSessionError)
    {
        Log(@"ERROR - SoundManager: Unable to set the audio session state to YES with error %d.", (int) result);
        return;
    }

        //music players handling
    bool plays = false;
    if (musicPlayer[currentPlayer] != nil)
        plays = [musicPlayer[currentPlayer] isPlaying];
    if (musicPlayer[currentPlayer] != nil && !plays)
        [musicPlayer[currentPlayer] play];

    alcMakeContextCurrent(context);

是的,如果您只使用openAL声音,则此功能正常。但要播放长曲目,你应该使用AVAudioPlayer。 但这里再次是苹果魔术!如果您与OpenAL一起播放音乐,则会发生奇怪的事情。 取消传入呼叫,AVAudioPlayerDelegate :: audioPlayerEndInterruption将永远不会调用AVAudioSessionDelegate :: endInterruption。只有beginInterruption,而不是结束。 即使AppDelegate :: applicationWillEnterForeground也不会被调用,app也不知道我们已经返回。

但好消息是你可以在 AppDelegate :: applicationDidBecomeActive 方法中调用endInterruption,并恢复openAL上下文。这很有效!

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if (MySoundMngr != nil)
    {
        [MySoundMngr endInterruption];
    }

    // Restart any tasks that were paused and so on....
}

答案 1 :(得分:0)

我很难弄清楚这一点,所以想在这里添加我的答案。这都是专门在 Xamarin 中的,但我怀疑它普遍适用并且类似于@Tertium 的回答

  • 您可以使用 AVAudioSession.SharedInstance().SetPrefersNoInterruptionsFromSystemAlerts(true, out NSError err);

    防止 iOS 在某些情况下(例如,接到电话但拒绝接听电话)中断您的音频
  • 您在某些情况下仍会被打扰(例如,您接听电话)。要捕获这些内容,您必须在启动应用程序时AVAudioSession.Notifications.ObserveInteruption(myAudioInterruptionHandler);

在此处理程序中,您可以确定是关闭还是像这样返回:

void myAudioInterruptionHandler(object sender, AVAudioSessionInterruptionEventArgs args) {
  args.Notification.UserInfo.TryGetValue(
    new NSString("AVAudioSessionInterruptionTypeKey"),
    out NSObject typeKey
  );
  bool isBeginningInterruption = (typeKey.ToString() == "1");
  // ...
}

中断开始

当中断开始时,停止正在播放的任何音频(您需要根据您的应用自行处理此问题,但可能通过对所有内容调用 AL.SourceStop)。 然后,批判性地,

ContextHandle audioContextHandle = Alc.GetCurrentContext();
Alc.MakeContextCurrent(ContextHandle.Zero);

如果您不立即执行此操作,iOS 会破坏您的 ALC 上下文,而您注定要失败。请注意,如果您有 AudioRouteChanged 的处理程序,这也是迟到,您必须在 AudioInterruption 处理程序中执行此操作。

中断结束

当您从中断中恢复过来时,首先重新启动您的 iOS 音频会话: AVAudioSession.SharedInstance().SetActive(true);

您可能还需要重置您的首选输入(如果您始终使用默认输入,我认为此步骤是可选的)AVAudioSession.SharedInstance().SetPreferredInput(Input, out NSError err)

然后恢复你的上下文 Alc.MakeContextCurrent(audioContextHandle);