Я пытаюсь воспроизвести звук при нажатии кнопки, но есть некоторая задержка между тем, когда я нажимаю кнопку и когда звук воспроизводится. Я получаю эту ошибку: AudioFlinger(17396): write blocked for 162 msecs, 3 delayed writes, thread 0x15440
Это то, что я получил до сих пор:
ImageButton i = (ImageButton)findViewById(R.id.button);
i.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
s = new AudioPlayer(getApplicationContext());
s.playSound(R.raw.conga1);
}
return true;
}
});
Класс AudioPlayer
public class AudioPlayer {
private MediaPlayer mediaPlayer;
private final OnCompletionListener mediaPlayerListener = new MediaPlayerListener();
private Context context = null;
public AudioPlayer(Context context)
{
this.context = context;
init();
}
private void init() {
if (mediaPlayer == null) {
AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
int streamVolume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(mediaPlayerListener);
mediaPlayer.setVolume(streamVolume, streamVolume);
}
}
private void setSound(int id) {
if (mediaPlayer!=null) {
mediaPlayer.reset();
AssetFileDescriptor file = context.getResources().openRawResourceFd(id);
try {
mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());
file.close();
mediaPlayer.prepare();
} catch (IOException e) {
mediaPlayer = null;
}
}
}
public void playSound(int id) {
if (mediaPlayer!=null) {
setSound(id);
mediaPlayer.start();
}
}
private static class MediaPlayerListener implements OnCompletionListener {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(0);
}
}
}
Любые подсказки?
Спасибо заранее.
редактирует: Поэтому я добавил синглтон, и он помог, но все еще задерживается. Вот как это выглядит сейчас:
AudioPlayer:
public static synchronized AudioPlayer getSingletonObject(Context context, Uri pathToFile) {
if (audioPlayer == null) {
audioPlayer = new AudioPlayer(context, pathToFile);
}
return audioPlayer;
}
public void setSound(String pathToFile) {
if (mediaPlayer!=null) {
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(pathToFile);
mediaPlayer.prepareAsync();
} //catch....
}
}
public void playSound(String path) {
if (mediaPlayer!=null) {
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(path);
mediaPlayer.prepareAsync();
mediaPlayer.start();
} //catch...
}
}
Main:
final String path = "sdcard/myappsounds/snaredrum2.wav";
final AudioPlayer s = AudioPlayer.getSingletonObject(getApplicationContext(), Uri.parse(path));
s.setSound(path);
ImageButton i = (ImageButton)findViewById(R.id.button);
i.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
s.playSound(path);
}
return true;
}
});
Любые идеи? То, что я пытаюсь сделать, это как барабан, поэтому кнопки должны отвечать правильно.
I/O на Android работает медленно. Звуковая подсистема вынуждена ждать его данных и достаточно любезна, чтобы предупредить об этом.
Вместо того, чтобы предоставить MediaPlayer необработанный FileDescriptor (который не будет применять буферизацию), попробуйте использовать файл://URI. При любой удаче поставщик системного контента для файла: он будет буферизовать его для вас в момент его открытия.
Я действительно не знаю Android в глубину, но, глядя на этот код, вы могли бы попробовать использовать AudioPlayer
в качестве одноэлементного и повторно использовать экземпляр MediaPlayer
?
mediaPlayer.setDataSource(pathToFile); mediaPlayer.prepare();
гдеpathToFile
- это строка. Есть какие-нибудь подсказки?