Moved lap inserting and updating to StopwatchNotificationService
This commit is contained in:
parent
ad7335c6d6
commit
facdf05602
@ -1,6 +1,7 @@
|
|||||||
package com.philliphsu.clock2.stopwatch;
|
package com.philliphsu.clock2.stopwatch;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
import com.philliphsu.clock2.AsyncDatabaseTableUpdateHandler;
|
import com.philliphsu.clock2.AsyncDatabaseTableUpdateHandler;
|
||||||
import com.philliphsu.clock2.alarms.ScrollHandler;
|
import com.philliphsu.clock2.alarms.ScrollHandler;
|
||||||
@ -19,6 +20,17 @@ public class AsyncLapsTableUpdateHandler extends AsyncDatabaseTableUpdateHandler
|
|||||||
return new LapsTableManager(context);
|
return new LapsTableManager(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostAsyncInsert(Long result, Lap item) {
|
||||||
|
if (result > 1) {
|
||||||
|
// Update the notification's title with this lap number
|
||||||
|
Intent intent = new Intent(getContext(), StopwatchNotificationService.class)
|
||||||
|
.setAction(StopwatchNotificationService.ACTION_UPDATE_LAP_TITLE)
|
||||||
|
.putExtra(StopwatchNotificationService.EXTRA_LAP_NUMBER, result.intValue());
|
||||||
|
getContext().startService(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ===================== DO NOT IMPLEMENT =========================
|
// ===================== DO NOT IMPLEMENT =========================
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -26,11 +38,6 @@ public class AsyncLapsTableUpdateHandler extends AsyncDatabaseTableUpdateHandler
|
|||||||
// Leave blank.
|
// Leave blank.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostAsyncInsert(Long result, Lap item) {
|
|
||||||
// Leave blank.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostAsyncUpdate(Long result, Lap item) {
|
protected void onPostAsyncUpdate(Long result, Lap item) {
|
||||||
// Leave blank.
|
// Leave blank.
|
||||||
|
|||||||
@ -46,10 +46,7 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
// TODO: See if we can remove these? Since we save prefs in the notif. service.
|
// TODO: See if we can remove these? Since we save prefs in the notif. service.
|
||||||
private long mStartTime;
|
private long mStartTime;
|
||||||
private long mPauseTime;
|
private long mPauseTime;
|
||||||
private Lap mCurrentLap;
|
|
||||||
private Lap mPreviousLap;
|
|
||||||
|
|
||||||
private AsyncLapsTableUpdateHandler mUpdateHandler;
|
|
||||||
private ObjectAnimator mProgressAnimator;
|
private ObjectAnimator mProgressAnimator;
|
||||||
private SharedPreferences mPrefs;
|
private SharedPreferences mPrefs;
|
||||||
private WeakReference<FloatingActionButton> mActivityFab;
|
private WeakReference<FloatingActionButton> mActivityFab;
|
||||||
@ -69,7 +66,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
mUpdateHandler = new AsyncLapsTableUpdateHandler(getActivity(), null/*we shouldn't need a scroll handler*/);
|
|
||||||
mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||||
mStartTime = mPrefs.getLong(KEY_START_TIME, 0);
|
mStartTime = mPrefs.getLong(KEY_START_TIME, 0);
|
||||||
mPauseTime = mPrefs.getLong(KEY_PAUSE_TIME, 0);
|
mPauseTime = mPrefs.getLong(KEY_PAUSE_TIME, 0);
|
||||||
@ -79,6 +75,8 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
// onCreateView() or any other callback that is guaranteed to be called.
|
// onCreateView() or any other callback that is guaranteed to be called.
|
||||||
mStartDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_start_24dp);
|
mStartDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_start_24dp);
|
||||||
mPauseDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_pause_24dp);
|
mPauseDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_pause_24dp);
|
||||||
|
|
||||||
|
// TODO: Load the current lap here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -184,15 +182,17 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
// TODO: Will manipulating the cursor's position here affect the current
|
// TODO: Will manipulating the cursor's position here affect the current
|
||||||
// position in the adapter? Should we make a defensive copy and manipulate
|
// position in the adapter? Should we make a defensive copy and manipulate
|
||||||
// that copy instead?
|
// that copy instead?
|
||||||
|
Lap currentLap = null;
|
||||||
|
Lap previousLap = null;
|
||||||
if (data.moveToFirst()) {
|
if (data.moveToFirst()) {
|
||||||
mCurrentLap = data.getItem();
|
currentLap = data.getItem();
|
||||||
// Log.d(TAG, "Current lap ID = " + mCurrentLap.getId());
|
// Log.d(TAG, "Current lap ID = " + mCurrentLap.getId());
|
||||||
}
|
}
|
||||||
if (data.moveToNext()) {
|
if (data.moveToNext()) {
|
||||||
mPreviousLap = data.getItem();
|
previousLap = data.getItem();
|
||||||
// Log.d(TAG, "Previous lap ID = " + mPreviousLap.getId());
|
// Log.d(TAG, "Previous lap ID = " + mPreviousLap.getId());
|
||||||
}
|
}
|
||||||
if (mCurrentLap != null && mPreviousLap != null) {
|
if (currentLap != null && previousLap != null) {
|
||||||
// We really only want to start a new animator when the NEWLY RETRIEVED current
|
// We really only want to start a new animator when the NEWLY RETRIEVED current
|
||||||
// and previous laps are different (i.e. different laps, NOT merely different instances)
|
// and previous laps are different (i.e. different laps, NOT merely different instances)
|
||||||
// from the CURRENT current and previous laps, as referenced by mCurrentLap and mPreviousLap.
|
// from the CURRENT current and previous laps, as referenced by mCurrentLap and mPreviousLap.
|
||||||
@ -208,13 +208,13 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
// NOTE: If we just recreated ourselves due to rotation, mChronometer.isRunning() == false,
|
// NOTE: If we just recreated ourselves due to rotation, mChronometer.isRunning() == false,
|
||||||
// because it is not yet visible (i.e. mVisible == false).
|
// because it is not yet visible (i.e. mVisible == false).
|
||||||
if (isStopwatchRunning()) {
|
if (isStopwatchRunning()) {
|
||||||
startNewProgressBarAnimator();
|
startNewProgressBarAnimator(currentLap, previousLap);
|
||||||
} else {
|
} else {
|
||||||
// I verified the bar was visible already without this, so we probably don't need this,
|
// I verified the bar was visible already without this, so we probably don't need this,
|
||||||
// but it's just a safety measure..
|
// but it's just a safety measure..
|
||||||
// ACTUALLY NOT A SAFETY MEASURE!
|
// ACTUALLY NOT A SAFETY MEASURE!
|
||||||
// mSeekBar.setVisibility(View.VISIBLE);
|
// mSeekBar.setVisibility(View.VISIBLE);
|
||||||
ProgressBarUtils.setProgress(mSeekBar, getCurrentLapProgressRatio());
|
ProgressBarUtils.setProgress(mSeekBar, getCurrentLapProgressRatio(currentLap, previousLap));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mSeekBar.setVisibility(View.INVISIBLE);
|
mSeekBar.setVisibility(View.INVISIBLE);
|
||||||
@ -228,10 +228,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
|
|
||||||
final Intent serviceIntent = new Intent(getActivity(), StopwatchNotificationService.class);
|
final Intent serviceIntent = new Intent(getActivity(), StopwatchNotificationService.class);
|
||||||
if (mStartTime == 0) {
|
if (mStartTime == 0) {
|
||||||
// addNewLap() won't call through unless chronometer is running, which
|
|
||||||
// we can't start until we compute mStartTime
|
|
||||||
mCurrentLap = new Lap();
|
|
||||||
mUpdateHandler.asyncInsert(mCurrentLap);
|
|
||||||
setMiniFabsVisible(true);
|
setMiniFabsVisible(true);
|
||||||
// Handle the default action, i.e. post the notification for the first time.
|
// Handle the default action, i.e. post the notification for the first time.
|
||||||
getActivity().startService(serviceIntent);
|
getActivity().startService(serviceIntent);
|
||||||
@ -258,41 +254,14 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
|
|
||||||
@OnClick(R.id.new_lap)
|
@OnClick(R.id.new_lap)
|
||||||
void addNewLap() {
|
void addNewLap() {
|
||||||
if (!mChronometer.isRunning()) {
|
Intent serviceIntent = new Intent(getActivity(), StopwatchNotificationService.class)
|
||||||
Log.d(TAG, "Cannot add new lap");
|
.setAction(StopwatchNotificationService.ACTION_ADD_LAP);
|
||||||
return;
|
getActivity().startService(serviceIntent);
|
||||||
}
|
|
||||||
if (mCurrentLap != null) {
|
|
||||||
mCurrentLap.end(mChronometer.getText().toString());
|
|
||||||
}
|
|
||||||
mPreviousLap = mCurrentLap;
|
|
||||||
mCurrentLap = new Lap();
|
|
||||||
if (mPreviousLap != null) {
|
|
||||||
// if (getAdapter().getItemCount() == 0) {
|
|
||||||
// mUpdateHandler.asyncInsert(mPreviousLap);
|
|
||||||
// } else {
|
|
||||||
mUpdateHandler.asyncUpdate(mPreviousLap.getId(), mPreviousLap);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
mUpdateHandler.asyncInsert(mCurrentLap);
|
|
||||||
// This would end up being called twice: here, and in onLoadFinished(), because the
|
|
||||||
// table updates will prompt us to requery.
|
|
||||||
// startNewProgressBarAnimator();
|
|
||||||
// TODO: Start service with ACTION_ADD_LAP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.stop)
|
@OnClick(R.id.stop)
|
||||||
void stop() {
|
void stop() {
|
||||||
// Remove the notification. This will also write to prefs and clear the laps table.
|
// Remove the notification. This will also write to prefs and clear the laps table.
|
||||||
//
|
|
||||||
// The service will make changes to shared prefs, which will fire our
|
|
||||||
// OnSharedPrefChangeListener, which will call this stop() method. As such, this
|
|
||||||
// stop() method will be called twice: first from the click, and the second from
|
|
||||||
// the OnSharedPrefChange callback.
|
|
||||||
// TODO: Make similar changes as you did with onFabClick() so that the above method calls
|
|
||||||
// are made in the OnSharedPrefChange callback. You may find it helpful to extract
|
|
||||||
// the above method calls into private helper methods, just as you did for
|
|
||||||
// onFabClick().
|
|
||||||
Intent stop = new Intent(getActivity(), StopwatchNotificationService.class)
|
Intent stop = new Intent(getActivity(), StopwatchNotificationService.class)
|
||||||
.setAction(StopwatchNotificationService.ACTION_STOP);
|
.setAction(StopwatchNotificationService.ACTION_STOP);
|
||||||
getActivity().startService(stop);
|
getActivity().startService(stop);
|
||||||
@ -311,8 +280,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
// stop() will also make a call to updateRunning(), but the running state has not
|
// stop() will also make a call to updateRunning(), but the running state has not
|
||||||
// changed from the time we left the app.
|
// changed from the time we left the app.
|
||||||
mChronometer.stop();
|
mChronometer.stop();
|
||||||
mCurrentLap.pause();
|
|
||||||
mUpdateHandler.asyncUpdate(mCurrentLap.getId(), mCurrentLap);
|
|
||||||
// No issues controlling the animator here, because onLoadFinished() can't
|
// No issues controlling the animator here, because onLoadFinished() can't
|
||||||
// call through to startNewProgressBarAnimator(), because by that point
|
// call through to startNewProgressBarAnimator(), because by that point
|
||||||
// the chronometer won't be running.
|
// the chronometer won't be running.
|
||||||
@ -330,10 +297,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
mPauseTime = 0;
|
mPauseTime = 0;
|
||||||
mChronometer.setBase(mStartTime);
|
mChronometer.setBase(mStartTime);
|
||||||
mChronometer.start();
|
mChronometer.start();
|
||||||
if (!mCurrentLap.isRunning()) {
|
|
||||||
mCurrentLap.resume();
|
|
||||||
mUpdateHandler.asyncUpdate(mCurrentLap.getId(), mCurrentLap);
|
|
||||||
}
|
|
||||||
// This animator instance will end up having end() called on it. When
|
// This animator instance will end up having end() called on it. When
|
||||||
// the table update prompts us to requery, onLoadFinished will be called as a result.
|
// the table update prompts us to requery, onLoadFinished will be called as a result.
|
||||||
// There, it calls startNewProgressAnimator() to end this animation and starts an
|
// There, it calls startNewProgressAnimator() to end this animation and starts an
|
||||||
@ -353,8 +316,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
mStartTime = 0;
|
mStartTime = 0;
|
||||||
mPauseTime = 0;
|
mPauseTime = 0;
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
mCurrentLap = null;
|
|
||||||
mPreviousLap = null;
|
|
||||||
// No issues controlling the animator here, because onLoadFinished() can't
|
// No issues controlling the animator here, because onLoadFinished() can't
|
||||||
// call through to startNewProgressBarAnimator(), because by that point
|
// call through to startNewProgressBarAnimator(), because by that point
|
||||||
// the chronometer won't be running.
|
// the chronometer won't be running.
|
||||||
@ -376,8 +337,8 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
mActivityFab.get().setImageDrawable(running ? mPauseDrawable : mStartDrawable);
|
mActivityFab.get().setImageDrawable(running ? mPauseDrawable : mStartDrawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startNewProgressBarAnimator() {
|
private void startNewProgressBarAnimator(Lap currentLap, Lap previousLap) {
|
||||||
final long timeRemaining = remainingTimeBetweenLaps();
|
final long timeRemaining = remainingTimeBetweenLaps(currentLap, previousLap);
|
||||||
if (timeRemaining <= 0) {
|
if (timeRemaining <= 0) {
|
||||||
mSeekBar.setVisibility(View.INVISIBLE);
|
mSeekBar.setVisibility(View.INVISIBLE);
|
||||||
return;
|
return;
|
||||||
@ -388,8 +349,8 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
// This can't go in the onAnimationStart() callback because the listener is added
|
// This can't go in the onAnimationStart() callback because the listener is added
|
||||||
// AFTER ProgressBarUtils.startNewAnimator() starts the animation.
|
// AFTER ProgressBarUtils.startNewAnimator() starts the animation.
|
||||||
mSeekBar.setVisibility(View.VISIBLE);
|
mSeekBar.setVisibility(View.VISIBLE);
|
||||||
mProgressAnimator = ProgressBarUtils.startNewAnimator(
|
mProgressAnimator = ProgressBarUtils.startNewAnimator(mSeekBar,
|
||||||
mSeekBar, getCurrentLapProgressRatio(), timeRemaining);
|
getCurrentLapProgressRatio(currentLap, previousLap), timeRemaining);
|
||||||
mProgressAnimator.addListener(new Animator.AnimatorListener() {
|
mProgressAnimator.addListener(new Animator.AnimatorListener() {
|
||||||
private boolean cancelled;
|
private boolean cancelled;
|
||||||
|
|
||||||
@ -424,26 +385,18 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getCurrentLapProgressRatio() {
|
private double getCurrentLapProgressRatio(Lap currentLap, Lap previousLap) {
|
||||||
if (mPreviousLap == null)
|
if (previousLap == null)
|
||||||
return 0;
|
return 0;
|
||||||
// The cast is necessary, or else we'd have integer division between two longs and we'd
|
// The cast is necessary, or else we'd have integer division between two longs and we'd
|
||||||
// always get zero since the numerator will always be less than the denominator.
|
// always get zero since the numerator will always be less than the denominator.
|
||||||
return remainingTimeBetweenLaps() / (double) mPreviousLap.elapsed();
|
return remainingTimeBetweenLaps(currentLap, previousLap) / (double) previousLap.elapsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private long remainingTimeBetweenLaps() {
|
private long remainingTimeBetweenLaps(Lap currentLap, Lap previousLap) {
|
||||||
if (mCurrentLap == null || mPreviousLap == null)
|
if (currentLap == null || previousLap == null)
|
||||||
return 0;
|
return 0;
|
||||||
return mPreviousLap.elapsed() - mCurrentLap.elapsed();
|
return previousLap.elapsed() - currentLap.elapsed();
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Delete.
|
|
||||||
private void savePrefs() {
|
|
||||||
mPrefs.edit().putLong(KEY_START_TIME, mStartTime)
|
|
||||||
.putLong(KEY_PAUSE_TIME, mPauseTime)
|
|
||||||
.putBoolean(KEY_CHRONOMETER_RUNNING, mChronometer.isRunning())
|
|
||||||
.apply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -7,22 +7,35 @@ import android.os.SystemClock;
|
|||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.philliphsu.clock2.ChronometerNotificationService;
|
import com.philliphsu.clock2.ChronometerNotificationService;
|
||||||
import com.philliphsu.clock2.MainActivity;
|
import com.philliphsu.clock2.MainActivity;
|
||||||
import com.philliphsu.clock2.R;
|
import com.philliphsu.clock2.R;
|
||||||
|
import com.philliphsu.clock2.timers.ChronometerDelegate;
|
||||||
|
|
||||||
public class StopwatchNotificationService extends ChronometerNotificationService {
|
public class StopwatchNotificationService extends ChronometerNotificationService {
|
||||||
private static final String ACTION_ADD_LAP = "com.philliphsu.clock2.stopwatch.action.ADD_LAP";
|
private static final String TAG = "StopwatchNotifService";
|
||||||
|
|
||||||
private AsyncLapsTableUpdateHandler mLapsTableUpdateHandler;
|
public static final String ACTION_ADD_LAP = "com.philliphsu.clock2.stopwatch.action.ADD_LAP";
|
||||||
|
public static final String ACTION_UPDATE_LAP_TITLE = "com.philliphsu.clock2.stopwatch.action.UPDATE_LAP_TITLE";
|
||||||
|
|
||||||
|
public static final String EXTRA_LAP_NUMBER = "com.philliphsu.clock2.stopwatch.extra.LAP_NUMBER";
|
||||||
|
|
||||||
|
private AsyncLapsTableUpdateHandler mUpdateHandler;
|
||||||
private SharedPreferences mPrefs;
|
private SharedPreferences mPrefs;
|
||||||
|
private final ChronometerDelegate mDelegate = new ChronometerDelegate();
|
||||||
|
private Lap mCurrentLap;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
mLapsTableUpdateHandler = new AsyncLapsTableUpdateHandler(this, null);
|
mUpdateHandler = new AsyncLapsTableUpdateHandler(this, null);
|
||||||
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
// TODO: I'm afraid the base time here will be off by a considerable amount from the base time
|
||||||
|
// set in StopwatchFragment.
|
||||||
|
mDelegate.init();
|
||||||
|
mDelegate.setShowCentiseconds(true, false);
|
||||||
// TODO: I think we can make this a foreground service so even
|
// TODO: I think we can make this a foreground service so even
|
||||||
// if the process is killed, this service remains alive.
|
// if the process is killed, this service remains alive.
|
||||||
}
|
}
|
||||||
@ -58,27 +71,38 @@ public class StopwatchNotificationService extends ChronometerNotificationService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleDefaultAction(Intent intent, int flags, long startId) {
|
protected void handleDefaultAction(Intent intent, int flags, long startId) {
|
||||||
|
// TODO: Why do we need this check? Won't KEY_START_TIME always have a value of 0 here?
|
||||||
|
if (mPrefs.getLong(StopwatchFragment.KEY_START_TIME, 0) == 0) {
|
||||||
|
mCurrentLap = new Lap();
|
||||||
|
mUpdateHandler.asyncInsert(mCurrentLap);
|
||||||
|
}
|
||||||
// TODO: String resource [Stopwatch: Lap %1$s]. If no laps, just [Stopwatch]
|
// TODO: String resource [Stopwatch: Lap %1$s]. If no laps, just [Stopwatch]
|
||||||
setContentTitle(getString(R.string.stopwatch));
|
setContentTitle(getString(R.string.stopwatch));
|
||||||
syncNotificationWithStopwatchState(true/*always true*/);
|
syncNotificationWithStopwatchState(true/*always true*/);
|
||||||
// We don't need to write anything to SharedPrefs because if we're here, StopwatchFragment
|
// We don't need to write anything to SharedPrefs because if we're here, StopwatchFragment
|
||||||
// already wrote the necessary values to file.
|
// will start this service again with ACTION_START_PAUSE, which will do the writing.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleStartPauseAction(Intent intent, int flags, long startId) {
|
protected void handleStartPauseAction(Intent intent, int flags, long startId) {
|
||||||
// TODO: Tell StopwatchFragment to start/pause itself.. perhaps with an Intent?
|
|
||||||
boolean running = mPrefs.getBoolean(StopwatchFragment.KEY_CHRONOMETER_RUNNING, false);
|
boolean running = mPrefs.getBoolean(StopwatchFragment.KEY_CHRONOMETER_RUNNING, false);
|
||||||
SharedPreferences.Editor editor = mPrefs.edit();
|
SharedPreferences.Editor editor = mPrefs.edit();
|
||||||
editor.putBoolean(StopwatchFragment.KEY_CHRONOMETER_RUNNING, !running);
|
editor.putBoolean(StopwatchFragment.KEY_CHRONOMETER_RUNNING, !running);
|
||||||
if (running) {
|
if (running) {
|
||||||
editor.putLong(StopwatchFragment.KEY_PAUSE_TIME, SystemClock.elapsedRealtime());
|
editor.putLong(StopwatchFragment.KEY_PAUSE_TIME, SystemClock.elapsedRealtime());
|
||||||
|
mCurrentLap.pause();
|
||||||
|
mUpdateHandler.asyncUpdate(mCurrentLap.getId(), mCurrentLap);
|
||||||
} else {
|
} else {
|
||||||
long startTime = mPrefs.getLong(StopwatchFragment.KEY_START_TIME, 0);
|
long startTime = mPrefs.getLong(StopwatchFragment.KEY_START_TIME, 0);
|
||||||
long pauseTime = mPrefs.getLong(StopwatchFragment.KEY_PAUSE_TIME, 0);
|
long pauseTime = mPrefs.getLong(StopwatchFragment.KEY_PAUSE_TIME, 0);
|
||||||
startTime += SystemClock.elapsedRealtime() - pauseTime;
|
startTime += SystemClock.elapsedRealtime() - pauseTime;
|
||||||
editor.putLong(StopwatchFragment.KEY_START_TIME, startTime);
|
editor.putLong(StopwatchFragment.KEY_START_TIME, startTime);
|
||||||
editor.putLong(StopwatchFragment.KEY_PAUSE_TIME, 0);
|
editor.putLong(StopwatchFragment.KEY_PAUSE_TIME, 0);
|
||||||
|
// TODO: Why do we need this check? Won't this lap always be paused here?
|
||||||
|
if (!mCurrentLap.isRunning()) {
|
||||||
|
mCurrentLap.resume();
|
||||||
|
mUpdateHandler.asyncUpdate(mCurrentLap.getId(), mCurrentLap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
editor.apply();
|
editor.apply();
|
||||||
syncNotificationWithStopwatchState(!running);
|
syncNotificationWithStopwatchState(!running);
|
||||||
@ -86,7 +110,6 @@ public class StopwatchNotificationService extends ChronometerNotificationService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleStopAction(Intent intent, int flags, long startId) {
|
protected void handleStopAction(Intent intent, int flags, long startId) {
|
||||||
// TODO: Tell StopwatchFragment to stop itself.. perhaps with an Intent?
|
|
||||||
mPrefs.edit()
|
mPrefs.edit()
|
||||||
.putLong(StopwatchFragment.KEY_START_TIME, 0)
|
.putLong(StopwatchFragment.KEY_START_TIME, 0)
|
||||||
.putLong(StopwatchFragment.KEY_PAUSE_TIME, 0)
|
.putLong(StopwatchFragment.KEY_PAUSE_TIME, 0)
|
||||||
@ -100,14 +123,33 @@ public class StopwatchNotificationService extends ChronometerNotificationService
|
|||||||
// We can either clear the laps table here, as we've done already, or do as the TODO above
|
// We can either clear the laps table here, as we've done already, or do as the TODO above
|
||||||
// says and tell StopwatchFragment to stop itself. The latter would also stop the
|
// says and tell StopwatchFragment to stop itself. The latter would also stop the
|
||||||
// chronometer view if the fragment is still in view (i.e. app is still open).
|
// chronometer view if the fragment is still in view (i.e. app is still open).
|
||||||
mLapsTableUpdateHandler.asyncClear();
|
mCurrentLap = null;
|
||||||
|
mUpdateHandler.asyncClear();
|
||||||
stopSelf();
|
stopSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleAction(@NonNull String action, Intent intent, int flags, long startId) {
|
protected void handleAction(@NonNull String action, Intent intent, int flags, long startId) {
|
||||||
if (ACTION_ADD_LAP.equals(action)) {
|
if (ACTION_ADD_LAP.equals(action)) {
|
||||||
mLapsTableUpdateHandler.asyncInsert(null/*TODO*/);
|
if (mPrefs.getBoolean(StopwatchFragment.KEY_CHRONOMETER_RUNNING, false)) {
|
||||||
|
String timestamp = mDelegate.formatElapsedTime(SystemClock.elapsedRealtime(),
|
||||||
|
null/*Resources not needed here*/).toString();
|
||||||
|
mCurrentLap.end(timestamp);
|
||||||
|
mUpdateHandler.asyncUpdate(mCurrentLap.getId(), mCurrentLap);
|
||||||
|
|
||||||
|
Lap newLap = new Lap();
|
||||||
|
mUpdateHandler.asyncInsert(newLap);
|
||||||
|
mCurrentLap = newLap;
|
||||||
|
}
|
||||||
|
} else if (ACTION_UPDATE_LAP_TITLE.equals(action)) {
|
||||||
|
int lapNumber = intent.getIntExtra(EXTRA_LAP_NUMBER, 0);
|
||||||
|
if (lapNumber == 0) {
|
||||||
|
Log.w(TAG, "Lap number was not passed in with intent");
|
||||||
|
}
|
||||||
|
// Unfortunately, the ID is only assigned when retrieving a Lap instance from
|
||||||
|
// its cursor; the value here will always be 0.
|
||||||
|
setContentTitle(getString(R.string.stopwatch_and_lap_number, lapNumber));
|
||||||
|
updateNotification(true);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("StopwatchNotificationService cannot handle action " + action);
|
throw new IllegalArgumentException("StopwatchNotificationService cannot handle action " + action);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -206,6 +206,8 @@
|
|||||||
|
|
||||||
<string name="stopwatch">Stopwatch</string>
|
<string name="stopwatch">Stopwatch</string>
|
||||||
<string name="lap">Lap</string>
|
<string name="lap">Lap</string>
|
||||||
|
<!-- The notification title to use when there are laps in a stopwatch timing. An example is "Stopwatch - Lap 2". -->
|
||||||
|
<string name="stopwatch_and_lap_number">Stopwatch \u002d Lap %1$d</string>
|
||||||
|
|
||||||
<!-- https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/values/strings.xml -->
|
<!-- https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/values/strings.xml -->
|
||||||
<!-- The representation of a time duration when negative. An example is -1:14. This can be used with a countdown timer for example.-->
|
<!-- The representation of a time duration when negative. An example is -1:14. This can be used with a countdown timer for example.-->
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user