I've found the audio subsystem is a little quirky. It's great if you
are playing songs, or video but if you are writing a game that plays
short sounds quickly it poses problems. After much work I found a
pretty cool solution to one of the annoying problems of MediaPlayer
being sluggish to play audio.
The problem is the audio system tends to go to sleep after 3 seconds.
When my application tries to play the next sound the phone's audio
system wakes up but seems to queue the sound instead of playing it.
When my application plays yet another sound -- as long as the sound
system hasn't gone back to sleep again -- it plays BOTH sounds at
once! This causes unacceptable behavior for any game.
What I ended up doing was this:
1. Use Audacity to create a 1-second .wav of total silence and add the
wave into my manifest as a raw resource referenced in the app as
R.raw.silence.
2. On startup, create a MediaPlayer instance, load the R.raw.silence
resource and play in a loop constantly.
This worked great at keeping the audio system awake, however the phone
was now draining the battery quickly whenever the game was loaded.
Since Android (and most phones) don't have a great way for the user to
terminate a task, this meant if you played the game for a couple of
minutes in the morning, the battery would drain at an accelerated rate
for the rest of the day! A bit unacceptable.
So here's the rather simple solution: Create a runnable under the
thread's handler and have the runnable keep track of the audio system.
If no user action has happened in 15 seconds, then pause the silence
track allowing the audio system to go to sleep. On the next user
action, restart the silence which wakes up the audio system which
places the silence clip on the queue. The next sound played works
perfectly as the silence actually plays along with the sound you want!
So in the program define a handler:
// Setup our handler for this thread's runnables
private Handler MyThreadHandler = new Handler();
Inside the applications activity in the onCreate method:
mSilence = MediaPlayer.create( (Context)this, R.raw.silence);
//Setup the audio sleep runnable with the following call
SetupAudioSleepTimeouts(); // <-- this is OUR audio sleeper
(below)
Now, anywhere in the program an event happens that means there is user
interaction ongoing or you just aren't ready to let the audio go to
sleep yet add this:
AudioSleepKeepAwake(); // Keep our audio system awake
Later within our activity class add the audio support logic
//--------------------------------------------------------------------
// audio control routines
//
private static final int AUDIOSLEEPTIME = 1000; // 1000 1 second
per audio timer tick
private static final int AUDIOSLEEPTIMEOUT = 15; // /timeout after
15 seconds of non activity and allow audio subsystem to goto sleep
private static final int AUDIOPAUSED = -1;
int AudioSleepTimer; // Counter to put audio to sleep.
If negative then we are paused.
//--------------------------------------------------------------------------------------
// AudioSleeperTask
// This runs all the time in the background
// and handles the 'silence' track that runs in the
background.
// If no user activity occurs for XX seconds this task
stops the
// background music and allows the
//
private Runnable AudioSleeperTask = new Runnable()
{
// Task to perform on each system tick
public void run()
{
if( AudioSleepTimer != AUDIOPAUSED )
{
AudioSleepTimer++;
if( AudioSleepTimer > AUDIOSLEEPTIMEOUT )
{
Log.i(TAG, "Audio: Putting audio to sleep");
mSilence.pause();
AudioSleepTimer = AUDIOPAUSED;
}
}
MyThreadHandler.postDelayed( this, AUDIOSLEEPTIME );
}
};
//----------------------------------------------------------------------------------------------
// Handle setting up the audio sleep timeout subsystem
public void SetupAudioSleepTimeouts()
{
Log.i(TAG, "Audio: Setup Audio KeepAwake");
// Get our silence started so we don't go to sleep
mSilence.setLooping( true );
mSilence.start();
// Setup the audio sleep timer
AudioSleepTimer = 0;
MyThreadHandler.removeCallbacks( AudioSleeperTask );
MyThreadHandler.postDelayed( AudioSleeperTask,
AUDIOSLEEPTIME);
}
//----------------------------------------------------------------------------------------------
// Keep the audio sleep timer awake
//
public void AudioSleepKeepAwake(){
if( AudioSleepTimer == AUDIOPAUSED )
{
Log.i(TAG, "Audio: Waking up Audio");
mSilence.start();
}
AudioSleepTimer = 0;
}
Of course it would be better to create a new class and encapsulate all
this inside the 'audiokeepawake' class. I posted it like this in order
to not confuse architectural niceities with the the audio system's
solution...
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---