Не все приложения и игры требуют звуковых эффектов или фоновой музыки. Но некоторые – могут стать гораздо приятнее или интереснее. А если речь о медиаплеере или симуляторе гитары, то без звукового сопровождения и вовсе не обойтись.
В этой статье мы разберём, как добавить звуки и музыку в Android-приложение.
Содержание:
Звуки
Прежде всего, чтобы запустить звук, нужно где-то взять этот самый звук. Скачаем любую mp3-шку и положим её в папку /название_проекта/app/src/main/res/raw.
Не всегда эта папка есть. У меня обычно её в проекте нету. Поэтому в папке res я самостоятельно создаю папку raw.
Не забываем о правилах именования файлов ресурсов в проектах IntelliJ IDEA (или Android Studio) – английский язык, маленькие буквы, цифры, из спецсимволов разрешены нижние подчёркивания.
После того, как крик петуха успешно приземлился в нужной папке проекта, идём в код. Для воспроизведения коротких звуковых эффектов в Android обычно используется класс SoundPool. Напишем класс, который будет ответственен за музыку. Впоследствии мы сможем его использовать в любой Activity без необходимости копировать однотипный код (чтобы код был чище).
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 |
/** * класс для управления проигрыванием звуков * * @version 1.0, 21.07.2024 */ public class SoundPlayer { private SoundPool soundPool; private int soundIdCooCaReCoo; private final int MAX_LEFT_VOLUME = 1; private final int MAX_RIGHT_VOLUME = 1; private final int NO_LOOP = 0; private final int NORMAL_PLAY_SPEED = 1; private final int DEFAULT_SOUND_PRIORITY = 0; public SoundPlayer(Context context) { AudioAttributes audioAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .build(); soundPool = new SoundPool.Builder() .setMaxStreams(1) .setAudioAttributes(audioAttributes) .build(); soundIdCooCaReCoo = soundPool.load(context, R.raw.coo_ca_re_coo, DEFAULT_SOUND_PRIORITY); } public void playCooCaReCooSound() { soundPool.play(soundIdCooCaReCoo, MAX_LEFT_VOLUME, MAX_RIGHT_VOLUME, DEFAULT_SOUND_PRIORITY, NO_LOOP, NORMAL_PLAY_SPEED); } } |
Отлично! А теперь создадим простую Activity, добавим в неё кнопку и опробуем класс SoundPlayer на практике.
Код файла activity_main.xml, разметка интерфейса, где расположена кнопка по центру экрана внутри ConstraintLayout:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/mainLayout" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageButton android:id="@+id/soundButton" android:layout_width="100dp" android:layout_height="100dp" android:background="@android:color/transparent" android:scaleType="fitXY" android:src="@drawable/sound" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout> |
Код файла 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 |
public class MainActivity extends AppCompatActivity { private SoundPlayer soundPlayer; private ImageButton soundButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); defineComponents(); defineFunctionality(); soundPlayer = new SoundPlayer(this); } /** * определение функциональности */ private void defineFunctionality() { soundButton.setOnClickListener(view -> playSound()); } /** * воспроизвести звук */ private void playSound() { soundPlayer.playCooCaReCooSound(); } /** * получение ссылок на графические компоненты */ private void defineComponents() { soundButton = findViewById(R.id.soundButton); } } |
При тестировании работы приложения на физическом устройстве Android звук крика петуха действительно проигрывался по нажатию на кнопку. Юху. При этом, если нажимать повторно, пока предыдущий крик не завершился, он будет прерываться и начинаться новый.
Кстати, в такой класс SoundPlayer, конечно, может быть помещено больше одного звука. Это зависит от того, сколько в вашем приложении их требуется. Для каждого звука тогда нужно создать свою переменную с soundId, а также свой публичный метод для проигрывания звука.
Музыка
Для воспроизведения фоновой музыки, которая обычно длится дольше, чем звуковые эффекты, в Android используется класс MediaPlayer.
И снова загружаем нужный файл в ту же самую папку res/raw. В этот раз это музыкальная композиция группы Queen. Не забываем про правила именования файлов ресурсов.
Напишем класс MusicPlayer для управления воспроизведением музыки в нашем приложении.
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 |
/** * класс для управления проигрыванием музыки * * @version 1.0, 21.07.2024 */ public class MusicPlayer { private MediaPlayer mediaPlayer; private boolean isTurnedOn; public MusicPlayer(Context context) { mediaPlayer = MediaPlayer.create(context, R.raw.queen_we_are_the_champions); mediaPlayer.setLooping(true); } public void turnOn() { mediaPlayer.start(); isTurnedOn = true; } public void turnOff() { mediaPlayer.pause(); isTurnedOn = false; } public void continueMusic() { if (isTurnedOn) { mediaPlayer.start(); } } public void pauseMusic() { if (isTurnedOn) { mediaPlayer.pause(); } } } |
Вот такой он получился. С помощью метода mediaPlayer.setLooping(true) поставили, чтобы музыка не заканчивалась, а всё время крутилась. Используем класс MusicPlayer в MainActivity:
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 |
public class MainActivity extends AppCompatActivity { private MusicPlayer musicPlayer; private ImageButton musicButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); defineComponents(); defineFunctionality(); musicPlayer = new MusicPlayer(this); } /** * определение функциональности */ private void defineFunctionality() { musicButton.setOnClickListener(view -> musicPlayer.turnOn()); } /** * получение ссылок на графические компоненты */ private void defineComponents() { musicButton = findViewById(R.id.musicButton); } } |
Отлично, пора протестировать то, что получилось. При открытии приложения тихо, но после нажатия на кнопку начинает играть музыка. Кажется, именно этого мы и добивались.
Остановка музыки при выходе из приложения
Однако есть нюанс. Если вы попробуете выйти из приложения, музыка никуда не денется. А это нехорошо. Нужно что-то с этим поделать.
На самом деле, всё просто. Необходимо лишь дописать реакцию при срабатывании событий onPause() и onResume() у Activity. Вот как будет выглядеть изменённый код MainActivity:
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 |
public class MainActivity extends AppCompatActivity { private MusicPlayer musicPlayer; private ImageButton musicButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); defineComponents(); defineFunctionality(); musicPlayer = new MusicPlayer(this); } @Override protected void onPause() { musicPlayer.pauseMusic(); super.onPause(); } @Override protected void onResume() { super.onResume(); musicPlayer.continueMusic(); } /** * определение функциональности */ private void defineFunctionality() { musicButton.setOnClickListener(view -> musicPlayer.turnOn()); } /** * получение ссылок на графические компоненты */ private void defineComponents() { musicButton = findViewById(R.id.musicButton); } } |
При сворачивании приложения музыка приостанавливается. При раскрытии – снова продолжается.
Готово! Как видите, работа со звуками и музыкой в Android не таит в себе никаких сложностей. Уже есть классы, которые позволяют при минимальной настройке получить результат. SoundPool вообще, хоть скорость звука изменяй, хоть громкость для правого и левого наушника, хоть приоритет.