Our app has a lot of music-like audio, in that we have a seekbar, play/pause controls and so forth.
The issue we're having is that on some devices, we cannot seek to the start of the file using the seekbar without it stuttering or missing a small amount at the start (about a second, give or take). The amount skipped is not the same from file-to-file and from device-to-device, but the amount is the same each time with the same file-device combination.
The only way we can start from the beginning without these issues is to call MediaPlayer.stop()
and then start afresh with a release and construction - something we want to avoid as seeking should just work. Seeking to other areas of the file seems to work, or at least it's not as noticable.
This happens on most of our devices, tested models that experience this include Asus Nexus 7, Huawei Nexus 6P, LG G4, and Sony Xperia Z. It's notable that we don't experience this on our samsung tablets.
We're coding in C++ using the JNI, with a minimum of Android 4.4. So all of our MediaPlayer calls go via the JNI into the java code. The seekbar passes a value between 0 and 1 as a percentage, and we have confirmed that it is indeed sending a 0 down to the JNI.
The files in question are stereo Ogg Vorbis with a Variable Bit Rate sampled at 44.1 KHz. They are stored in an OBB (packaged as an uncompressed zip) which is accessed via a FileInputStream with an offset and length. We use this method (or a similar one on the C++ side) successfully in other areas of the app for other files such as textures or XML files. We do have precident for copying out files before using them if need be; however, we'd rather avoid that in this case if we can.
Are we doing something wrong? Is it a known issue? Is there a workaround for this?
public void JNI_Audio_StartTrack(int iTrackIndex, String audioPath, long offset, long length)
{
if (enableDebug)
{
String myString = String.format("ExtAudio_StartTrack(%d,%s,%d,%d)", iTrackIndex, audioPath, offset, length);
Log.d("Tag", myString);
}
if (mediaPlayerInited)
{
mediaPlayer.release();
}
Context context = getApplicationContext();
int trackResource = 0;
FileInputStream fis = null;
try
{
fis = new FileInputStream(audioPath);
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(fis.getFD(), offset, length);
mediaPlayer.prepare();
mediaPlayer.start();
mediaPlayerInited = true;
}
//Normal FileInputStream handling Catch...Finally blocks follow
}
public void JNI_Audio_SeekTo(float iPercentage)
{
if (enableDebug)
{
String myString = String.format("ExtAudio_SeekTo(%f)", iPercentage);
Log.d("Tag", myString);
}
if (mediaPlayerInited)
{
int duration = mediaPlayer.getDuration();
float newSeekPos = (float)duration * iPercentage;
mediaPlayer.seekTo((int)newSeekPos);
}
}