I’ve a multi-threaded app where main thread initiate two threads:
- MakeRequest Thread
- QueueListener Thread
MakeRequest thread after each second query a printer on LAN to request some data and perform some calculations on it and feed it to a Queue on which the second thread is listening. As soon as the data is available in the Queue, QueueListener thread dequeue a record from the Queue and initiate another thread i.e. MediaPlayer thread this thread is responsible for playing 7 to 8 files depending on the string received. For which I am using the following code.
MediaPlayer mp = MediaPlayer.create(context, Uri.fromFile(new File(q[voiceIndex])));
mp.setOnCompletionListener(mCompletionListener);
mp.setOnErrorListener(mErrorListener);
mp.start();
this code is in PlayMedia() method, and in OnCompletionListener, I’ve the following code:
OnCompletionListener mCompletionListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
//will be called when media player finished playing a file.
mp.release();
StartPlayingNextFile();
}
};
private void StartPlayingNextFile() {
voiceIndex++;
if (voiceIndex < q.length){
PlayMedia();
}else{
finishedPlaying = true;
}
}
When QueueListener Thread initiate MediaPlayer Thread I’ve used Join() on MediaPlayer thread in order not to dequeue another string from the queue and wait till the MediaPlayer finishes its business, otherwise I’ll hear over lapping sounds.
Now, most of the time everything seems to be working fine but MediaPlayer sometime skips playing some files and thus MediaPlayer thread never terminates because OnCompletionListener never called and OnErrorListener never get called either, because of which Join() never releases, so I’ve to explicitly do it after a reasonable time has passed:
@Override
public void run() {
//record the start time
timeStart = new Date().getTime();
PlayMedia();
while (!finishedPlaying){
try {
//if a reasonable time has passed break the loop
long currentTime = (new Date().getTime() - timeStart);
long elapsedSeconds = TimeUnit.MILLISECONDS.toSeconds(currentTime);
if (elapsedSeconds > 15){
break;
}
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Log from LogCat can bee seen here where 5 files have been skipped between line 2 and 27 i.e.
Line 2:
01-21 01:20:18.474: V/MediaPlayerService(3240): Create new client(1854) from pid 15063, url=/mnt/sdcard/voicedata/200.wav, connId=1854
Line 27:
01-21 01:20:30.504: V/MediaPlayerService(3240): Create new client(1855) from pid 15063, url=/mnt/sdcard/voicedata/constants/bell.wav, connId=1855
files that have been skipped are:
/mnt/sdcard/voicedata/a.wav
/mnt/sdcard/voicedata/b.wav
/mnt/sdcard/voicedata/c.wav
/mnt/sdcard/voicedata/d.wav
/mnt/sdcard/voicedata/e.wav
and bell.wav is the very first file, that plays before all these files.
After rigorous testing I’ve found out that reducing the number of files actually improves the changes that MediaPlayer would not skip any file.