8

私は何週間も実際に何が起こっているのかを理解しようとしていましたが、中断後に再生を続行できない理由がわからないので、おそらく答えを知っているでしょう. AudioSessionSetActive(TRUE) は、アプリがバックグラウンドで再生され、別のアプリにいる場合、再アクティブ化中に kAudioSessionIncompatibleCategory である '!cat' を常に返します。アプリの使用中に中断が発生した場合でも、問題なく動作し、再生を続けます。

元のコードには、実際にはすべての AudioSession および AudioQueue 呼び出しが、エラーを意味する場合に OSStatus を出力するマクロでラップされていますが、読みやすくするために削除しました。また、[セルフポーズ]は一時停止を切り替えるだけなので、基本的には休止時に 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 Webサイトには、その正確な問題をカバーするそのトピックに関するビデオがあります. 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で行っているように)、2つの異なる方法([自己一時停止]と[自己再生])を使用する必要があります。予想外の回数。

于 2011-11-03T23:39:23.533 に答える
0

次のような条件の場合、elseで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 に答える
0

kAudioSessionEndInterruption がコードにヒットする場合とヒットしない場合があります。再生状態を制御するための信頼できる方法ではありません。コードでオーディオ セッションをオフにしないでください。あなたの場合、制御を再び取得できるようになると、セッションが再開されます。 AudioSessionSetActive(FALSE) をコメントアウトするだけで役に立ちます。

于 2011-11-01T12:38:45.087 に答える
0

私はそれが私のためにうまくいく方法を手に入れました、あなたはあなたのリスクを試すことができます.

関数では

void _audioSessionInterruptionListener(void *inClientData, UInt32 inInterruptionState)

削除する

[(NxAudioStreamer*)inClientData handleInterruptionChangeToState:inInterruptionState];

パラメータとして持っているためhandleInterruptionChangeToState、直接処理できる場合は呼び出す必要はありません。だからあなたを変更してくださいaudioSessionInterruptionListeneraudioSessionInterruptionListenerinInterruptionStateaudioSessionInterruptionListener

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 に答える