web-dev-qa-db-ja.com

iOS 4:バックグラウンドオーディオ用のリモコン

現在、iOS 4用に開発しているアプリのバックグラウンドオーディオを設定しようとしています。ただし、Pandoraなどの他のバックグラウンドオーディオアプリとは異なり、アプリには専用の音楽プレーヤーviewControllerがありません。タスクが少し混乱します。

適切なInfo.plist設定を正しく設定し、アプリデリゲートにAVAudioPlayerオブジェクトがあり、どこからでもアクセスできます。ユーザーが曲を再生するとき、私はAVAudioPlayerをその曲で初期化された新しいものに置き換えて、それを再生します。これはすべてうまく機能しますが、リモートコントロールイベントをサポートする方法がわかりません。

Appleのドキュメントに基づいて、私はこれを持っています:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    [self becomeFirstResponder];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
    [self resignFirstResponder];
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}

- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
    switch(event.subtype) {
        case UIEventSubtypeRemoteControlTogglePlayPause:
            if([iPhoneAppDelegate backgroundAudioPlayer].playing)
                [iPhoneAppDelegate pauseBackgroundAudioPlayer];
            else
                [iPhoneAppDelegate playBackgroundAudioPlayer];
            break;
    }
}

問題は、これをどこに置くかということです。 Appleのドキュメントは、これがどこかのView Controllerに含まれるべきだと示唆しているようですが、私のアプリには多くのViewControllerとNavigationControllerがあります。これをどこに置いても、何らかの理由でマルチタスクトレイのリモコンの[再生/一時停止の切り替え]ボタンをタップすると、曲が一時停止してから一時停止が解除されるか、何らかの理由で曲が2回再生されます。

31
Anshu Chimala

少し検索した後、Apple開発者フォーラムでグローバルリモートコントロールイベントを受信するためのいくつかの解決策を見つけました。

1つの方法は、UIWindowをサブクラス化し、そのremoteControlReceivedWithEvent:をオーバーライドすることです。

2番目の、おそらくより良い方法は、UIApplicationをサブクラス化し、sendEvent:をオーバーライドすることです。このようにして、すべてのリモートコントロールイベントをインターセプトしてグローバルに処理し、レスポンダーチェーンの後半で他のレスポンダーに処理させることはできません。

- (void)sendEvent:(UIEvent *)event {
     if (event.type == UIEventTypeRemoteControl) {
          // Handle event
     }
     else
          [super sendEvent:event];
}
19
Anshu Chimala

ドキュメントの例は少し誤解を招く可能性がありますが、どこにもサブクラス化する必要はありません。 remoteControlReceivedWithEvent:を配置する正しい場所は、アプリがフォアグラウンドにあるかどうかに関係なく、レスポンダーチェーンに残るため、アプリケーションデリゲートにあります。また、リモートコントロールイベントの受信の開始/終了は、ランダムビューの可視性ではなく、実際にイベントが必要かどうかに基づいて行う必要があります。

37

2番目のメソッドは機能しませんでした。sendEventは呼び出されませんでした。ただし、最初の方法はうまく機能しました(UIWindowをサブクラス化)。

4
Stelian Iancu

私はしばらくこれに苦労しました、そして上記の答えのどれもうまくいきませんでした。私のコードのバグ、そしてそれが誰かがこれを読むのに役立つことを願っていますが、AudioSessionを他の人とミックスするように設定したことでした。リモートコントロールイベントを取得するには、フォアグラウンドオーディオプレーヤーになりたいと考えています。次のような誤ったコードがあるかどうかを確認してください。

    [[AVAudioSession sharedInstance] setDelegate: self];
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
    UInt32 doSetProperty = 0;
    AudioSessionSetProperty (
                             kAudioSessionProperty_OverrideCategoryMixWithOthers,
                             sizeof (doSetProperty),
                             &doSetProperty
                             );
    NSError *activationError = nil;
    [[AVAudioSession sharedInstance] setActive: YES error: &activationError];       

そして、AudioSessionSetPropertyを削除するか、doSetPropertyを1に変更します。

3
Sherwin Zadeh

この動作に影響を与えると思われるものの1つは、setCategory:error:の代わりにsetCategory:withOptions:error:を使用してAVAudioSessionに設定したカテゴリオプションです。特に、試行錯誤の結果、AVAudioSessionCategoryOptionMixWithOthersを設定した場合、リモートコントロールイベントは取得されないようです。現在再生中のコントロールは引き続きiPodアプリを制御します。 AVAudioSessionCategoryOptionDuckOthersを設定すると、リモートコントロールイベントが発生しますが、どのアプリが制御されているかに関してあいまいさがあるようです。 categoryOptionsを0に設定するか、setCategory:error:を呼び出すだけが最適です。

0
Jimmy Dee
0

Windowをサブクラス化したり、イベントを転送したりする必要はありません。メインのViewControllerから処理するだけです。詳細については、オーディオミキサー(MixerHost)の例を参照してください。

http://developer.Apple.com/LIBRARY/IOS/#samplecode/MixerHost/Listings/Classes_MixerHostViewController_m.html

0
slf