delayed audio in android
i'm trying to play audio when a button is clicked but there's some delay between when i press the button and when the audio is actually played. I get this error: AudioFlinger(17396): write blocked for 162 msecs, 3 delayed writes, thread 0x15440
This is what i got so far:
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 class
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) {
medi开发者_开发知识库aPlayer = 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);
}
}
}
Any clues?
Thanks in advance.
EDITS: So i added a singleton and it helped but there's still delay. This is how it looks like now:
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;
}
});
Any ideas? What i'm trying to do is like a drumset, that's why the buttons must respond correctly.
I/O on Android is slow. The audio subsystem is being forced to wait for it's data, and is kind enough to warn about it.
Rather than giving MediaPlayer a raw FileDescriptor (which will have no buffering applied) try using a file:// URI. With any luck the system content provider for file: will buffer it up for you the moment it's opened.
I don't really know Android in depth, but from looking at this code what you could try is to use your AudioPlayer
as a singleton and reuse your MediaPlayer
instance?
精彩评论