So I'm trying to create a simple timer app that outputs the elapsed time to the screen. I'm trying to incorporate a pause button. It seems to work, except when pause button is pressed closed to values of x:x:1~ (min:sec:milli) if you unpause and repause rapidly again the next displayed value will be around x:x:N (N > 1) rather than x:x-1:9~. Logcat output below. DISPLAY is the time displayed (time remaining, SHOULD be always decreasing but its not). Elapsed time is the internal time elapsed (always increasing, so looks like that is ok)
10-09 23:28:16.152: D/ClockView(16547): ELAPSED TIME 1728
10-09 23:28:16.152: D/ClockView(16547): DISPLAY 0:8:272
10-09 23:28:16.252: D/ClockView(16547): ELAPSED TIME 1829
10-09 23:28:16.252: D/ClockView(16547): DISPLAY 0:8:171
10-09 23:28:16.282: D/ClockView(16547): PAUSE PRESSED
10-09 23:28:16.983: D/ClockView(16547): PAUSE PRESSED
10-09 23:28:16.983: D/ClockView(16547): ELAPSED TIME 1868
10-09 23:28:16.983: D/ClockView(16547): DISPLAY 0:8:132
10-09 23:28:17.083: D/ClockView(16547): ELAPSED TIME 1968
10-09 23:28:17.083: D/ClockView(16547): DISPLAY 0:8:32
10-09 23:28:17.123: D/ClockView(16547): PAUSE PRESSED
10-09 23:28:21.348: D/ClockView(16547): PAUSE PRESSED
10-09 23:28:21.348: D/ClockView(16547): ELAPSED TIME 2010
10-09 23:28:21.348: D/ClockView(16547): DISPLAY 0:7:990
10-09 23:28:21.448: D/ClockView(16547): ELAPSED TIME 2110
10-09 23:28:21.448: D/ClockView(16547): DISPLAY 0:7:890
Code below:
public class ClockCallable implements Callable<Long> {
private long startTime = SystemClock.elapsedRealtime();
private long elapsedTime = 0;
private long pausedStartTime = 0;
private long pausedTime = 0;
Object o = new Object();
private volatile boolean paused = false;
public void pause() {
paused = true;
synchronized(o) {
pausedStartTime = SystemClock.elapsedRealtime();
}
}
public void resume() {
paused = false;
synchronized(o) {
pausedTime = SystemClock.elapsedRealtime() - pausedStartTime;
startTime += pausedTime;
o.notifyAll();
}
}
public void reset() {
paused = false;
synchronized(o) {
clockCallable.startTime = SystemClock.elapsedRealtime();
clockCallable.elapsedTime = 0;
clockCallable.pausedStartTime = 0;
clockCallable.pausedTime = 0;
o.notifyAll();
}
}
@Override
public Long call() throws Exception {
try {
while (elapsedTime < maxTime && !Thread.currentThread().isInterrupted()) {
if (!paused) {
elapsedTime = SystemClock.elapsedRealtime() - startTime;
Log.d(TAG, "ELAPSED TIME " + elapsedTime);
handler.post(new Runnable() { //To post to UI thread
@Override
public void run() {
synchronized(o) {
updateTextView(elapsedTime);
}
}
});
Thread.sleep(100); //Prevent too much work on its main thread
if (Thread.currentThread().isInterrupted()) {
return (long) -1; //For future.cancel() handling
}
}
else {
try {
while(paused) {
synchronized(o) {
o.wait();
}
}
}
catch (InterruptedException e) {}
}
}
}
catch (InterruptedException e) {
e.printStackTrace();
return (long) -1; //For future.cancel() handling
}
return (long) 1;
}
}