Для воспроизведения музыки и других аудиоматериалов Android предоставляет класс MediaPlayer.
Чтобы воспроизводить аудио, MediaPlayer должен знать, какой именно ресурс (файл) нужно производить. Установить нужный ресурс для воспроизведения можно тремя способами:
в метод create() объекта MediaPlayer передается id ресурса, представляющего аудиофайл
в метод create() объекта MediaPlayer передается объект Uri, представляющего аудиофайл
в метод setDataSource() объекта MediaPlayer передается полный путь к аудиофайлу
После установки ресурса вызывается метод prepare() или prepareAsync() (асинхронный вариант prepare()). Этот метод подготавливает
аудиофайл к воспроизведению, извлекая из него первые секунды. Если мы воспроизводим файл из сети, то лучше использовать prepareAsync().
Для управления воспроизведением в классе MediaPlayer определены следующие методы:
start(): запускает аудио
pause(): приостанавливает воспроизведение
stop(): полностью останавливает воспроизведение
Итак, создадим новый проект. Как и в случае с видео, аудиофайл должен находиться в папке res/raw, поэтому добавим в проект в Android Studio такую папку. Для этого нажмем на папку res правой кнопкой мыши и в появившемся меню выберем New -> Android Resource Directory:
Затем в появившемся окне в качестве типа папки укажем raw (что также будет использоваться в качестве названия папки):
И скопируем в нее какой-нибудь аудио-файл.
Для управления аудиопотоком определим в файле activity_main.xml три кнопки:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/playButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Play"
android:onClick="play"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/pauseButton"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/pauseButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Pause"
android:onClick="pause"
app:layout_constraintLeft_toRightOf="@id/playButton"
app:layout_constraintRight_toLeftOf="@id/stopButton"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/stopButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Stop"
android:onClick="stop"
app:layout_constraintLeft_toRightOf="@id/pauseButton"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
И изменим код класса MainActivity:
package com.example.mediaapp;
import androidx.appcompat.app.AppCompatActivity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
MediaPlayer mPlayer;
Button playButton, pauseButton, stopButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlayer= MediaPlayer.create(this, R.raw.music);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
stopPlay();
}
});
playButton = findViewById(R.id.playButton);
pauseButton = findViewById(R.id.pauseButton);
stopButton = findViewById(R.id.stopButton);
pauseButton.setEnabled(false);
stopButton.setEnabled(false);
}
private void stopPlay(){
mPlayer.stop();
pauseButton.setEnabled(false);
stopButton.setEnabled(false);
try {
mPlayer.prepare();
mPlayer.seekTo(0);
playButton.setEnabled(true);
}
catch (Throwable t) {
Toast.makeText(this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public void play(View view){
mPlayer.start();
playButton.setEnabled(false);
pauseButton.setEnabled(true);
stopButton.setEnabled(true);
}
public void pause(View view){
mPlayer.pause();
playButton.setEnabled(true);
pauseButton.setEnabled(false);
stopButton.setEnabled(true);
}
public void stop(View view){
stopPlay();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mPlayer.isPlaying()) {
stopPlay();
}
}
}
Обработчик каждой кнопки кроме вызова определенного метода у MediaPlayer также переключает доступность кнопок.
И если запуск и приостановка воспроизведения особых сложностей не вызывает, то при обработки полной остановки воспроизведения мы можем столкнуться с рядом трудностей. В частности, когда мы выходим из приложения - полностью закрываем его через диспетчер приложений либо нажимаем на кнопку Назад, то у нас для текущей Activity вызывается метод onDestroy, activity уничтожается, но MediaPlayer продолжает работать. Если мы вернемся к приложению, то activity будет создана заново, но с помощью кнопок мы не сможем управлять воспроизведением. Поэтому в даном случае переопределяем метод onDestroy, в котором завершаем воспроизведение.
Для корректного завершения также определен обработчик естественного завершения
воспроизведения OnCompletionListener, действие которого будет аналогично нажатию на кнопку "Стоп".
Добавим к воспроизведению индикатор громкости. Для этого в файле activity_main.xml определим SeekBar:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/playButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Play"
android:onClick="play"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/pauseButton"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/volumeControl" />
<Button
android:id="@+id/pauseButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Pause"
android:onClick="pause"
app:layout_constraintLeft_toRightOf="@id/playButton"
app:layout_constraintRight_toLeftOf="@id/stopButton"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/stopButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Stop"
android:onClick="stop"
app:layout_constraintLeft_toRightOf="@id/pauseButton"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<SeekBar
android:id="@+id/volumeControl"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layout_constraintTop_toBottomOf="@id/playButton"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
И далее изменим код класса MainActivity:
package com.example.mediaapp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
MediaPlayer mPlayer;
Button playButton, pauseButton, stopButton;
SeekBar volumeControl;
AudioManager audioManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlayer=MediaPlayer.create(this, R.raw.music);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
stopPlay();
}
});
playButton = findViewById(R.id.playButton);
pauseButton = findViewById(R.id.pauseButton);
stopButton = findViewById(R.id.stopButton);
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
int curValue = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
volumeControl = findViewById(R.id.volumeControl);
volumeControl.setMax(maxVolume);
volumeControl.setProgress(curValue);
volumeControl.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
pauseButton.setEnabled(false);
stopButton.setEnabled(false);
}
private void stopPlay(){
mPlayer.stop();
pauseButton.setEnabled(false);
stopButton.setEnabled(false);
try {
mPlayer.prepare();
mPlayer.seekTo(0);
playButton.setEnabled(true);
}
catch (Throwable t) {
Toast.makeText(this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public void play(View view){
mPlayer.start();
playButton.setEnabled(false);
pauseButton.setEnabled(true);
stopButton.setEnabled(true);
}
public void pause(View view){
mPlayer.pause();
playButton.setEnabled(true);
pauseButton.setEnabled(false);
stopButton.setEnabled(true);
}
public void stop(View view){
stopPlay();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mPlayer.isPlaying()) {
stopPlay();
}
}
}
Для управления громкостью звука применяется класс AudioManager. А в с помощью вызова audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0);
в качестве второго параметра можно передать нужное значение громкости.