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 |
// assetsのファイルをオープン AssetFileDescriptor afdescripter = getAssets().openFd(filePath); // MediaPlayer のインスタンス生成 MediaPlayer mediaPlayer = new MediaPlayer(); // 音楽ファイルをmediaplayerに設定 mediaPlayer.setDataSource(afdescripter.getFileDescriptor(), afdescripter.getStartOffset(),afdescripter.getLength()); // 再生準備、再生可能状態になるまでブロック mediaPlayer.prepare(); // 再生開始 mediaPlayer.start(); // 再生終了 mediaPlayer.stop(); // リセット mediaPlayer.reset(); // リソースの解放 mediaPlayer.release(); |
音量を調整する場合、アプリでボリュームを作成することもできますが、もともとある音量調整ボタンでユーザーが好みで設定できる方が無駄がなく、ユーザーにとっても便利です。そこで setVolumeControlStream を使います。
1 |
setVolumeControlStream(AudioManager.STREAM_MUSIC); |
これを設定しないと、ボリュームでコントロールされるのは(通知音と着信音)となります。
サンプルコード
まとめるとこうなります
MainActivity.java
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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
package com.example.testmediaplayer; import android.content.res.AssetFileDescriptor; 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.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import java.io.IOException; public class MainActivity extends AppCompatActivity { private MediaPlayer mediaPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); // 音楽開始ボタン Button buttonStart = findViewById(R.id.start); // リスナーをボタンに登録 buttonStart.setOnClickListener( v -> { // 音楽再生 audioPlay(); }); // 音楽停止ボタン Button buttonStop = findViewById(R.id.stop); // リスナーをボタンに登録 buttonStop.setOnClickListener( v -> { if (mediaPlayer != null) { // 音楽停止 audioStop(); } }); } // assets から読む private boolean audioSetup(){ // インタンスを生成 mediaPlayer = new MediaPlayer(); //音楽ファイル名, あるいはパス String filePath = "music.mp3"; // assetsから mp3 ファイルを読み込み try(AssetFileDescriptor afdescripter = getAssets().openFd(filePath)) { // MediaPlayerに読み込んだ音楽ファイルを指定 mediaPlayer.setDataSource( afdescripter.getFileDescriptor(), afdescripter.getStartOffset(), afdescripter.getLength()); // 音量調整を端末のボタンに任せる setVolumeControlStream(AudioManager.STREAM_MUSIC); mediaPlayer.prepare(); } catch (IOException e) { throw new RuntimeException(e); } return true; } /* // rawから読む private boolean audioSetup(){ boolean fileCheck = false; // rawにファイルがある場合 mediaPlayer = MediaPlayer.create(this, R.raw.music); // 音量調整を端末のボタンに任せる setVolumeControlStream(AudioManager.STREAM_MUSIC); fileCheck = true; return fileCheck; } */ private void audioPlay() { if (mediaPlayer == null) { // audio ファイルを読出し if (audioSetup()){ Toast.makeText(getApplication(), "Rread audio file", Toast.LENGTH_SHORT).show(); } else{ Toast.makeText(getApplication(), "Error: read audio file", Toast.LENGTH_SHORT).show(); return; } } else{ // 繰り返し再生する場合 mediaPlayer.stop(); mediaPlayer.reset(); // リソースの解放 mediaPlayer.release(); } // 再生する mediaPlayer.start(); // 終了を検知するリスナー mediaPlayer.setOnCompletionListener( mp -> { Log.d("debug","end of audio"); audioStop(); }); } private void audioStop() { // 再生終了 mediaPlayer.stop(); // リセット mediaPlayer.reset(); // リソースの解放 mediaPlayer.release(); mediaPlayer = null; } } |
リソース、レイアウトファイルは以下にあります
レイアウト
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">TestMediaPlayer</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
前のコードの audioSetup() の部分のみ変更します。この場合 try catch や prepare() もいりません。
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
... private boolean audioSetup(){ boolean fileCheck = false; // rawにファイルがある場合 mediaPlayer = MediaPlayer.create(this, R.raw.music); // 音量調整を端末のボタンに任せる setVolumeControlStream(AudioManager.STREAM_MUSIC); fileCheck = true; return fileCheck; } ... |
サンプル動画
実際には、メールやLineなどしながら音楽を聴くという状況が多いと思います。その場合はMediaPlayerはバックグラウンドで再生した方がいいのでServiceとNotificationを使います。
- 関連ページ
- 簡単なMediaPlayerで音楽を再生
- WAV音声ファイルをAudioTrackで再生
- SoundPoolで効果音を鳴らす
Reference:
MediaPlayer | Android Developers