メディアボタンへの応答

メディアボタンとは、Android デバイスや周辺デバイスにあるハードウェア ボタンのことです。たとえば、Bluetooth ヘッドセットの一時停止 / 再生ボタンなどです。ユーザーがメディアボタンを押すと、そのボタン特有の「キーコード」を含む KeyEvent が Android により生成されます。メディアボタン KeyEvent のキーコードは、KEYCODE_MEDIA で始まる名前(たとえば、KEYCODE_MEDIA_PLAY)の定数です。

アプリは、次の順序で 3 つのケースでメディアボタン イベントを処理できるようにする必要があります。 優先度:

  • アプリの UI アクティビティが表示されている場合
  • UI アクティビティが非表示で、アプリのメディア セッションがアクティブの場合
  • UI アクティビティが非表示で、アプリのメディア セッションが非アクティブであり再起動を必要とする場合

フォアグラウンド アクティビティでのメディアボタンの処理

フォアグラウンド アクティビティが onKeyDown() でメディアボタンのキーイベントを受け取る メソッドを呼び出します。実行中の Android のバージョンに応じて、システムがイベントを メディア コントローラ:

  • Android 5.0(API レベル 21)以降を実行している場合は、 FLAG_HANDLES_MEDIA_BUTTONS MediaBrowserCompat.ConnectionCallback.onConnected。これにより、 自動的にメディア コントローラの dispatchMediaButtonEvent(), これにより、キーコードがメディア セッション コールバックに変換されます。
  • Android 5.0(API レベル 21)より前では、onKeyDown() を変更して、 できます。 (詳しくは、アクティブなメディア セッションでのメディアボタンの処理をご覧ください)。 次のコード スニペットは、 ディスパッチ MediaButtonEvent() を呼び出します。true を必ず返品してください。 イベントが処理されたことを示します。

    Kotlin

        fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                return super.onKeyDown(keyCode, event)
            }
            when (keyCode) {
                KeyEvent.KEYCODE_MEDIA_PLAY -> {
                    yourMediaController.dispatchMediaButtonEvent(event)
                    return true
                }
            }
            return super.onKeyDown(keyCode, event)
        }
        

    Java

        @Override
        boolean onKeyDown(int keyCode, KeyEvent event) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                  return super.onKeyDown(keyCode, event);
                }
                switch (keyCode) {
                  case KeyEvent.KEYCODE_MEDIA_PLAY:
                          yourMediaController.dispatchMediaButtonEvent(event);
                          return true;
                }
                return super.onKeyDown(keyCode, event);
        }
        

メディア セッションの検索

フォアグラウンド アクティビティがイベントを処理しない場合、Android は 適切なメディア セッションを指定します。これも実行中のバージョンに応じて Android でメディア セッションを検索するには、次の 2 つの方法があります。

  • Android 8.0(API レベル 26)以降を実行している場合、システムは MediaSession でローカルに音声を再生した最後のアプリを見つけます。セッションが Android はイベントを直接送信します。それ以外の場合、 セッションがアクティブではなくメディアボタン レシーバーがある場合、Android はイベントを送信します。 レシーバーに送信されます。これによりセッションが再開され、イベントを受信できるようになります。 (詳しくは、メディアボタンを使用して非アクティブなメディア セッションを再起動するをご覧ください)。 セッションにメディアボタン レシーバーがない場合、システムはメディアを破棄します。 イベントが発生し、何も起こりません。ロジックを以下に示します。 図:

  • Android 8.0(API レベル 26)より前では、システムはイベントの送信を アクティブなメディア セッション。アクティブなメディア セッションが複数ある場合、Android は 再生準備中(バッファリング/接続中)中のメディア セッションを選択します。 「再生中」、または「一時停止」です。(参照: アクティブなメディア セッションでのメディアボタンの処理 をご覧ください)。アクティブな 直近のアクティブなセッションにイベントを送信しようとします。 (詳しくは、メディアボタンを使用して非アクティブなメディア セッションを再起動するをご覧ください)。 このロジックを次の図に示します。

アクティブなメディア セッションでのメディアボタンの処理

Android 5.0(API レベル 21)以降では、Android は以下を呼び出して、メディア ボタン イベントをアクティブなメディア セッションに自動的にディスパッチします。 onMediaButtonEvent()。 デフォルトでは、このコールバックによって、KeyEvent はキーコードに対応する適切なメディア セッション コールバック メソッドに変換されます。

Android 5.0(API レベル 21)より前の Android では、インテントをブロードキャストすることでメディアボタン イベントを処理します。 ACTION_MEDIA_BUTTON アクションに置き換えます。アプリは BroadcastReceiver を使用してこれらのインテントをインターセプトします。「 MediaButtonReceiver トレーニング用のクラスは できます。これは、Terraform のコンビニエンス クラスです。 Android media-compat ライブラリ ACTION_MEDIA_BUTTON を処理し、受け取ったインテントを 適切な MediaSessionCompat.Callback メソッド呼び出し。

MediaButtonReceiver は存続期間の短い BroadcastReceiver で、着信を転送 インテントを、メディア セッションを管理しているサービスに渡します。「新規顧客の獲得」目標を Android 5.0 より前のシステムでは、メディアボタンを含める必要があります。 MEDIA_BUTTON インテント フィルタを使用して、マニフェストの MediaButtonReceiver をオーバーライドできます。

<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
   <intent-filter>
     <action android:name="android.intent.action.MEDIA_BUTTON" />
   </intent-filter>
 </receiver>

BroadcastReceiver により、インテントはサービスに転送されます。インテントを解析する 次に、メディア セッションへのコールバックを生成して、サービスの onStartCommand()MediaButtonReceiver.handleIntent() メソッドを含めます。 これにより、キーコードが適切なセッション コールバック メソッドに変換されます。

Kotlin

private val mediaSessionCompat: MediaSessionCompat = ...

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    MediaButtonReceiver.handleIntent(mediaSessionCompat, intent)
    return super.onStartCommand(intent, flags, startId)
}

Java

private MediaSessionCompat mediaSessionCompat = ...;

 public int onStartCommand(Intent intent, int flags, int startId) {
   MediaButtonReceiver.handleIntent(mediaSessionCompat, intent);
   return super.onStartCommand(intent, flags, startId);
 }

メディアボタンを使用した非アクティブなメディア セッションの再起動

Android により、最後にアクティブだったメディア セッションの特定ができた場合は、ACTION_MEDIA_BUTTON インテントがマニフェストに登録されたコンポーネント(サービスや BroadcastReceiver など)に送信され、そのセッションの再起動が試みられます。

これにより、UI が表示されていない状態(ほとんどの音声アプリが該当するケース)でアプリの再生を再開できます。

MediaSessionCompat を使用すると、この動作は自動的に有効になります。もし Android フレームワークの MediaSession またはサポート ライブラリ 24.0.0 ~ 25.1.1 メディアボタンでゲームを再起動できるようにするには、setMediaButtonReceiver を呼び出す必要がある 応答がありません。

Android 5.0(API レベル 21)以降では、次の方法でこの動作を無効にできます。 null のメディアボタン レシーバーを設定する場合:

Kotlin

// Create a MediaSessionCompat
mediaSession = MediaSessionCompat(context, LOG_TAG)
mediaSession.setMediaButtonReceiver(null)

Java

// Create a MediaSessionCompat
mediaSession = new MediaSessionCompat(context, LOG_TAG);
mediaSession.setMediaButtonReceiver(null);

メディアボタン ハンドラのカスタマイズ

onMediaButtonEvent() のデフォルトの動作では、キーコードが抽出され、メディア セッションの現在の状態とサポートされているアクションのリストから、呼び出されるメソッドが決定されます。たとえば、KEYCODE_MEDIA_PLAY なら onPlay() が呼び出されます。

すべてのアプリで一貫したメディアボタン エクスペリエンスを提供するには、 特定の目的のためにのみ逸脱します。メディアボタンが 必要な場合は、コールバックの onMediaButtonEvent() メソッドを呼び出し、次を使用して KeyEvent を抽出します。 intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT), 自分でイベントを処理し、true を返します。

概要

Android のすべてのバージョンでメディアボタン イベントを適切に処理するには、 FLAG_HANDLES_MEDIA_BUTTONS を指定する 設定することもできます。

また、サポートする Android のバージョンによっては、 次の要件も満たす必要があります

Android 5.0 以降で実行する場合:

  • メディア コントローラ onConnected() コールバックから MediaControllerCompat.setMediaController() を呼び出す
  • アクティブでないセッションをメディアボタンで再開できるようにするには、以下を呼び出して MediaButtonReceiver を動的に作成します。 setMediaButtonReceiver()PendingIntent を渡す

Android 5.0 より前のシステムで実行する場合:

  • アクティビティの onKeyDown() をオーバーライドしてメディアボタンを処理する
  • MediaButtonReceiver をアプリのマニフェストに追加して静的に作成する