First of all, thank you for this great site, I have found a great deal of information by searching through the questions answered here. I have a problem, though, that I only found one mention of (with no answer).
I am writing an application that uses AudioTrack to loop a runtime-generated sinewave through the headphone jack (to control other electronics). It does this at timed intervals (using Handler.postDelayed), and it works just fine - except if you happen to force close the application. In that case, the sine wave keeps on playing even after the app itself is long gone, and literally the only thing I can do to stop it is to reboot the phone.
The sound stops like it should if the application is closed properly, and even if it crashes.
I have tried:
- creating an onDestroy() method to stop and release the AudioTrack instance, but unfortunately, it doesn't even get called.
- using a larger audio buffer for the sound loop (hoping that the small buffer size caused the bug); no difference.
- starting my app again: now I have two freaking sine waves!
- uninstalling(!) the app entirely: the sine wave is still there to haunt me from beyond its grave.
- putting the phone into silent mode: no difference. (I don't want this to happen to my users.)
- turning the Media Volume all the way down, and waiting 15+ minutes: no difference.
- changing the sample rate to 11, 22, or 44.1 kHz: no difference.
- starting and killing the app again and again: I could actually get 8 different immortal sine waves interfering with each other this way. Pretty cool actually. :P
I know it's not 'healthy' to use task killers on Android, but a lot of people still do, and I don't want my users' phones to become unstoppable noise generators in case my application happens to hang and get its arse whooped.
Here is the code that generates the sine wave:
int bufSize = (int)(11025.0 / 60.0); // the number of samples needed for a seamless loop at 60Hz
AT = new AudioTrack(AudioManager.STREAM_MUSIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_8BIT, bufSize, AudioTrack.MODE_STATIC);
byte buffer[] = new byte[bufSize];
float angle = 0.0f;
for (int i=0; i < bufSize; i++){
buffer[i] = (byte)(Math.sin(angle) * 255);
angle += (float)(2*Math.PI) * 60 / 11025;
}
if (AT.write(buffer, 0, bufSize) != bufSize){
log("Error: Couldn't write audio buffer!");
} else {
AT.setLoopPoints(0, bufSize, -1);
AT.play();
}
Even though I'm pretty sure this bug is in Android itself, I have been desperately searching for a way to detect a force close in order to run one last line of code to stop this from happening before my app dies. I've found no solution, even though I know this is possible somehow (I have an evil alarm app that comes back to life even if you kill it with a task killer). I would be extremely grateful if anyone could enlighten me!
I've also noticed that when my app is running in the background and I return to it (from the "recent apps" menu or through any other way), it seems as if a new instance is created each time. This means you can't stop the other instance playing in the background - except if you use a task killer... I'm sure this must be some trivial beginner's mistake I've made, but I was wondering if it might be related to the Sinewave of Death.
Running Android 2.1.1 on an Xperia X10 mini pro.