I have tried almost every method but I've failed to achieve gapless audio playback between looping a single track with a duration of 10-15 seconds.
Steps I've tried and failed :
Different audio file formats
.mp3
.wav
.ogg
usingsetLooping(true)
:MediaPlayer mp1 = MediaPlayer.create(MainActivity.this, R.raw.track1); mp1.setLooping(true); mp1.start();
Creating two mediaplayers and looping one after another using
setOnCompletionListener
same failed to loop without gaps.Using
setNextMediaPlayer(nextmp)
some how it works but only two loops is possible. We have to prepare and start again after the completion of previous two loops.mp1.start(); mp1.setNextMediaPlayer(mp2);
Update: Result of @Jeff Mixon answer: Mediaplayer looping stops with an error Android. Jeff Mixon works fine but only for 10 or 20 loops after that, due to some garbage collection issue the Mediaplayers stops immediately leaving the logs as posted below. I'm really kind of stuck here for 2 years. Thanks in advance.
E/MediaPlayer(24311): error (1, -38) E/MediaPlayer(23256): Error(1,-1007) E/MediaPlayer(23546): Error (1,-2147483648)
From the test that I have done, this solution works fine, over 150 loops with a 13 seconds 160 kbps MP3 without any problem:
To use
LoopMediaPlayer
you can just call:Ugly proof-of-concept code, but you'll get the idea:
This worked for me on an API 19 device and a 5-second 128 kbps MP3. No gaps in the loop.
I suggest you to use SoundPool API instead of
MediaPlayer
.From the official documentation:
Take a look here for a practical example of how to use
SoundPool
.For some reason, I found that my "OnCompletion" Event was always firing a fraction of second late when attempting to loop an 8-second OGG file. For anyone experiencing this type of delay, try the following.
It is possible to forcibly queue a "nextMediaPlayer" as recommend in previous solutions, by simply posting a delayed Runnable to a Handler for your MediaPlayers and avoiding looping in onCompletion Event altogether.
This performs flawlessly for me with my 160kbps 8-second OGG, min API 16.
Somewhere in your Activity/Service, create a HandlerThread & Handler...
...start the Thread, declare and set up your MediaPlayers...
...create a Method for swapping your MediaPlayers...
...create Runnables to post to your thread...
In your Service's onStartCommand() or somewhere in your Activity, start the MediaPlayer...
At least as of KitKat, Mattia Maestrini's Answer (to this question) is the only solution I've found that allows gapless looping of a large (> 1Mb uncompressed) audio sample. I've tried:
By simply including Maestrini's
LoopMediaPlayer
class in my project and then replacing myMediaPlayer.create()
calls withLoopMediaPlayer.create()
calls, I can ensure my .OGG sample is looped seamlessly.LoopMediaPlayer
is therefore a commendably practical and transparent solution.But this transparency begs the question: once I swap my
MediaPlayer
calls forLoopMediaPlayer
calls, how does my instance callMediaPlayer
methods such as .isPlaying
,.pause
or.setVolume
? Below is my solution for this issue. Possibly it can be improved upon by someone more Java-savvy than myself (and I welcome their input), but so far I've found this a reliable solution.The only changes I make to Maestrini's class (aside from some tweaks recommended by Lint) are as marked at the end of the code below; the rest I include for context. My addition is to implement several methods of
MediaPlayer
withinLoopMediaPlayer
by calling them onmCurrentPlayer
.Caveat: while I implement several useful methods of
MediaPlayer
below, I do not implement all of them. So if you expect for example to call.attachAuxEffect
you will need to add this yourself as a method toLoopMediaPlayer
along the lines of what I have added. Be sure to replicate the original interfaces of these methods (i.e., Parameters, Throws, and Returns):Something like this should work. Keep two copies of the same file in the res.raw directory. Please note that this is just a POC and not an optimized code. I just tested this out and it is working as intended. Let me know what you think.