添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
7
10

More than 3 years have passed since last update.

【Kotlin研修10日目】メディアファイルの再生、MediaPlayerのライフサイクル

Posted at
メディアファイルの再生

メディアファイル (= 音声 動画 ファイル)は、 MediaPlayer クラスを用いて再生する。
メディアファイル を再生する手順は、以下の通り。

MediaPlayerオブジェクトの生成

MediaPlayer() での MediaPlayer オブジェクトの生成時、 MediaPlayer オブジェクトは Idle 状態から始まる。

MediaPlayer

メディアファイル を制御する プレーヤー を定義するクラス。

MediaPlayerのライフサイクル // MediaPlayerプロパティ // -> オブジェクト解放時はnullにするため、Nullable型で宣言 private var _player : MediaPlayer ? = null // アクティビティ初期化時の処理 override fun onCreate ( savedInstanceState : Bundle ?) { // MediaPlayerオブジェクトの生成 _player = MediaPlayer ()

生成した MediaPlayer オブジェクトに制御対象の リソースファイル を定義することで、 Initialized 状態に遷移させる。

なお、 リソースファイル res フォルダ内に Resource Type: raw Android Resource Directory を作成し、作成したディレクトリ内に配置しておく。

MediaPlayer.setDataSource(
    context: Context,
    uri: Uri
): Unit
// パラメータ
// context: MediaPlayerを利用するアクティビティオブジェクト(コンテキスト)
// uri: メディアファイルのURI
String型→Uri型の変換
Uri.parse(uriString: String!): Uri!
// パラメータ
// uriString: Uri型に変換するUri文字列
サンプルコード
MainActivity.kt
class MainActivity : AppCompatActivity() {
    // MediaPlayerプロパティ
    private var _player: MediaPlayer? = null
    // アクティビティ初期化時の処理
    override fun onCreate(savedInstanceState: Bundle?) {
        // メディアファイルのURI文字列
        val mediaFileUriStr = "android.resource://${packageName}/${R.raw.<メディアファイル名>}"
        // String型 → URI型 への変換
        val mediaFileUri = Uri.parse(mediaFileUriStr)
        // MediaPlayerがnullでない場合の処理
        _player?.let {
            // メディアファイルの指定
            it.setDataSource(this@MainActivity, mediaFileUri)
MediaPlayerオブジェクトへのリスナ定義

メディアファイル準備完了(イベント)を検知するMediaPlayer.OnPreparedListenerインタフェースを実装したリスナクラスと、
メディアファイル再生完了(イベント)を検知するMediaPlayer.OnCompletionListenerインタフェースを実装したリスナクラスを定義する。

サンプルコード
MainActivity.kt
class MainActivity : AppCompatActivity() {
    // MediaPlayerプロパティ
    private var _player: MediaPlayer? = null
    // アクティビティ初期化時の処理
    override fun onCreate(savedInstanceState: Bundle?) {
        // MediaPlayerがnullでない場合の処理
        _player?.let {
            // メディアファイルの準備完了時のリスナ定義
            it.setOnPreparedListener(PlayerPreparedListener())
            // メディアファイルの再生完了時のリスナ定義
            it.setOnCompletionListener(PlayerCompletionListener())
    // "メディアファイルの準備完了"イベントを検知するリスナクラス
    private inner class PlayerPreparedListener: MediaPlayer.OnPreparedListener {
        // "メディアファイルの準備"完了時の処理
        override fun onPrepared(mp: MediaPlayer?) {
    // "メディアファイルの再生完了"イベントを検知するリスナクラス
    private inner class PlayerCompletionListener: MediaPlayer.OnCompletionListener {
        // "メディアファイルの再生"完了時の処理
        override fun onCompletion(mp: MediaPlayer?) {

インターネットのストリーミング再生は一般的に処理に負荷がかかるため、
同期でメディアの再生準備を行うprepare()メソッドではなく、非同期で再生準備を行うprepareAsync()メソッドを用いる。

MediaPlayer.prepareAsync()
サンプルコード
MainActivity.kt
class MainActivity : AppCompatActivity() {
    // MediaPlayerプロパティ
    private var _player: MediaPlayer? = null
    // アクティビティ初期化時の処理
    override fun onCreate(savedInstanceState: Bundle?) {
        // MediaPlayerがnullでない場合の処理
        _player?.let {
            // 非同期でのMediaPlayerオブジェクトの準備
            it.prepareAsync()
MediaPlayerオブジェクトの解放

MediaPlayerシステムリソースを消費するため、アクティビティの終了時(=onDestroy())にMediaPlayerオブジェクトを解放する必要がある。

また、アクティビティクラスMediaPlayerをプロパティとして宣言している場合、MediaPlayerオブジェクトを確実に解放すると同時にプロパティの値をnullにしておくことが推奨される。

MediaPlayer.release()
サンプルコード
MainActivity.kt
class MainActivity : AppCompatActivity() {
    // MediaPlayerプロパティ
    // -> オブジェクト解放時はnullにするため、Nullable型で宣言
    private var _player: MediaPlayer? = null
    // アクティビティ終了時の処理
    override fun onDestroy() {
        // MediaPlayerがnullでない場合の処理
        // -> let関数ブロック内のitは非Nullable型であるため、
        //    let関数内では_playerの値をnullにできない
        _player?.let {
            // MediaPlayerが再生中であれば、安全のために停止
            if (it.isPlaying) {
                // MediaPlayerの停止
                it.stop()
            // MediaPlayerオブジェクトの解放
            it.release()
        // MediaPlayerをnullに変更
        _player = null
        // アクティビティの終了
        super.onDestroy()

メディアファイルの制御を行うMediaPlayerクラスのメソッドを用いてプレーヤーを操作する。

ただし、メディアファイルの停止を行うstop()メソッドを用いた場合、
再度再生する場合はprepare()メソッドを用いて再生準備を行う必要がある。
上図を参照

メディアファイルの再生・一時停止・停止 メディアファイルの末尾に進む(再生を完了させる)

メディアファイルの再生を完了させるには、MediaPlayerクラスの現在セットされているメディアファイルの再生時間を保持するdurationプロパティを用いてシーク操作を行う。

なお、メディアファイルの一時停止(=Paused状態)中に終了位置までシーク操作を行った場合、
MediaPlayerは依然として再生完了(=PlaybackCompleted状態)直前のPaused状態であるため、
start()メソッドを用いてPlaybackCompleted状態に遷移させる必要がある。

サンプルコード
kotlin.MainActivity.kt
// MediaPlayerがnullでない場合の処理
MediaPlayer?.let {
    // 再生中のメディアファイルの長さ
    val duration = it.duration
    // 再生位置を末尾に変更
    it.seekTo(duration)
    // MediaPlayerが再生中でない場合の処理
    if (!it.isPlaying) {
        // MediaPlayerの再生
        it.start()

現在セットされているメディアファイルループさせるには、MediaPlayerクラスのisLoopingプロパティを操作する。

ループ機能の実装にあたって、一般的にはトグルスイッチが用いられる。

トグルスイッチの実装

トグルスイッチBoolean型の値を保持するボタンであり、チェックボックスラジオボタンと同様、CompoundButtonクラスを継承している。

CompoundButtonクラス

Boolean型の値を保持するボタンを定義するクラス。

サンプルコード
MainActivity.kt
class MainActivity : AppCompatActivity() {
    // MediaPlayerプロパティ
    // -> オブジェクト解放時はnullにするため、Nullable型で宣言
    private var _player: MediaPlayer? = null
    // アクティビティ初期化時の処理
    override fun onCreate(savedInstanceState: Bundle?) {
        // MediaPlayerオブジェクトの生成
        _player = MediaPlayer()
        // トグルスイッチ
        val loopSwitch = findViewById<SwitchMaterial>(R.id.swLoop)
        // トグルスイッチをリスナとしてセット
        loopSwitch.setOnCheckedChangeListener(LoopSwitchChangedListener())
    // ループスイッチの"状態遷移"イベントを検知するリスナクラス
    private inner class LoopSwitchChangedListener: CompoundButton.OnCheckedChangeListener {
        // "状態遷移"イベント検知時の処理
        override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
            // ループ機能の変更
            _player?.isLooping = isChecked
7
10
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
Sign up Login
7
10