Added random exercise set option for schedules. Also fixed annoying repeating notification sound when the timer was running. Restructure animations.
Closes #24
This commit is contained in:
parent
5a70021a3f
commit
4848fdd301
12 changed files with 110 additions and 38 deletions
|
|
@ -42,7 +42,9 @@ import org.secuso.privacyfriendlypausinghealthily.dialog.ExerciseDialog;
|
|||
import org.secuso.privacyfriendlypausinghealthily.exercises.ExerciseLocale;
|
||||
import org.secuso.privacyfriendlypausinghealthily.service.TimerService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.view.Gravity.CENTER_HORIZONTAL;
|
||||
|
|
@ -88,6 +90,7 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo
|
|||
private boolean showBigTimer = false;
|
||||
private boolean showControlButtons = true;
|
||||
private boolean keepScreenOn = true;
|
||||
private boolean scheduledExercise = false;
|
||||
|
||||
// exerciseSet info
|
||||
private long exerciseSetId;
|
||||
|
|
@ -125,16 +128,26 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo
|
|||
exerciseSetId = pref.getLong(FirstLaunchManager.DEFAULT_EXERCISE_SET, 0L);
|
||||
pauseDuration = pref.getLong(FirstLaunchManager.PAUSE_TIME, 5 * 60 * 1000);
|
||||
repeatStatus = pref.getBoolean(FirstLaunchManager.REPEAT_STATUS, false);
|
||||
keepScreenOn = pref.getBoolean(FirstLaunchManager.KEEP_SCREEN_ON_DURING_EXERCISE, true);
|
||||
continuousStatus = pref.getBoolean(FirstLaunchManager.REPEAT_EXERCISES, false);
|
||||
try {
|
||||
exerciseTime = Long.parseLong(pref.getString(FirstLaunchManager.EXERCISE_DURATION, "30")) * 1000;
|
||||
} catch (NumberFormatException e) {
|
||||
exerciseTime = 30L * 1000;
|
||||
}
|
||||
keepScreenOn = pref.getBoolean(FirstLaunchManager.KEEP_SCREEN_ON_DURING_EXERCISE, true);
|
||||
|
||||
initResources();
|
||||
|
||||
// this must be called after init resources because the database is needed
|
||||
// TODO: this call should probably not be done on the UI thread
|
||||
boolean randomScheduleExercise = pref.getBoolean(FirstLaunchManager.PREF_SCHEDULE_RANDOM_EXERCISE, false);
|
||||
scheduledExercise = getIntent().getBooleanExtra("SCHEDULED", false);
|
||||
|
||||
if(scheduledExercise && randomScheduleExercise) {
|
||||
List<ExerciseSet> set = dbHelper.getExerciseSets(pref.getBoolean(FirstLaunchManager.PREF_HIDE_DEFAULT_SETS, false));
|
||||
exerciseSetId = set.get((new Random()).nextInt(set.size())).getId(); // random from available sets
|
||||
}
|
||||
|
||||
ActionBar ab = getSupportActionBar();
|
||||
if (ab != null) {
|
||||
ab.setDisplayHomeAsUpEnabled(true);
|
||||
|
|
@ -229,6 +242,7 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo
|
|||
if(pref.getBoolean(FirstLaunchManager.PREF_EXERCISE_CONTINUOUS, false)) {
|
||||
Intent timerServiceIntent = new Intent(this.getApplicationContext(), TimerService.class);
|
||||
timerServiceIntent.setAction(TimerService.ACTION_START_TIMER);
|
||||
timerServiceIntent.putExtra("SCHEDULE", scheduledExercise);
|
||||
startService(timerServiceIntent);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package org.secuso.privacyfriendlypausinghealthily.activities;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
|
@ -76,9 +74,12 @@ public class TimerActivity extends BaseActivity implements android.support.v4.ap
|
|||
private boolean isActivityVisible = false;
|
||||
|
||||
// animation
|
||||
private int mShortAnimationDuration;
|
||||
private boolean currentStatusIsPickerVisible = false;
|
||||
|
||||
private ExerciseSet currentExerciseSet;
|
||||
private ConstraintSet constraintSetPicker;
|
||||
private ConstraintSet constraintSetRunning;
|
||||
|
||||
// Service
|
||||
private TimerService mTimerService = null;
|
||||
|
||||
|
|
@ -96,7 +97,6 @@ public class TimerActivity extends BaseActivity implements android.support.v4.ap
|
|||
mTimerService = null;
|
||||
}
|
||||
};
|
||||
private ExerciseSet currentExerciseSet;
|
||||
|
||||
private void onServiceConnected() {
|
||||
updateUI();
|
||||
|
|
@ -126,9 +126,28 @@ public class TimerActivity extends BaseActivity implements android.support.v4.ap
|
|||
setContentView(R.layout.activity_timer);
|
||||
|
||||
initResources();
|
||||
initAnimations();
|
||||
getSupportLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called <b>after</b> {@link #initResources()}
|
||||
*/
|
||||
private void initAnimations() {
|
||||
constraintSetPicker = new ConstraintSet();
|
||||
constraintSetPicker.clone(mainContent);
|
||||
|
||||
constraintSetRunning = new ConstraintSet();
|
||||
constraintSetRunning.clone(mainContent);
|
||||
int[] chainViews = {R.id.button_reset, R.id.button_playPause};
|
||||
float[] chainWeights = {0.5f, 0.5f};
|
||||
constraintSetRunning.createHorizontalChain(0, ConstraintSet.LEFT, 0, ConstraintSet.RIGHT, chainViews, chainWeights, ConstraintSet.CHAIN_PACKED);
|
||||
constraintSetRunning.setVisibility(R.id.button_reset, View.VISIBLE);
|
||||
constraintSetRunning.setVisibility(R.id.picker_layout, View.INVISIBLE);
|
||||
constraintSetRunning.setVisibility(R.id.progressBar, View.VISIBLE);
|
||||
constraintSetRunning.setVisibility(R.id.timerText, View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNavigationDrawerID() {
|
||||
return R.id.nav_timer;
|
||||
|
|
@ -188,8 +207,6 @@ public class TimerActivity extends BaseActivity implements android.support.v4.ap
|
|||
private void initResources() {
|
||||
final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
|
||||
mShortAnimationDuration = getResources().getInteger(android.R.integer.config_shortAnimTime);
|
||||
exerciseSetAdapter = new ExerciseSetSpinnerAdapter(this, R.layout.layout_exercise_set, new LinkedList<ExerciseSet>());
|
||||
|
||||
mainContent = findViewById(R.id.main_content);
|
||||
|
|
@ -391,25 +408,8 @@ public class TimerActivity extends BaseActivity implements android.support.v4.ap
|
|||
private synchronized void showPicker(final boolean showPicker) {
|
||||
if(showPicker != currentStatusIsPickerVisible) {
|
||||
|
||||
ConstraintSet constraintSet1 = new ConstraintSet();
|
||||
constraintSet1.clone(mainContent);
|
||||
constraintSet1.setHorizontalBias(R.id.button_playPause, 0.5f);
|
||||
constraintSet1.setVisibility(R.id.button_reset, View.INVISIBLE);
|
||||
constraintSet1.setVisibility(R.id.picker_layout, View.VISIBLE);
|
||||
constraintSet1.setVisibility(R.id.progressBar, View.INVISIBLE);
|
||||
constraintSet1.setVisibility(R.id.timerText, View.INVISIBLE);
|
||||
|
||||
|
||||
ConstraintSet constraintSet2 = new ConstraintSet();
|
||||
constraintSet2.clone(mainContent);
|
||||
constraintSet2.setHorizontalBias(R.id.button_playPause, 0.66f);
|
||||
constraintSet2.setVisibility(R.id.button_reset, View.VISIBLE);
|
||||
constraintSet2.setVisibility(R.id.picker_layout, View.INVISIBLE);
|
||||
constraintSet2.setVisibility(R.id.progressBar, View.VISIBLE);
|
||||
constraintSet2.setVisibility(R.id.timerText, View.VISIBLE);
|
||||
|
||||
TransitionManager.beginDelayedTransition(mainContent);
|
||||
ConstraintSet constraint = showPicker ? constraintSet1 : constraintSet2;
|
||||
ConstraintSet constraint = showPicker ? constraintSetPicker : constraintSetRunning;
|
||||
constraint.applyTo(mainContent);
|
||||
|
||||
//pickerLayout.clearAnimation();
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public class FirstLaunchManager {
|
|||
public static final String PREF_EXERCISE_CONTINUOUS = "pref_exercise_continuous";
|
||||
public static final String PREF_HIDE_DEFAULT_SETS = "pref_hide_default_exercise_sets";
|
||||
public static final String WORK_TIME = "WORK_TIME";
|
||||
public static final String PREF_SCHEDULE_RANDOM_EXERCISE= "pref_schedule_random_exercise";
|
||||
|
||||
private final SQLiteHelper dbHandler;
|
||||
private Context context;
|
||||
|
|
@ -85,6 +86,7 @@ public class FirstLaunchManager {
|
|||
.putLong(PREF_SCHEDULE_EXERCISE_TIME, 32400000L)
|
||||
.putBoolean(KEEP_SCREEN_ON_DURING_EXERCISE, true)
|
||||
.putBoolean(PREF_EXERCISE_CONTINUOUS, false)
|
||||
.putBoolean(PREF_SCHEDULE_RANDOM_EXERCISE, false)
|
||||
.putStringSet(PREF_SCHEDULE_EXERCISE_DAYS, new HashSet<String>(Arrays.asList("Mo", "Di", "Mi", "Do", "Fr", "Sa", "So")))
|
||||
.apply();
|
||||
|
||||
|
|
@ -108,6 +110,7 @@ public class FirstLaunchManager {
|
|||
// channels
|
||||
NotificationChannel timerRunningChannel = new NotificationChannel("timer_running", "Timer Running Notification", NotificationManager.IMPORTANCE_DEFAULT);
|
||||
timerRunningChannel.setVibrationPattern(new long[] { 0 });
|
||||
timerRunningChannel.setSound(null, null);
|
||||
timerRunningChannel.setGroup(groupId);
|
||||
|
||||
NotificationChannel timerDoneChannel = new NotificationChannel("timer_done", "Timer Done Notification", NotificationManager.IMPORTANCE_HIGH);
|
||||
|
|
|
|||
|
|
@ -181,6 +181,29 @@ public class SQLiteHelper extends SQLiteAssetHelper {
|
|||
return result;
|
||||
}
|
||||
|
||||
public synchronized List<ExerciseSet> getExerciseSets(boolean hideDefaults) {
|
||||
Cursor c = getExerciseSetsCursor();
|
||||
|
||||
List<ExerciseSet> result = new ArrayList<>();
|
||||
|
||||
if(c != null) {
|
||||
|
||||
c.moveToFirst();
|
||||
|
||||
while(!c.isAfterLast()) {
|
||||
ExerciseSet set = ExerciseSetColumns.fromCursor(c);
|
||||
if(!hideDefaults || !set.isDefaultSet()) {
|
||||
result.add(set);
|
||||
}
|
||||
c.moveToNext();
|
||||
}
|
||||
|
||||
c.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Exercise> buildExerciseList(Cursor c) {
|
||||
List<Exercise> result = new ArrayList<>();
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public final class ExerciseLocale {
|
|||
"en", "de"
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the available language. If the default language of the device is not available. {@code "en"} will be returned.
|
||||
|
|
|
|||
|
|
@ -25,4 +25,4 @@ public class NotificationCancelReceiver extends BroadcastReceiver {
|
|||
manager.cancel(TimerService.NOTIFICATION_ID);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public class TimerSchedulerReceiver extends WakefulBroadcastReceiver {
|
|||
}
|
||||
|
||||
private void startTimer() {
|
||||
mTimerService.startTimer(mPref.getLong(WORK_TIME, 1000L * 60L * 60L));
|
||||
mTimerService.startTimer(mPref.getLong(WORK_TIME, 1000L * 60L * 60L), true);
|
||||
}
|
||||
|
||||
public static void scheduleNextAlarm(@NonNull Context context) {
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ public class TimerService extends Service {
|
|||
};
|
||||
private BroadcastReceiver notificationDeletedReceiver = new NotificationDeletedReceiver();
|
||||
private BroadcastReceiver notificationPreferenceChangedReceiver = new NotificationCancelReceiver();
|
||||
private boolean scheduled = false;
|
||||
|
||||
private void onTimerDone() {
|
||||
|
||||
|
|
@ -101,7 +102,10 @@ public class TimerService extends Service {
|
|||
Intent snoozeIntent = new Intent(this, TimerService.class);
|
||||
snoozeIntent.setAction(ACTION_SNOOZE_TIMER);
|
||||
|
||||
PendingIntent startExercises = PendingIntent.getActivity(this, 0, new Intent(this, ExerciseActivity.class), FLAG_CANCEL_CURRENT);
|
||||
Intent exerciseIntent = new Intent(this, ExerciseActivity.class);
|
||||
exerciseIntent.putExtra("SCHEDULED", scheduled);
|
||||
|
||||
PendingIntent startExercises = PendingIntent.getActivity(this, 0, exerciseIntent, FLAG_CANCEL_CURRENT);
|
||||
PendingIntent snoozeExercise = PendingIntent.getService(this, 0, snoozeIntent, FLAG_UPDATE_CURRENT);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "timer_done");
|
||||
|
|
@ -149,7 +153,17 @@ public class TimerService extends Service {
|
|||
unregisterReceiver(notificationPreferenceChangedReceiver);
|
||||
}
|
||||
|
||||
public synchronized void startTimer(final long duration) {
|
||||
public void startTimer(final long duration, boolean scheduled) {
|
||||
this.scheduled = scheduled;
|
||||
startTimerInternal(duration);
|
||||
}
|
||||
|
||||
public void startTimer(final long duration) {
|
||||
this.scheduled = false;
|
||||
startTimerInternal(duration);
|
||||
}
|
||||
|
||||
private synchronized void startTimerInternal(final long duration) {
|
||||
if(!isRunning) {
|
||||
initialDuration = duration;
|
||||
|
||||
|
|
@ -262,7 +276,7 @@ public class TimerService extends Service {
|
|||
|
||||
final String action = intent.getAction();
|
||||
|
||||
if (ACTION_START_TIMER.equals(action)) handleRestartTimer();
|
||||
if (ACTION_START_TIMER.equals(action)) handleRestartTimer(intent);
|
||||
else if (ACTION_PAUSE_TIMER.equals(action)) pauseTimer();
|
||||
else if (ACTION_RESUME_TIMER.equals(action)) resumeTimer();
|
||||
else if (ACTION_STOP_TIMER.equals(action)) stopAndResetTimer();
|
||||
|
|
@ -282,12 +296,19 @@ public class TimerService extends Service {
|
|||
startTimer(snoozeTime);
|
||||
}
|
||||
|
||||
private void handleRestartTimer(Intent intent) {
|
||||
if(intent != null) {
|
||||
scheduled = intent.getBooleanExtra("SCHEDULE", false);
|
||||
}
|
||||
handleRestartTimer();
|
||||
}
|
||||
|
||||
private void handleRestartTimer() {
|
||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
if(pref.getBoolean(PREF_EXERCISE_CONTINUOUS, false)) {
|
||||
long duration = pref.getLong(WORK_TIME, 1000 * 60 * 60);
|
||||
startTimer(duration);
|
||||
startTimerInternal(duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -304,11 +325,15 @@ public class TimerService extends Service {
|
|||
|
||||
String time = String.format(Locale.US, "%02d:%02d:%02d", hours, minutes, seconds);
|
||||
|
||||
PendingIntent startExercises = PendingIntent.getActivity(this, 0, new Intent(this, ExerciseActivity.class), FLAG_CANCEL_CURRENT);
|
||||
Intent exerciseIntent = new Intent(this, ExerciseActivity.class);
|
||||
exerciseIntent.putExtra("SCHEDULED", scheduled);
|
||||
PendingIntent startExercises = PendingIntent.getActivity(this, 0, exerciseIntent, FLAG_CANCEL_CURRENT);
|
||||
|
||||
builder.setContentText(time);
|
||||
builder.setColor(ContextCompat.getColor(this, R.color.colorAccent));
|
||||
builder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
|
||||
builder.setOnlyAlertOnce(true);
|
||||
builder.setSound(null);
|
||||
builder.setWhen(0);
|
||||
builder.setProgress((int) initialDuration, (int) (initialDuration - remainingDuration), false);
|
||||
builder.setSmallIcon(R.mipmap.ic_notification);
|
||||
|
|
|
|||
|
|
@ -291,9 +291,7 @@
|
|||
android:tint="@color/darkblue"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.33"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:srcCompat="@drawable/ic_replay_black_48dp" />
|
||||
|
||||
<ImageButton
|
||||
|
|
@ -308,9 +306,10 @@
|
|||
android:onClick="onClick"
|
||||
android:scaleType="fitXY"
|
||||
android:tint="@color/darkblue"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:srcCompat="@drawable/ic_play_arrow_black" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
|
|
|||
|
|
@ -163,5 +163,6 @@
|
|||
<string name="dialog_warning_not_enough_exercise_time">Die ausgewählte Übungszeit ist zu kurz, um das gewählte Übungsset abzuschließen. Die Übungszeit wird automatisch angepasst. Möchten Sie den Timer starten?</string>
|
||||
<string name="warning">Achtung</string>
|
||||
<string name="toast_not_enough_exercise_time">Die gewählte Übungszeit ist nicht ausreichend, um das gewählte Übungsset abzuschließen. Die Zeit wurde automatisch angepasst.</string>
|
||||
<string name="pref_schedule_random_exercise">Verwende zufällige Übungssets</string>
|
||||
|
||||
</resources>
|
||||
|
|
@ -156,6 +156,7 @@
|
|||
<string name="dialog_warning_not_enough_exercise_time">The chosen exercise time is too short to finish the selected exercise set. The time will automatically be adjusted. Are you sure you want to start the timer?</string>
|
||||
<string name="warning">Warning</string>
|
||||
<string name="toast_not_enough_exercise_time">The currently selected exercise time is not sufficient to complete the chosen exercise set. The time has been adjusted.</string>
|
||||
<string name="pref_schedule_random_exercise">Use random exercise sets</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@
|
|||
android:title="@string/pref_schedule_exercise_days"
|
||||
android:key="pref_schedule_exercise_days"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:dependency="pref_schedule_exercise"
|
||||
android:title="@string/pref_schedule_random_exercise"
|
||||
android:key="pref_schedule_random_exercise"/>
|
||||
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
Loading…
Add table
Add a link
Reference in a new issue