Skip to content

Commit

Permalink
Fix drifting brew timer.
Browse files Browse the repository at this point in the history
  • Loading branch information
caseydavenport committed May 29, 2015
1 parent e8145ad commit 58601b8
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 62 deletions.
6 changes: 6 additions & 0 deletions BACKLOG
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ be recorded here
* Can choose where to export recipes.
* Better integration with Dropbox / Google Drive

//////////////////////////////////////////////
// Changelog for release 1.0.6 ///////////////
//////////////////////////////////////////////
* Fix parsing of XML which uses special characters.
* Fix timer drift

//////////////////////////////////////////////
// Changelog for release 1.0.5 ///////////////
//////////////////////////////////////////////
Expand Down
7 changes: 5 additions & 2 deletions src/com/biermacht/brews/frontend/BrewTimerActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,10 @@ public void pause() {
}

public void stop() {
// Set the currently displayed page to be the first instruction.
mViewPager.setCurrentItem(0);
currentItem = 0;

// Tell the timer serviced that we've stopped
Intent i = new Intent();
i.setAction(Constants.BROADCAST_TIMER_CONTROLS);
Expand Down Expand Up @@ -494,7 +498,7 @@ public void setTimerFromSeconds(int time) {
}

public void setTimerFromCurrentStep() {
if (! inst.showTimer()) {
if (!inst.showTimer()) {
setTimerToNull();
}
else {
Expand Down Expand Up @@ -548,7 +552,6 @@ public void onClick(View v) {
break;
}
case R.id.stop_button: {
mViewPager.setCurrentItem(0);
stop();
break;
}
Expand Down
108 changes: 48 additions & 60 deletions src/com/biermacht/brews/services/BrewTimerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
Expand Down Expand Up @@ -81,7 +82,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("BrewTimerService", "NULL intent passed to brew timer service. Likely due to " +
"a service restart. Canceling the service!");
stopSelf();
return Service.START_NOT_STICKY;
return Service.START_STICKY;
}

// Use the service ID to keep track of our corresponding notification
Expand All @@ -105,7 +106,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
// Indicate that the service is running
BrewTimerService.isRunning = true;

return Service.START_NOT_STICKY;
return Service.START_STICKY;
}

@Override
Expand All @@ -115,14 +116,12 @@ public void onDestroy() {

// Unregister receivers
unregisterReceiver(countdownReceiver);
unregisterReceiver(timer);
unregisterReceiver(messageHandler);
}

public void registerReceivers() {
// Create and register a new Timer. This will count down and broadcast the remaining time.:w
timer = new Timer(this);
registerReceiver(timer, new IntentFilter(Constants.BROADCAST_TIMER));

// Register our receiver for remaining time broadcasts
registerReceiver(countdownReceiver, new IntentFilter(Constants.BROADCAST_REMAINING_TIME));
Expand Down Expand Up @@ -189,8 +188,8 @@ public IBinder onBind(Intent intent) {
}
}

// Broadcast receiver
class Timer extends BroadcastReceiver {

class Timer {
// Keep track of timer state
public int timerState = Constants.STOPPED;

Expand All @@ -199,89 +198,78 @@ class Timer extends BroadcastReceiver {

// More private fields
private Context c;
AlarmManager alarmManager;
PendingIntent pendingTimerIntent;
CountDownTimer timer;

public Timer(Context c) {
super();
this.c = c;
this.alarmManager = (AlarmManager) (c.getSystemService(Context.ALARM_SERVICE));
this.pendingTimerIntent = PendingIntent.getBroadcast(c, 0, new Intent(Constants.BROADCAST_TIMER), 0);

}

/**
* Starts the timer, initializing the timer to the given number of seconds. If the timer is
* already running, this is a no-op.
* @param seconds
*/
public void start(int seconds) {
if (timerState != Constants.RUNNING) {
timerState = Constants.RUNNING;
remainingSeconds = seconds;
}

// Schedule the first timer callback.
this.scheduleTimerTick();
// Create a new countdown timer which starts at the given number of seconds, and counts
// down at a rate of one tick per 1000 milliseconds.
timer = new CountDownTimer(seconds * 1000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
remainingSeconds = (int) millisUntilFinished / 1000;
broadcastTime();
}

@Override
public void onFinish() {
// When the timer is finished, advertise that there is no time left remaining. This
// case it not handled by onTick(), since it is never called with 0 time remaining.
remainingSeconds = 0;
broadcastTime();
}
};
timer.start();
}
}

// Alternative to start(time) which just continues using the current
// remaining seconds.
/**
* An alternative to start(time) which starts the timer with the remaining number
* of seconds left.
*/
public void start() {
start(remainingSeconds);
}

/**
* Stops timer execution. This cancels the current timer and sets the timerState
* appropriately.
*/
public void stop() {
timerState = Constants.STOPPED;
timer.cancel();
}

/**
* Pauses timer execution. This cancels the current timer, and sets the timerState
* appropriately.
*/
public void pause() {
timerState = Constants.PAUSED;
timer.cancel();
}

/**
* Broadcasts the current remaining time to the BrewTimerActivity, where it is displayed
* in the timer view.
*/
public void broadcastTime() {
Intent i = new Intent();
i.setAction(Constants.BROADCAST_REMAINING_TIME);
i.putExtra(Constants.KEY_SECONDS, remainingSeconds);
c.sendBroadcast(i);
}

@Override
public void onReceive(Context c, Intent i) {
// If we're not running, stop ticking down.
if (timerState != Constants.RUNNING) {
return;
}

// Decrement current seconds
remainingSeconds = remainingSeconds - 1;

// Broadcast time
broadcastTime();

// Stop when we reach zero seconds remaining
if (remainingSeconds <= 0) {
stop();
}

// Schedule the next timer callback.
this.scheduleTimerTick();
}

/**
* Schedules a system alarm in 1000 milliseconds. This alarm is received by the Service and is
* used to update the timer.
*/
public void scheduleTimerTick() {
// For pre-KITKAT version of Android, AlarmManager.set() schedules an exact time in the future.
// For post-KITKAT version of Android, setExact() was added to perform this function, and set()
// is no-longer guaranteed to be exact (the OS may choose the reschedule in order to save
// battery life). We don't want to allow the OS to reschedule the timer, so make sure to use
// setExact() if it is available.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
this.alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 1000,
pendingTimerIntent);
}
else {
this.alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 1000,
pendingTimerIntent);
}
}
}

0 comments on commit 58601b8

Please sign in to comment.