中断後にAudioSessionSetActiveが失敗する

私は何週間も実際に何が起こったのか把握しようとしていましたが、なぜ中断後に再生を続けることができないのかわからないので、おそらく皆さんは答えを知っています。 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 /と/ amaudiostreamer/src/122de41fe6c0/AMAudioStreamer/AMAudioStreamer/Classes/NxAudioStreamer.m が問題を解決するのに役立ちます。

8

6 答え

AudioQueue APIを使用している場合は、いくつかの要因に応じていくつかの追加ステップを実行する必要があります。私はそれをしたことがないので、私は専門家に説明を残します:
Apple DeveloperのWebサイトにその問題に関する正確な情報を記載したビデオがあります。 WWDC 2010セッション412 iPhone OSパート1のオーディオ開発について45分ほどで、そのことについてかなり良い説明があります。

3
追加された
そのビデオにはたくさんのものがあります。私が正しく覚えていれば、AudioSessionカテゴリのセクションがあります。おそらくそこに何かが見つかります。
追加された 著者 Vincent Bernier,
私はまだAudioSessionSetActive(true)を取得できません。返す!猫、おそらくそれは何を返すかどうか、私がしなければならないすべての再生を続行する必要はありません。ですから、基本的には、ハードウェアコーデックを使用しながらAudioQueueを処分して再作成する必要があります。これはあなたの返事のおかげで非常に重要です。
追加された 著者 Andy,

私は問題を抱えていました.Appleの実行中にAlarmが来ると、ユーザーはデバイスの電源ボタンを押すだけでスリープ状態になります。次に、スリープから復帰した後、 AudioSessionSetActive は "このオーディオタイプを使用できません"のようなもので失敗します。私はInterruptedListenerの AudioSessionSetActive(true)の前に audiosession プロパティを追加しようとしましたが、運がありません。 最後に私は追加しました

retry(~1000 times :) 

ftw)

AudioSessionSetActive(true), 

私の問題を解決しました。

2
追加された
当時は完全に管理していなかったと思いますが、それはまったくランダムな動作でした。その後、私はAVFoundationとAVSessionに切り替えました。正に、私はAppleがSDKにバグを持っていたと思うし、このコードがiOS 6でも正しく動作するだろうと推測しているが、それは唯一の仮定だ。
追加された 著者 Andy,

else if 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 メソッドを分析してみてください。

あなたはオーディオのライブストリーミングを使用していますか?キューの開始の問題が解決された質問の回答をお勧めします私の答えで与えられたエラーを処理することによって。

どちらかがあなたに役立つことを願っています。

0
追加された
私は最初にあなたが私の質問の答えでその事を試しなければならないと信じています。しかしここでは、正確な問題を得るのは難しいでしょう。コードを変更する場所を正確に指定する必要があります。私がやった時、これは私のための挑戦でした...あなたに最高の幸運を...あなたが問題を解決できることを願っています...
追加された 著者 DShah,
期待どおり、それは動作しませんし、よりファッショナブルな方法で同じエラーが表示されます: "AVAudioSessionでカテゴリを設定できませんでした。操作を完了できませんでした(OSStatusエラー560161140)。私はrioInterruptionListenerを分析しようとします。私はちょっとしたことを逃したと思います。
追加された 著者 Andy,

私はそれが私のために働く方法をいくつか持って、あなたのリスクを試すことができます。

この関数

void _audioSessionInterruptionListener(void *inClientData, UInt32 inInterruptionState)

除去する

[(NxAudioStreamer*)inClientData handleInterruptionChangeToState:inInterruptionState];

no need to call handleInterruptionChangeToState when you can directly handle it in audioSessionInterruptionListener because audioSessionInterruptionListener has inInterruptionState as a parameter. So modify your to 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");
    }
}
0
追加された
私はこれをあきらめ、AVFoundationを使用すると思います。なぜなら、iOS 3はもう私にとって重要ではないからです。とにかくお返事ありがとうございます。
追加された 著者 Andy,

> オーディオセッションプログラミングガイドクッキングブックのセクション、コードサンプル(状況に応じて互換性があると思われる) kAudioSessionCategory_MediaPlaybackを使用して)実際には

AudioSessionSetActive(FALSE);

kAudioSessionBeginInterruption の場合は

AudioSessionSetActive(TRUE);

kAudioSessionEndInterruption の場合は呼び出します。私は本当にあなたがこれをやるべきだとは思わない。 この投稿この問題も(kAudioSessionIncompatibleCategoryを取得して)説明しているようです。これらの呼び出しを両方ともコメントアウトするとどうなりますか?

フォアグラウンドではなく、バックグラウンドであなたのアプリがミステリーであるときに問題が発生する理由。おそらく[自己ポーズ](トグルプレイ状態)が呼び出されているように(おそらくNX_STATE_PLAYを使っているような)状態を追跡し、次に2つの異なるメソッド([セルフポーズ]と[セルフプレイ])を持つべきです。予期しない回数。

0
追加された
[セルフポーズ]は2回しかコールされていないので、基本的にAudioQueuePauseで割り込みを開始し、AudioQueueStartで割り込みを終了しました。 VERIFY_OSS AudioSessionSetActive(true) - '!cat' VERIFY_OSS AudioQueueStart(audioQueue、NULL) - -12985 VERIFY_OSS AudioSessionSetActive(true) - '!cat' VERIFY_OSS AudioQueueStart(audioQueue、NULL) - -12985私は、私のコードからAudioSessionSetActive(FALSE)を削除しました。
追加された 著者 Andy,

kAudioSessionEndInterruptionはあなたのコードにヒットすることも、ヒットしないこともあります。あなたのプレイ状態をコントロールする信頼できる方法ではなく、あなたのコードでオーディオセッションをオフにしないでください。 AudioSessionSetActive(FALSE)をコメントアウトするだけで役立ちます。

0
追加された
私はあなたのポイントを参照してください、それは私に戻るオーディオセッションを取得し、再生を続けるのに役立ちません:(
追加された 著者 Andy,