Для воспроизведения музыки и других аудиоматериалов 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);
в качестве второго параметра можно передать нужное значение громкости.