打开 al 声音在来电后不播放,直到应用重新启动
Posted
技术标签:
【中文标题】打开 al 声音在来电后不播放,直到应用重新启动【英文标题】:open al sounds don't play after the incoming call, until app restart 【发布时间】:2012-12-02 12:51:30 【问题描述】:我使用 OpenAL 播放游戏声音,使用标准 AV 播放背景音乐。最近我发现在 当 bg 音乐仍在播放时,来电所有 openal 声音都不起作用。如果我强制停止应用程序并重新开始 声音再次出现。 smbd 是否知道在来电期间/之后 openal 发生了什么?
【问题讨论】:
刚刚找到:developer.apple.com/library/ios/documentation/Audio/Conceptual/…。应该阅读以了解问题所在 【参考方案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 的声音,就会发生一些奇怪的事情。 取消来电和 AVAudioSessionDelegate::endInterruption 与 AVAudioPlayerDelegate::audioPlayerEndInterruption 永远不会调用。只有开始中断,没有结束。 甚至 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....
【讨论】:
我在 iOS 10 上仍然遇到这种问题。我认为interruption
是为 AVAudio
s 设计的。你的意思是OpenAL
的东西也需要中断吗?
为了避免所有令人头疼的问题,我已经停止写目标 c 并开始使用 xamarin 和 c#(VS2015+Xamarin 现在是免费的)。由于有缺陷的 xcode 和丑陋的语言,在开发过程中遭受了痛苦,然后应用程序甚至无法工作 - 不,这对我来说太过分了,现在人们有了另一种选择。至少我很高兴地发展:)
Alc.MakeContextCurrent(ContextHandle.Zero);
on interrupt 是这里的关键。【参考方案2】:
我很难弄清楚这一点,所以想在这里添加我的答案。这都是 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);
【讨论】:
以上是关于打开 al 声音在来电后不播放,直到应用重新启动的主要内容,如果未能解决你的问题,请参考以下文章
托管在 Azure 上的点网 mvc 应用程序突然一次又一次地重定向到登录页面,直到重新启动