In Android 4.x my audio looping app has 0.2 to 0.5 second gaps in the sound loops.
I'm using MediaPlayer as my sounds can be quite large (2-3mb each in some cases) and it can run multiple instances at the same time.
I have researched this quite a bit and I see there is a bug for Android 4.x... however, I have tried many work arounds and I can't seem to get any of them working.
Here's a sample of the code I'm using:
public class SoundPlayer implements OnCompletionListener {
private MediaPlayer mp = null;
public void initPlayer() {
if(mp == null) {
mp = new MediaPlayer();
}
}
public void prepare(Context context, int resource) {
initPlayer();
try{
mp.reset();
Uri uri = Uri.parse("android.resource://com.myapp.app/"+resource);
mp.setDataSource(context,uri);
mp.prepare();
isPrepared = true;
mp.setOnCompletionListener(this);
} catch(Exception e) {
e.printStackTrace();
}
}
.......... etc (Uses typical MediaPlayer methods such as stop(), start(), setLooping(true)
}
I'm not using anything special, so I'm just wondering if anyone knows of a work around for the looping bug on Android.
Okay old Post, but this solution works. This is kind of hack. It'll help somebody if somebody came to this answer.
I am just using three media players. mp1
, mp2
, mp3
. mp1
gets play, and I set mp2
to its setNextMediaPlayer
. when mp1
ends, I set mp3
to mp2's
setNextMediaPlayer
. when mp2
ends, I set mp1
to mp3's
setNextMediaPlayer
. Following is the complete code which play pause, stop, set vol. Just create an object BZMediaPlayer
, start it by providing uri
, or resource id.
import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.util.Log;
public class BZMediaPlayer {
private Context context;
private Uri uri;
private int resourceId;
// which file is getting played
public static final int URI_PLAYING = 1;
public static final int RESOURCE_PLAYING = 2;
private int filePlaying;
// states of the media player
public static final int STATE_PLAYING = 1;
public static final int STATE_PAUSED = 2;
public static final int STATE_STOP = 3;
// current state
private int state = STATE_STOP;
// current mediaPlayer which is playing
private int mediaPlayerIndex = -1;
// 3 media players
private MediaPlayer mp[] = new MediaPlayer[3];
// current volume
private float vol;
public BZMediaPlayer(Context context) {
this.context = context;
}
/**
* plays the provided uri
* @param uri
*/
public void play(Uri uri) {
this.uri = uri;
// current playing file
filePlaying = URI_PLAYING;
// stop any playing session
stop();
// initialize and set listener to three mediaplayers
for (int i = 0; i < mp.length; i++) {
mp[i] = MediaPlayer.create(context, uri);
mp[i].setOnCompletionListener(completionListener);
}
// set nextMediaPlayers
mp[0].setNextMediaPlayer(mp[1]);
mp[1].setNextMediaPlayer(mp[2]);
// start the first MediaPlayer
mp[0].start();
// set mediaplayer inex
mediaPlayerIndex = 0;
// set state
state = STATE_PLAYING;
}
/**
* play file from resource
* @param resourceId
*/
public void play(int resourceId) {
this.resourceId = resourceId;
filePlaying = RESOURCE_PLAYING;
stop();
for (int i = 0; i < mp.length; i++) {
mp[i] = MediaPlayer.create(context, resourceId);
mp[i].setOnCompletionListener(completionListener);
}
mp[0].setNextMediaPlayer(mp[1]);
mp[1].setNextMediaPlayer(mp[2]);
mp[0].start();
mediaPlayerIndex = 0;
state = STATE_PLAYING;
}
/**
* play if the mediaplayer is pause
*/
public void play() {
if (state == STATE_PAUSED) {
mp[mediaPlayerIndex].start();
Log.d("BZMediaPlayer", "playing");
state = STATE_PLAYING;
}
}
/**
* pause current playing session
*/
public void pause() {
if (state == STATE_PLAYING) {
mp[mediaPlayerIndex].pause();
Log.d("BZMediaPlayer", "pausing");
state = STATE_PAUSED;
}
}
/**
* get current state
* @return
*/
public int getState() {
return state;
}
/**
* stop every mediaplayer
*/
public void stop() {
for(int i = 0 ; i < mp.length ; i++) {
if (mp[i] != null) {
mp[i].stop();
if(mp[i].isPlaying()) {
mp[i].release();
}
}
}
state = STATE_STOP;
}
/**
* set vol for every mediaplayer
* @param vol
*/
public void setVol(float vol) {
this.vol = vol;
for(int i = 0 ; i < mp.length ; i++) {
if (mp[i] != null && mp[i].isPlaying()) {
mp[i].setVolume(vol, vol);
}
}
}
/**
* internal listener which handles looping thing
*/
private MediaPlayer.OnCompletionListener completionListener = new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer curmp) {
int mpEnds = 0;
int mpPlaying = 0;
int mpNext = 0;
if(curmp == mp[0]) {
mpEnds = 0;
mpPlaying = 1;
mpNext = 2;
}
else if(curmp == mp[1]) {
mpEnds = 1;
mpPlaying = 2;
mpNext = 0; // corrected, else index out of range
}
else if(curmp == mp[2]) {
mpEnds = 2;
mpPlaying = 0; // corrected, else index out of range
mpNext = 1; // corrected, else index out of range
}
// as we have set mp2 mp1's next, so index will be 1
mediaPlayerIndex = mpPlaying;
Log.d("BZMediaPlayer", "Media Player " + mpEnds);
try {
// mp3 is already playing release it
if (mp[mpNext] != null) {
mp[mpNext].release();
}
// if we are playing uri
if (filePlaying == URI_PLAYING) {
mp[mpNext] = MediaPlayer.create(context, uri);
} else {
mp[mpNext] = MediaPlayer.create(context, resourceId);
}
// at listener to mp3
mp[mpNext].setOnCompletionListener(this);
// set vol
mp[mpNext].setVolume(vol, vol);
// set nextMediaPlayer
mp[mpPlaying].setNextMediaPlayer(mp[mpNext]);
// set nextMediaPlayer vol
mp[mpPlaying].setVolume(vol, vol);
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
Hope it will help somebody
Edit: clean code
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With