【Androidアプリ開発】JetpackライブラリMedia3で動画をローカル再生する

android-iconプログラミング

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
    }
}

コメント