I have a thread in an Android application that I would like to wait at a certain point in its operation for either:
- A notification from another thread, or
- A timeout to occur, which I would like to specify in real time.
Presently I have (roughly) the following:
...
doStuff();
synchronized(this) {
if (!notificationReceived) wait(TIMEOUTPERIOD);
}
doMoreStuff();
...
and in a method called from another thread:
synchronized(this) {
notificationReceived = true;
notifyAll();
}
This almost works. In fact, it worked all the way through debugging and testing, and only stopped working when I tried to deploy the application in the field. Because it turns out that the timer in Object.wait() stops when the phone CPU goes to sleep. As does the one in Thread.sleep(). Oops.
Now, I don’t mind that the call won’t return while the phone is asleep (actually I consider this desirable — the results of the action aren’t needed at any point when the phone is asleep), but if the phone sleeps for the duration of my timeout period, I’d like the action to trigger as soon as it does wake up.
Is there any way I’m missing to do this? I know I could use AlarmManager to send me a broadcast Intent after the required time, and put the continuation code in a (what…? A BroadcastReceiver? I’ve never done this before…) but this would substantially complicate the logic of my application. So: is there an easier way I can put a (cancellable) realtime delay in my thread?
I solved this problem by registering a BroadcastReceiver dynamically that has a reference to the object I wanted notifying, and making it call notifyAll() when it received a broadcast. I then used AlarmManager to set up alarms for it prior to each call to wait(), and cancelled the alarms after wait() returned if it was not due to a timeout.
I think there may be a race condition in my code where a timeout occurs at about the same time as an external notification, but in my case I decided it does not matter if I get a duplicated notification from time to time.