LoginSignup
3
0

More than 3 years have passed since last update.

MediaSessionConnectorを使った再生/停止制御でハマった話

Last updated at Posted at 2019-06-13

はじめに

音楽や動画を扱うアプリではExoPlayerとMedia Sessionを組み合わせることが多いと思います。
そのため、ExoPlayerにはMedia SessionのCallbackと同期してExoPlayerの再生/停止などの制御を行うExoPlayer MediaSession extensionという拡張機能が用意されています。

ExoPlayer MediaSession extension

このコアとなっているのはMediaSessionConnectorというクラスで、このクラスがExoPlayerとMedia Sessionを接続する役割を担っています。
このクラスを使って再生/停止制御をしようと思ったときにハマった部分があったので、その内容を以下に記載します。

r2.9.6までonPlay()/onPause()はExoPlayerの制御を行ってくれなかった

冒頭にも記載した通り、MediaSessionConnectorはMedia SessionのCallbackと同期してExoPlayerの再生/停止などの制御を行うときのコアとなるクラスです。
利用するときの最低限の実装は以下のような感じになります(onGetRoot()onLoadChildren()は省略)。

class SampleMediaBrowserService : MediaBrowserServiceCompat() {

  private lateinit var exoPlayer: SimpleExoPlayer
  private lateinit var mediaSession: MediaSessionCompat

  override onCreate() {

    // ExoPlayerの初期化
    exoPlayer = SimpleExoPlayer.newSimpleInstance(this)

    // MediaSessionの初期化
    mediaSession = MediaSessionCompat(this, "media_session").apply {
      setFlags(
        MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
        or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
      )
      setSessionToken(sessionToken)
      isActive = true
      ...
    }

    // MediaSessionConnectorの初期化
    // 必要に応じて各種Callbackをセットする
    // 例:PlaybackPreparer、PlaybackControllerなど
    MediaSessionConnector(mediaSession, /* playbackController= */ null).apply {
      setPlayer(exoPlayer, /* playbackPreparer= */ null)
      ...
    }
  }

  ...

}



このように設定することでExoPlayerの再生/停止制御を行ってくれるとてっきり思っていたのですが、どうやらそうではなく、MediaSessionConnectorの処理としてはMedia Session側に処理を委譲しているだけでした。
ソースコード全体はこちらから確認できます。

MediaSessionConnector(r2.9.6)#LL850-862
@Override
public void onPlay() {
  if (canDispatchToPlaybackController(PlaybackStateCompat.ACTION_PLAY)) {
    playbackController.onPlay(player);
  }
}

@Override
public void onPause() {
  if (canDispatchToPlaybackController(PlaybackStateCompat.ACTION_PAUSE)) {
    playbackController.onPause(player);
  }
}



そのため、Media SessionにCallback(PlaybackController)をセットし、その実装の中でExoPlayerに対して自前で再生/停止制御を行ってあげなければなりません
(正直「マジかよ…overrideしないといけないメソッド増えてむしろ分かりづらくなるやん…」と思い、一旦は使うのをやめてしまいました。)

r2.10.0からはonPlay()/onPause()はExoPlayerの制御を行ってくれるようになった

ところが、r2.10.0からはMediaSessionConnector内で再生/停止制御を行ってくれる実装になっていました。ソースコード全体はこちらから確認できます。

MediaSessionConnector(r2.10.0)#LL1045-1064
@Override
public void onPlay() {
  if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_PLAY)) {
    if (player.getPlaybackState() == Player.STATE_IDLE) {
      if (playbackPreparer != null) {
        playbackPreparer.onPrepare();
      }
    } else if (player.getPlaybackState() == Player.STATE_ENDED) {
      controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
    }
    controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ true);
  }
}

@Override
public void onPause() {
  if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_PAUSE)) {
    controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false);
  }
}

おわりに

ExoPlayerはバージョンアップの度に結構な破壊的変更が入るので、現在使っているバージョン次第ではさくっとアップデートできる場合とそうでない場合があるとは思いますが、これでやっとExoPlayerに対して自前で再生/停止制御を行わずに済みそうです。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0