メディアファイルの再生
メディアファイル
(=音声
・動画
ファイル)は、MediaPlayer
クラスを用いて再生する。
メディアファイル
を再生する手順は、以下の通り。
MediaPlayer
オブジェクトの生成メディアファイル
のURI
を指定MediaPlayer
オブジェクトのリスナ定義非同期
による再生準備MediaPlayer
オブジェクトの解放
MediaPlayerオブジェクトの生成
MediaPlayer()
でのMediaPlayer
オブジェクトの生成時、MediaPlayer
オブジェクトはIdle
状態から始まる。
MediaPlayer
メディアファイル
を制御するプレーヤー
を定義するクラス。
MediaPlayerのライフサイクル
ライフサイクル | メソッド | 呼び出しタイミング |
---|---|---|
Idle |
MediaPlayer() または reset()
|
オブジェクト の生成 |
Initialized |
setDataSource() |
メディアファイル の定義 |
Preparing |
prepareAsync() |
非同期 でのメディアファイル の準備開始 |
Prepared |
OnPreparedListener.onPrepared() または prepare()
|
メディアファイル の準備完了 |
Started |
start() |
メディアファイル の再生
|
Paused |
pause() |
メディアファイル の一時停止
|
PlaybackCompleted |
OnCompletionListener.onCompletion() |
メディアファイル の再生完了
|
Stopped |
stop() |
メディアファイル の停止
|
End |
release() |
オブジェクト の解放 |
Error |
OnErrorListener.onError() |
エラー の発生 |
サンプルコード
class MainActivity : AppCompatActivity() {
// MediaPlayerプロパティ
// -> オブジェクト解放時はnullにするため、Nullable型で宣言
private var _player: MediaPlayer? = null
// アクティビティ初期化時の処理
override fun onCreate(savedInstanceState: Bundle?) {
// MediaPlayerオブジェクトの生成
_player = MediaPlayer()
...
}
...
}
再生するメディアファイルのURI指定
生成した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文字列
サンプルコード
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
インタフェースを実装したリスナクラスを定義する。
サンプルコード
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()
サンプルコード
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()
サンプルコード
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()
メソッドを用いて再生準備
を行う必要がある。
※上図を参照
メディアファイルの再生・一時停止・停止
メソッド | 内容 |
---|---|
start() |
再生 |
pause() |
一時停止 |
stop() |
停止 |
再生位置(シーク)の操作
メディアファイル
の再生位置
(=シーク
)を変更する場合は、MediaPlayer
のseekTo()
メソッドを用いる。
定義
MediaPlayer.seekTo(msec: Int): Unit
// パラメータ
// msec: 開始位置からのオフセット[ms]
メディアファイルの先頭に戻る
サンプルコード
MediaPlayer.seekTo(0)
メディアファイルの末尾に進む(再生を完了させる)
メディアファイル
の再生を完了させるには、MediaPlayer
クラスの現在セットされているメディアファイル
の再生時間を保持するduration
プロパティを用いてシーク操作
を行う。
なお、メディアファイル
の一時停止(=Paused
状態)中に終了位置までシーク操作
を行った場合、
MediaPlayer
は依然として再生完了
(=PlaybackCompleted
状態)直前のPaused
状態であるため、
start()
メソッドを用いてPlaybackCompleted
状態に遷移させる必要がある。
サンプルコード
// MediaPlayerがnullでない場合の処理
MediaPlayer?.let {
// 再生中のメディアファイルの長さ
val duration = it.duration
// 再生位置を末尾に変更
it.seekTo(duration)
// MediaPlayerが再生中でない場合の処理
if (!it.isPlaying) {
// MediaPlayerの再生
it.start()
}
}
ループ機能
現在セットされているメディアファイル
をループ
させるには、MediaPlayer
クラスのisLooping
プロパティを操作する。
ループ機能
の実装にあたって、一般的にはトグルスイッチ
が用いられる。
トグルスイッチの実装
トグルスイッチ
はBoolean
型の値を保持するボタンであり、チェックボックス
やラジオボタン
と同様、CompoundButton
クラスを継承している。
CompoundButtonクラス
Boolean
型の値を保持するボタン
を定義するクラス。
サンプルコード
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
}
}
}