MediaPlayer()を使って簡単な音楽再生アプリが作れます。Audioを扱うものとしては他にはSoundPoolやAudioTrackがあります。
2024.1.1
MediaPlayer
MediaPlayerの特徴としては、呼び出してから再生まである程度時間がかかります。ゲームで言うとBGMを流しっぱなしには向きますが、爆発音を出したい時はタイミングが合わないかもしれません。
ゲームでの爆発音などは SoundPool が使えます。更に、時間遅延が無いのは AudioTrack です。それぞれ一長一短がありますので用途に合わせた使い方が必要です。
MediaPlayerでの音楽ファイルはassetsあるいはrawに置きます。
assetsとrawの違いは、
- assets:フォルダー分けができる
- たくさんファイルがあるケースではassetsが便利
- raw:ベタにただファイルを入れる配置
assetsの設定
mp3ファイルを入れるため「assets」フォルダーを作ります。appを選択した状態で
「New」->「Folder」->「assets folder」からフォルダを作成して、そこにmp3ファイルを入れます。
あるいは直接フォルダーをmainの下に作ることでもできます。
..\app\src\main\assets
手順としては
- assetsをオープンして音楽素材を取得
- MediaPlayerのインスタンスを生成して
- 音楽素材を設定
- 準備ができるまで待ち
- 再生を始める
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// MediaPlayer のインスタンス生成 val mediaPlayer : MediaPlayer(); // 音楽ファイルをmediaplayerに設定 mediaPlayer.setDataSource(afdescripter.getFileDescriptor(), afdescripter.getStartOffset(),afdescripter.getLength()); // 再生可能状態かどうかのチェック mediaPlayer.setOnPreparedListener(object : MediaPlayer.OnPreparedListener { override fun onPrepared(mp: MediaPlayer?) { // ... } }) // 再生開始 mediaPlayer.start() // 再生終了 mediaPlayer.stop() // リセット mediaPlayer.reset() // リソースの解放 mediaPlayer.release() |
音量を調整する場合、アプリでボリュームを作成することもできますが、もともとある音量調整ボタンでユーザーが好みで設定できる方が無駄がなく、ユーザーにとっても便利です。そこで setVolumeControlStream を使います。
1 |
volumeControlStream = AudioManager.STREAM_MUSIC |
これを設定しないと、ボリュームでコントロールされるのは(通知音と着信音)となります。
サンプルコード
まとめるとこうなります
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
//package com.example.kotlinmediaplayer import android.media.AudioManager import android.media.MediaPlayer import android.os.Bundle import android.util.Log import android.widget.Button import android.widget.Toast import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import java.io.IOException class MainActivity : AppCompatActivity() { private lateinit var mediaPlayer: MediaPlayer override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContentView(R.layout.activity_main) ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } // 音楽開始ボタン val buttonStart: Button = findViewById(R.id.start) // リスナーをボタンに登録 buttonStart.setOnClickListener { // 音楽再生 audioPlay() } // 音楽停止ボタン val buttonStop: Button = findViewById(R.id.stop) // リスナーをボタンに登録 buttonStop.setOnClickListener { // 音楽停止 audioStop() } } // assets から読む private fun audioSetup(): Boolean { mediaPlayer = MediaPlayer() //音楽ファイル名, あるいはパス val filePath = "music.mp3" // assetsから mp3 ファイルを読み込み try { assets.openFd(filePath).use { afdescripter -> // MediaPlayerに読み込んだ音楽ファイルを指定 mediaPlayer.setDataSource( afdescripter.fileDescriptor, afdescripter.startOffset, afdescripter.length ) // 音量調整を端末のボタンに任せる volumeControlStream = AudioManager.STREAM_MUSIC mediaPlayer.prepare() } } catch (e: IOException) { throw RuntimeException(e) } return true } private fun audioPlay() { // audio ファイルを読出し if (audioSetup()) { Toast.makeText(application, "Rread audio file", Toast.LENGTH_SHORT).show() } else { Toast.makeText(application, "Error: read audio file", Toast.LENGTH_SHORT).show() return } // 再生する mediaPlayer.start() // 終了を検知するリスナー mediaPlayer.setOnCompletionListener { _ -> Log.d("debug", "end of audio") audioStop() } } private fun audioStop() { // 再生終了 mediaPlayer.stop() // リセット mediaPlayer.reset() // リソースの解放 mediaPlayer.release() } } |
レイアウト
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/start" android:text="@string/start" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="40dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.4" /> <Button android:id="@+id/stop" android:text="@string/stop" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="40dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.6" /> </androidx.constraintlayout.widget.ConstraintLayout> |
リソース
strings.xml
1 2 3 4 5 |
<resources> <string name="app_name">KotlinMediaPlayer</string> <string name="start">start</string> <string name="stop">stop</string> </resources> |
BGMとして繰り返し再生させる場合は、release()でリソースを解放しないと、メモリーが圧迫されて止まりますので注意です。再生終了を検知させてもいいのですが、ここは簡単にインスタンスを生成する前にリリースさせます。
1 2 3 4 5 6 7 |
// 繰り返し再生する場合 if (mediaPlayer != null) { mediaPlayer.stop() mediaPlayer.reset() // リソースの解放 mediaPlayer.release() } |
rawフォルダを使う
assetsからデータを取り出しましたが、参考のためrawフォルダに置いた場合です。
この場合mp3などの拡張子はいりません。
rawフォルダをresの下に作成して
音楽素材を入れます。
あるいは直接作ってもできます。
..\app\src\main\res\raw
MainActivity.kt
1 2 3 4 |
// インタンスを生成 mediaPlayer = MediaPlayer() // rawにファイル,music.mp3がある mediaPlayer = MediaPlayer.create(this, R.raw.music) |
サンプル動画
実際には、メールやLineなどしながら音楽を聴くという状況が多いと思います。その場合はMediaPlayerはバックグラウンドで再生した方がいいのでServiceとNotificationを使います。
- 関連ページ
- 簡単なMediaPlayerで音楽を再生
- WAV音声ファイルをAudioTrackで再生
- SoundPoolで効果音を鳴らす
Reference:
MediaPlayer | Android Developers