Media3について
Media3はJetpackライブラリの1つで、2021年10月27日にバージョン1.0.0-alpha01が公開されています。主な用途としてはメディア(動画、配信)周りのサポートをしてくれるライブラリで、元々ExoPlayerというAndroidで利用されているライブラリがありましたが、それを元に作成されたようです。
現状はMedia3とExoPlayerは別のレポジトリとして開発が行われ、しばらくは並行して行っていくようですが、将来的にはMedia3に置き換わっていくように記載されていました。
ローカルファイルの再生
今回はアプリ内にあるmp4ファイルを再生する簡単なアプリを作ってみます。Media3はExoPlayerと同様にメディアセッションの管理やDASH、HLSのサポートやエラー処理など幅広い機能がありますが、それらを実装するとソースコードが増えてしまいますので、最低限の実装を記載しつつ必要であればリファレンスなどを参考にしながら実装してみてください。
まずライブラリをbuild.gradle(app)に足します。以下は最低限のみ記載していますが、他にも多くのライブラリがコンポーネントごとに作られていますので、必要そうなのは取ってきても大丈夫です!
def media3_version = "1.0.0-alpha01"
implementation "androidx.media3:media3-exoplayer:$media3_version"
implementation "androidx.media3:media3-ui:$media3_version"
implementation "androidx.media3:media3-session:$media3_version"
implementation "androidx.media3:media3-test-utils:$media3_version"
続いて、xmlにはStyledPlayerViewというコンポーネントを配置しましょう。以前はPlayerViewというのが主流だったように記憶していますが、ここ数年はStyledPlayerViewが主流なんですかね。間違っていたらすいません…
<androidx.media3.ui.StyledPlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.media3.ui.StyledPlayerView>
最後にアクティビティのコードを記載します。特にこれといったことはしていませんが、createMediaItems関数で再生したいMediaItemのリストとして作成し、initializePlayer関数で作成しています。
class SamplePlayer : AppCompatActivity() {
private lateinit var binding: ActivitySamplePlayerBinding
private lateinit var mediaItems: MutableList<MediaItem>
private var player: ExoPlayer? = null
private var trackSelectionParameters: DefaultTrackSelector.Parameters? = null
private lateinit var trackSelector: DefaultTrackSelector
private var startAutoPlay: Boolean = false
private var startItemIndex: Int = 0
private var startPosition: Long = 0L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySamplePlayerBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.playerView.requestFocus()
trackSelectionParameters =
DefaultTrackSelector.ParametersBuilder( /* context= */this).build()
clearStartPosition()
}
override fun onStart() {
super.onStart()
if (Util.SDK_INT > 23) {
initializePlayer()
binding.playerView.onResume()
}
}
private fun initializePlayer() {
if (player == null) {
mediaItems = createMediaItems()
trackSelector = DefaultTrackSelector(this)
player = ExoPlayer.Builder(this)
.setTrackSelector(trackSelector)
.build()
player?.trackSelectionParameters = trackSelectionParameters!!
player?.setAudioAttributes(AudioAttributes.DEFAULT, true)
player?.playWhenReady = startAutoPlay
binding.playerView.player = player
}
val haveStartPosition = startItemIndex != C.INDEX_UNSET
if (haveStartPosition) {
player?.seekTo(startItemIndex, startPosition)
}
player?.setMediaItems(mediaItems, !haveStartPosition)
player?.prepare()
}
private fun createMediaItems(): MutableList<MediaItem> {
val mediaItems = mutableListOf<MediaItem>()
val rawDataSource = RawResourceDataSource(this)
rawDataSource.open(DataSpec(RawResourceDataSource.buildRawResourceUri(R.raw.<ここにmp4ファイル名>)))
mediaItems.add(
MediaItem.fromUri(rawDataSource.uri!!)
)
return mediaItems
}
private fun clearStartPosition() {
startAutoPlay = true
startItemIndex = C.INDEX_UNSET
startPosition = C.TIME_UNSET
}
}