Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

メディア ブラウザ クライアントの作成

クライアント / サーバーの設計を完了するには、UI のコード、関連する MediaController、MediaBrowser を含むアクティビティ コンポーネントを作成する必要があります。

MediaBrowser は、MediaBrowserService への接続と、それに続く UI 用 MediaController の作成という、2 つの重要な機能を担います。

注: MediaBrowser の推奨される実装は、media-compat サポート ライブラリで定義されている MediaBrowserCompat です。このページ全体を通して、「MediaBrowser」という用語は MediaBrowserCompat のインスタンスを指します。

MediaBrowserService への接続

クライアント アクティビティでは、作成されたときに MediaBrowserService に接続します。そのために、多少の調整が必要となります。すなわち、アクティビティのライフサイクル コールバックを次のように変更します。

  • onCreate() では、MediaBrowserCompat を構築します。ここで、MediaBrowserService の名前と、定義した MediaBrowserCompat.ConnectionCallback を渡します。
  • onStart() では、MediaBrowserService に接続します。ここで、MediaBrowserCompat.ConnectionCallback が利用されます。接続が成功したら、onConnect() コールバックでメディア コントローラを作成し、それをメディア セッションに接続して UI を MediaController に接続したうえで、メディア セッションからのコールバックを受信するようコントローラを登録します。
  • onResume() では、アプリがデバイスの音量コントロールに応答できるように音声ストリームを設定します。
  • onStop() では、MediaBrowser を切断し、アクティビティが停止した場合は MediaController.Callback の登録を解除します。

Kotlin

    class MediaPlayerActivity : AppCompatActivity() {

        private lateinit var mediaBrowser: MediaBrowserCompat

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // ...
            // Create MediaBrowserServiceCompat
            mediaBrowser = MediaBrowserCompat(
                    this,
                    ComponentName(this, MediaPlaybackService::class.java),
                    connectionCallbacks,
                    null // optional Bundle
            )
        }

        public override fun onStart() {
            super.onStart()
            mediaBrowser.connect()
        }

        public override fun onResume() {
            super.onResume()
            volumeControlStream = AudioManager.STREAM_MUSIC
        }

        public override fun onStop() {
            super.onStop()
            // (see "stay in sync with the MediaSession")
            MediaControllerCompat.getMediaController(this)?.unregisterCallback(controllerCallback)
            mediaBrowser.disconnect()
        }
    }
    

Java

    public class MediaPlayerActivity extends AppCompatActivity {
      private MediaBrowserCompat mediaBrowser;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ...
        // Create MediaBrowserServiceCompat
        mediaBrowser = new MediaBrowserCompat(this,
          new ComponentName(this, MediaPlaybackService.class),
            connectionCallbacks,
            null); // optional Bundle
      }

      @Override
      public void onStart() {
        super.onStart();
        mediaBrowser.connect();
      }

      @Override
      public void onResume() {
        super.onResume();
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
      }

      @Override
      public void onStop() {
        super.onStop();
        // (see "stay in sync with the MediaSession")
        if (MediaControllerCompat.getMediaController(MediaPlayerActivity.this) != null) {
          MediaControllerCompat.getMediaController(MediaPlayerActivity.this).unregisterCallback(controllerCallback);
        }
        mediaBrowser.disconnect();

      }
    }
    

MediaBrowserCompat.ConnectionCallback のカスタマイズ

アクティビティで MediaBrowserCompat を構築するときは、ConnectionCallback のインスタンスを作成する必要があります。その onConnected() メソッドを変更して、MediaBrowserService からメディア セッション トークンを取得し、そのトークンを使用して MediaControllerCompat を作成します。

MediaControllerCompat.setMediaController() という便利なメソッドを使用して、コントローラへのリンクを保存します。これにより、メディアボタンの処理が可能になります。また、トランスポート コントロール作成時に MediaControllerCompat.getMediaController() を呼び出してコントローラを取得することも可能になります。

次のコードサンプルは、onConnected() メソッドをどのように変更するかを示しています。

Kotlin

    private val connectionCallbacks = object : MediaBrowserCompat.ConnectionCallback() {
        override fun onConnected() {

            // Get the token for the MediaSession
            mediaBrowser.sessionToken.also { token ->

                // Create a MediaControllerCompat
                val mediaController = MediaControllerCompat(
                        this@MediaPlayerActivity, // Context
                        token
                )

                // Save the controller
                MediaControllerCompat.setMediaController(this@MediaPlayerActivity, mediaController)
            }

            // Finish building the UI
            buildTransportControls()
        }

        override fun onConnectionSuspended() {
            // The Service has crashed. Disable transport controls until it automatically reconnects
        }

        override fun onConnectionFailed() {
            // The Service has refused our connection
        }
    }
    

Java

    private final MediaBrowserCompat.ConnectionCallback connectionCallbacks =
      new MediaBrowserCompat.ConnectionCallback() {
        @Override
        public void onConnected() {

          // Get the token for the MediaSession
          MediaSessionCompat.Token token = mediaBrowser.getSessionToken();

          // Create a MediaControllerCompat
          MediaControllerCompat mediaController =
            new MediaControllerCompat(MediaPlayerActivity.this, // Context
            token);

          // Save the controller
          MediaControllerCompat.setMediaController(MediaPlayerActivity.this, mediaController);

          // Finish building the UI
          buildTransportControls();
        }

        @Override
        public void onConnectionSuspended() {
          // The Service has crashed. Disable transport controls until it automatically reconnects
        }

        @Override
        public void onConnectionFailed() {
          // The Service has refused our connection
        }
      };
    

UI のメディア コントローラへの接続

上記の ConnectionCallback サンプルコードには、UI を具現化する buildTransportControls() 呼び出しが含まれています。プレーヤーを制御する UI 要素には、onClickListener を設定する必要があります。それぞれに対して、適切な MediaControllerCompat.TransportControls メソッドを選択します。

各ボタンに onClickListener を設定したコードは、次のようになります。

Kotlin

    fun buildTransportControls() {
        val mediaController = MediaControllerCompat.getMediaController(this@MediaPlayerActivity)
        // Grab the view for the play/pause button
        playPause = findViewById<ImageView>(R.id.play_pause).apply {
            setOnClickListener {
                // Since this is a play/pause button, you'll need to test the current state
                // and choose the action accordingly

                val pbState = mediaController.playbackState.state
                if (pbState == PlaybackStateCompat.STATE_PLAYING) {
                    mediaController.transportControls.pause()
                } else {
                    mediaController.transportControls.play()
                }
            }
        }

        // Display the initial state
        val metadata = mediaController.metadata
        val pbState = mediaController.playbackState

        // Register a Callback to stay in sync
        mediaController.registerCallback(controllerCallback)
    }
    

Java

    void buildTransportControls()
    {
      // Grab the view for the play/pause button
      playPause = (ImageView) findViewById(R.id.play_pause);

      // Attach a listener to the button
      playPause.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
          // Since this is a play/pause button, you'll need to test the current state
          // and choose the action accordingly

          int pbState = MediaControllerCompat.getMediaController(MediaPlayerActivity.this).getPlaybackState().getState();
          if (pbState == PlaybackStateCompat.STATE_PLAYING) {
            MediaControllerCompat.getMediaController(MediaPlayerActivity.this).getTransportControls().pause();
          } else {
            MediaControllerCompat.getMediaController(MediaPlayerActivity.this).getTransportControls().play();
          }
      });

      MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(MediaPlayerActivity.this);

      // Display the initial state
      MediaMetadataCompat metadata = mediaController.getMetadata();
      PlaybackStateCompat pbState = mediaController.getPlaybackState();

      // Register a Callback to stay in sync
      mediaController.registerCallback(controllerCallback);
    }
    }
    

TransportControls メソッドにより、サービスのメディア セッションにコールバックが送信されます。それぞれのコントロールに対して MediaSessionCompat.Callback メソッドを定義したことを確認してください。

メディア セッションとの同期の維持

UI には、メディア セッションの現在の状態を PlaybackState とメタデータの内容に沿って表示するようにします。トランスポート コントロールを作成すると、セッションの現在の状態を取得して UI に表示し、その状態と現在実施可能なアクションに基づいてトランスポート コントロールを有効または無効にできます。

状態またはメタデータが変化するたびにメディア セッションからコールバックを受信するには、次の 2 つのメソッドを使用して MediaControllerCompat.Callback を定義します。

Kotlin

    private var controllerCallback = object : MediaControllerCompat.Callback() {

        override fun onMetadataChanged(metadata: MediaMetadataCompat?) {}

        override fun onPlaybackStateChanged(state: PlaybackStateCompat?) {}
    }
    

Java

    MediaControllerCompat.Callback controllerCallback =
      new MediaControllerCompat.Callback() {
        @Override
        public void onMetadataChanged(MediaMetadataCompat metadata) {}

        @Override
        public void onPlaybackStateChanged(PlaybackStateCompat state) {}
      };
    

このコールバックは、トランスポート コントロールの作成時に登録し(buildTransportControls() メソッドを参照)、アクティビティの停止時に(そのアクティビティの onStop() ライフサイクル メソッドで)登録を解除します。