Ну вообще-то работа со звуком — это слишком громкое название для этой статьи. На самом деле, во время написания этой вот игры у меня возникла необходимость проигрывать фоновые мелодии и звуки нажатия на экран. Ну и полез я в справку по Android SDK. Ребята из гугла предлагают для таких целей использовать класс SoundPool. Однако у меня с ним почему-то не заладилось. То ли я справку читал не внимательно, то ли еще что, не знаю… И я решил накидать пару своих собственных небольших классов для решения этой не столь уж эпохальной проблемы. Вот собственно об этих классах мы сейчас и поговорим.
Начнем с того, что опишем небольшой класс mSoundTrack, который будет отвечать за проигрывание одного звука. На самом деле — это просто обертка для класса MediaPlayer. И вот его код:
package ru.davidmd.myengine;
import android.content.Context;
import android.media.MediaPlayer;
public class mSoundTrack {
private MediaPlayer track;
private boolean playable;
private String name;
/**
* Конструктор
*
* @param cont
* - контекст
* @param resid
* - идентификатор ресурса
* @param name
* - имя трека
* @param looped
* - зацикленность проигрывания
*/
public mSoundTrack(Context cont, int resid, String name, boolean looped) {
this.playable = true;
this.track = MediaPlayer.create(cont, resid);
this.track.setLooping(looped);
this.name = name;
}
/**
* запускает трек если в настройках mSettings есть звук
*/
public void start() {
if (mSettings.isSound()) {
if (!track.isPlaying())
track.start();
} else
this.stop();
}
/**
* перезапускает звук независимо от того играется он в данный момент или нет
*/
public void forceStart() {
if (mSettings.isSound()) {
if (track.isPlaying()) {
track.pause();
track.seekTo(0);
track.start();
} else {
track.start();
}
}
}
/**
* приостанавливает проигрывание звука! ВНИМАНИЕ!!! Не высвобождает память,
* не отсоединяется от потока... просто приостанавливает!
*/
public void stop() {
if (track.isPlaying())
track.pause();
}
/**
* перематывает трек на начало
*/
public void rewind() {
this.stop();
track.seekTo(0);
this.start();
}
/**
* @return возвращает параметр playable
*/
public boolean isPlayable() {
return playable;
}
/**
* @param playable
* - истина, если трек должен играться при проигрывании ложь в
* противном случае
*/
public void setPlayable(boolean playable) {
this.playable = playable;
}
public String getName() {
return name;
}
}
Теперь посмотрим попристальнее, что тут к чему. Имеются целых три переменные, это track — экземпляр класса MediaPlayer, name — строка в которой мы храним имя трека и логическая переменная playable — которая отвечает за то можно ли воспроизводить данный конкретный звук или нет (для чего нам последняя будет понятно чуть позже).
Соответственно имеется конструктор с целой кучей параметров: Context cont, int resid, String name, boolean looped. По порядку: Context cont — контекст из которого мы получаем доступ к ресурсам программы, int resid — идентификатор ресурса с изображением (надеюсь этой теме я тоже посвящу как-нить отдельную статью) — две эти переменные отвечают за загрузку данных из ресурсов мы их уже использовали в классе mSimpleSprite. Дальше все гораздо проще — сначала строка с именем звука, а затем, булева переменная looped — которая отвечает за то, будет ли зациклено воспроизведение нашего трека. Ну а сам конструктор думаю в комментариях не нуждается.
Идем дальше какие методы у нас здесь имеются? Давайте по порядку: start() — метод который запускает воспроизведение звука. Если звук был приостановлен, тогда воспроизведение продолжается с места где звук остановили. Метод forceStart() отличается от предыдущего тем, что если звук в данный момент воспроизводится, то происходит перемотка на самое начало трека и звук воспроизводится с самого начала. Оба эти метода проверяют перед запуском включен ли звук в классе глобальных настроек приложения mSettings.
Следующий метод stop() — не знаю почему я назвал его «стоп», ведь на самом деле он просто приостанавливает воспроизведение звука. На самом деле думаю стоило так и назвать его pause 🙂 Но видно писал все это я глубокой ночью, так что претензии не принимаются :). Метод rewind() тоже не содержит каких-то откровений и просто перематывает звук на начало. Два метода isPlayable() и setPlayable(boolean playable) соответственно проверяют и устанавливают для трека статус playable. Ну а метод getName() — просто возвращает имя трека. Вот и все что касается нашего трека. Итак у нашего проигрывателя есть треки, и мы легко можем их проиграть, приостановить или перемотать на начало. Казалось бы, для наших целей большего и не надо! Но нет, на самом деле в игре (а вы ведь не забыли что это все еще часть нашего игрового движка?) гораздо удобнее обладать каким-то общим средством для запуска и проигрывания звуков.
Таким средством станет наш следующий класс: mPlayer. Начну по привычке с его кода:
package ru.davidmd.myengine;
import java.util.ArrayList;
import android.content.Context;
public class mPlayer {
private static ArrayList<mSoundTrack> tracks = new ArrayList<mSoundTrack>();
/**
* Добавляет трек из ресурсов
*
* @param c
* - контекст
* @param resid
* - идентификатор ресурса
* @param name
* - имя для нового трека
* @param looped
* - зацикленность трека
*/
public static void addTrack(Context c, int resid, String name,
boolean looped) {
mSoundTrack track = new mSoundTrack(c, resid, name, looped);
tracks.add(track);
}
/**
* Возвращает трек из списка по его имени
*
* @param name
* - имя трека
* @return возвращает трек с именем name
*/
public static mSoundTrack getTrackByName(String name) {
mSoundTrack t = null;
for (mSoundTrack a : tracks) {
if (a.getName() == name) {
t = a;
break;
}
}
return t;
}
/**
* Метод запускает все треки, свойство playable которых имеет значение
* истина
*/
public static void playAll() {
for (mSoundTrack a : tracks) {
if (a.isPlayable()) {
a.start();
}
}
}
/**
* Метод останавливает все треки
*
*/
public static void stopAll() {
for (mSoundTrack a : tracks) {
a.stop();
}
}
}
Тоже на самом деле ничего сложного! В классе имеется статический список треков и метод для добавления трека в список — addTrack(). Помимо этого присутствует метод возвращающий трек по его имени — getTrackByName(String name), если такого имени не оказалось то возвращается null. Ну и собственно то ради чего все это затевалось: метод запуска всех треков (при запуске проверяется имеет ли трек статус проигрываемого) и метод остановки всех треков. Для написания не сложной игры этого простенького менеджера звуков оказалось вполне достаточно!
На сегодня все! жду комментов или примеров работы с SoundPool (Наверняка там все несколько легче).
Читать дальше тут.

«запускает трек если в настройках mSettings есть звук»
А где определение mSettings?
Честно говоря не помню где именно но где-то на страницах посвященных движку я об этом писал 🙂 В любом случае вы можете скачать полный код движка и посмотреть что там за такие mSettings 🙂
Здравствуйте. Хотел добавить в Пятнашки музыку. для этого добавил в папку «w» мелодию с именем «track». В классе MainScreen добавил к подключаемым классам mPlayer и в методе onStart() добавил mPlayer.getTrackByName(«track»).setPlayable(true);
mPlayer.getTrackByName(«track»).forceStart();
mPlayer.playAll();
отладчик ошибок никаких не находит, но в эмуляторе игра не работает. Не подскажите в чем причина?
Разобрался что к чему =)
Где можно посмотреть реализацию метода isSound()?
Никогда не делайте так))