私はOpenALを使用してゲームサウンドを再生し、標準AVを使用してbg音楽を再生しています。最近、着信後、bg musicがまだ再生されている間は、すべてのオープンサウンドが機能しないことがわかりました。アプリを強制的に停止して再開すると、音が再び表示されます。smbdは、着信中/着信後にOpenalに何が起こっているかを知っていますか?
2 に答える
わかりました、解決策を見つけたようです。私は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が呼び出されることはありません。beginInterruptionのみであり、endではありません。AppDelegate :: applicationWillEnterForegroundでさえ呼び出されず、アプリは私たちが戻ってきたことを知りません。
ただし、幸いなことに、AppDelegate :: applicationDidBecomeActiveメソッドでendInterruptionを呼び出すことができ、openALコンテキストが復元されます。そしてこれはうまくいきます!
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if (MySoundMngr != nil)
{
[MySoundMngr endInterruption];
}
// Restart any tasks that were paused and so on....
}
これを理解するのに苦労したので、ここに私の答えを追加したいと思いました。これはすべて特にXamarinにありますが、一般的に適用され、@ Tertiumの答えに似ていると思います
状況によっては、iOS がオーディオを中断するのを防ぐことができます (たとえば、電話がかかってきたが拒否した場合)。
AVAudioSession.SharedInstance().SetPrefersNoInterruptionsFromSystemAlerts(true, out NSError err);
場合によっては、まだ中断されることがあります (たとえば、電話を受けるなど)。これらをキャッチするには
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
this is too lateのハンドラーがある場合は、ハンドラーで実行する必要があることに注意してくださいAudioInterruption
。
中断終了
中断から戻ったら、まず iOS オーディオ セッションを再起動します。
AVAudioSession.SharedInstance().SetActive(true);
優先入力をリセットする必要がある場合もあります (常にデフォルトの入力を使用する場合、この手順はオプションだと思います)。AVAudioSession.SharedInstance().SetPreferredInput(Input, out NSError err)
次に、コンテキストを復元します
Alc.MakeContextCurrent(audioContextHandle);