Rev Tyler
Rev Tyler

Reputation: 603

Android Media Player hanging or returning null

I've got an interesting situation with the android MediaPlayer. I've got about 30 sounds that I need to play in an activity. I'm getting strange results that I'm not sure are coming from memory issues or not...

The reason why I need to use media player is that I've got a timed flow to the sounds where one sound needs to play after the other in a certain order. I also use the callbacks to see which sound is played next. Thus, soundpool is out...

I've tried loading each sound in to it's own media player using MediaPlayer.create(). Now, this works fine on my device, a Samsung Galaxy S Vibrant. My client with a Samsung Ace, however is getting null pointer exceptions when I try to set the onCompletionListener, meaning .create() returned null on his device but not mine.

So, I switched from loading them all at once to loading them on the fly in the onCompletionListener of the previous sound using this method

This kind of works, the fist 3-4 sounds play and then it hangs on my client's device (still works fine on my device). Which I'm assuming it's hanging on the .prepare()

This is incredibly hard to sort out since my client has no real knowledge of logcat and no SDK to debug, and it works fine on my device. It even hangs on his second device which is the same model as mine.

Anyone have any idea what might be causing this or how to debug it?

I'm thinking my next step will be to simply just use the one MediaPlayer and use the mp parameter of OnCompletionListener to load up the next sound on the same media player. I'll post my findings.

Upvotes: 1

Views: 3884

Answers (2)

Rev Tyler
Rev Tyler

Reputation: 603

So, it must have been some kind of memory issue. I had 20+ media players loaded up initially.

Now I combined them all in to one media player and am loading the sounds dynamically. The sounds are small so I'm not worried about the loading time.

Here is some helper code in case anyone wants it.

private MediaPlayer getMediaPlayer(MediaPlayer mp, int resID, OnCompletionListener listener){
mp.release();
mp = null;
mp = new MediaPlayer();
AssetFileDescriptor afd = getResources().openRawResourceFd(resID);
try {
    mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
    mp.prepare();
    mp.setOnCompletionListener(listener);
} catch (IllegalArgumentException e) {
    e.printStackTrace();
} catch (IllegalStateException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}
return mp;
}

I use this to load a new sound. Its got a fair bit of overhead but it works and that's what's important.

Here is how I use it.

mSoundPlayer = getMediaPlayer(mSoundPlayer, R.raw.a123switch, endSwitch123Listener);
mSoundPlayer.start();

Upvotes: 1

Dororo
Dororo

Reputation: 3440

Providing you are releasing the media player correctly, it shouldn't be a memory problem. You can properly ensure this by doing:

if(mediaplayer!=null){
        if(mediaplayer.isPlaying()){
            mediaplayer.stop();
        }
        mediaplayer.release();
        mediaplayer = null;
}

I believe there is a 10MB limit (minimum, some phones are higher) to apk memory allocation, so you should be able to check this fits within your limits. Market will allow up to 50MB however.

For debugging, I suggest you ensure that all the assests are there (sounds silly, but it rules it out) since if you're missing the sound files it will of course fail to create. Creating Toast notifications if an exception is thrown e.g. IllegalStateException will ensure that you management of media player states is not a problem.

It's also worth mentioning that you should not ever mix prepare and create. If you are using create, it will already call prepare and subsequent calls to prepare may cause odd behaviour; not sure if it will nullify the player though!

In general, you don't want to really be doing it the way you propose (creating a new mediaplayer and changing the sound in onComplete). The reason for this is simple, when you call create or prepare, it will load the sound into memory - this will take a variable amount of time dependant on phone (it may be a really long time for some phones!). It's far better to load them all up at once.

Upvotes: 1

Related Questions