diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9130196
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+
+# testing
+/coverage
+
+# production
+/build
+/app/build
+/app/release
+
+# misc
+.*
+*.properties
+*.iml
+!.gitignore
+
diff --git a/app/build.gradle b/app/build.gradle
index c204660..f490654 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -49,6 +49,12 @@ android {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
+ lintOptions {
+ checkReleaseBuilds false
+ // Or, if you prefer, you can continue to check for errors in release builds,
+ // but continue the build even when errors are found:
+// abortOnError false
+ }
}
dependencies {
diff --git a/app/src/main/java/de/tadris/fitness/activity/RecordWorkoutActivity.java b/app/src/main/java/de/tadris/fitness/activity/RecordWorkoutActivity.java
index 5edd3c6..2121c5e 100644
--- a/app/src/main/java/de/tadris/fitness/activity/RecordWorkoutActivity.java
+++ b/app/src/main/java/de/tadris/fitness/activity/RecordWorkoutActivity.java
@@ -38,6 +38,8 @@ import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
+import android.speech.tts.TextToSpeech;
+
import androidx.core.app.ActivityCompat;
import org.mapsforge.core.graphics.Paint;
@@ -50,9 +52,11 @@ import org.mapsforge.map.layer.overlay.Polyline;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import de.tadris.fitness.Instance;
import de.tadris.fitness.R;
+import de.tadris.fitness.data.UserPreferences;
import de.tadris.fitness.data.Workout;
import de.tadris.fitness.map.MapManager;
import de.tadris.fitness.map.tilesource.TileSources;
@@ -82,6 +86,8 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
private Intent locationListener;
private Intent pressureService;
private boolean saved= false;
+ TextToSpeech tts;
+ boolean ttsReady = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -102,6 +108,9 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
recorder= new WorkoutRecorder(this, ACTIVITY, this);
recorder.start();
+ tts = new TextToSpeech(this, (int status) -> {
+ ttsReady = status == TextToSpeech.SUCCESS && tts.setLanguage(Locale.getDefault())>=0;
+ });
infoViews[0]= new InfoViewHolder(findViewById(R.id.recordInfo1Title), findViewById(R.id.recordInfo1Value));
infoViews[1]= new InfoViewHolder(findViewById(R.id.recordInfo2Title), findViewById(R.id.recordInfo2Value));
infoViews[2]= new InfoViewHolder(findViewById(R.id.recordInfo3Title), findViewById(R.id.recordInfo3Value));
@@ -169,9 +178,7 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
try{
while (recorder.isActive()){
Thread.sleep(1000);
- if(isResumed){
- mHandler.post(this::updateDescription);
- }
+ mHandler.post(this::updateDescription);
}
}catch (InterruptedException e){
e.printStackTrace();
@@ -179,15 +186,38 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
}).start();
}
- private int i = 0;
+ long lastSpokenUpdateTime = 0;
+ int lastSpokenUpdateDistance = 0;
- private void updateDescription(){
- i++;
- timeView.setText(UnitUtils.getHourMinuteSecondTime(recorder.getDuration()));
- infoViews[0].setText(getString(R.string.workoutDistance), UnitUtils.getDistance(recorder.getDistance()));
- infoViews[1].setText(getString(R.string.workoutBurnedEnergy), recorder.getCalories() + " kcal");
- infoViews[2].setText(getString(R.string.workoutAvgSpeed), UnitUtils.getSpeed(Math.min(100d, recorder.getAvgSpeed())));
- infoViews[3].setText(getString(R.string.workoutPauseDuration), UnitUtils.getHourMinuteSecondTime(recorder.getPauseDuration()));
+ private void updateDescription() {
+ long duration = recorder.getDuration();
+ int distanceInMeters = recorder.getDistance();
+ final String distanceCaption = getString(R.string.workoutDistance);
+ final String distance = UnitUtils.getDistance(distanceInMeters);
+ final String avgSpeedCaption = getString(R.string.workoutAvgSpeed);
+ final String avgSpeed = UnitUtils.getSpeed(Math.min(100d, recorder.getAvgSpeed()));
+ if (isResumed) {
+ timeView.setText(UnitUtils.getHourMinuteSecondTime(duration));
+ infoViews[0].setText(distanceCaption, distance);
+ infoViews[1].setText(getString(R.string.workoutBurnedEnergy), recorder.getCalories() + " kcal");
+ infoViews[2].setText(avgSpeedCaption, avgSpeed);
+ infoViews[3].setText(getString(R.string.workoutPauseDuration), UnitUtils.getHourMinuteSecondTime(recorder.getPauseDuration()));
+ }
+
+ final UserPreferences prefs = Instance.getInstance(this).userPreferences;
+ final long intervalT = 60 * 1000 * prefs.getSpokenUpdateTimePeriod();
+ final int intervalInMeters = (int) (1000.0 / UnitUtils.CHOSEN_SYSTEM.getDistanceFromKilometers(1) * prefs.getSpokenUpdateDistancePeriod());
+ if (!ttsReady ||
+ (intervalT == 0 || duration / intervalT == lastSpokenUpdateTime / intervalT)
+ && (intervalInMeters == 0 || distanceInMeters / intervalInMeters == lastSpokenUpdateDistance / intervalInMeters)
+ ) return;
+
+ final String text = distanceCaption + ": " + distance + ". "
+ + avgSpeedCaption + ": " + avgSpeed;
+ tts.speak(text, TextToSpeech.QUEUE_FLUSH, null, "updateDescription" + duration);
+
+ lastSpokenUpdateTime = duration;
+ lastSpokenUpdateDistance = distanceInMeters;
}
private void stop(){
diff --git a/app/src/main/java/de/tadris/fitness/activity/SettingsActivity.java b/app/src/main/java/de/tadris/fitness/activity/SettingsActivity.java
index 9d0befb..e17c687 100644
--- a/app/src/main/java/de/tadris/fitness/activity/SettingsActivity.java
+++ b/app/src/main/java/de/tadris/fitness/activity/SettingsActivity.java
@@ -165,6 +165,10 @@ public class SettingsActivity extends PreferenceActivity {
showWeightPicker();
return true;
});
+ findPreference("speech").setOnPreferenceClickListener(preference -> {
+ showSpeechConfig();
+ return true;
+ });
findPreference("import").setOnPreferenceClickListener(preference -> {
showImportDialog();
return true;
@@ -285,7 +289,8 @@ public class SettingsActivity extends PreferenceActivity {
np.setMaxValue((int) UnitUtils.CHOSEN_SYSTEM.getWeightFromKilogram(150));
np.setMinValue((int) UnitUtils.CHOSEN_SYSTEM.getWeightFromKilogram(20));
np.setFormatter(value -> value + " " + UnitUtils.CHOSEN_SYSTEM.getWeightUnit());
- np.setValue((int)Math.round(UnitUtils.CHOSEN_SYSTEM.getWeightFromKilogram(preferences.getInt("weight", 80))));
+ final String preferenceVariable = "weight";
+ np.setValue((int)Math.round(UnitUtils.CHOSEN_SYSTEM.getWeightFromKilogram(preferences.getInt(preferenceVariable, 80))));
np.setWrapSelectorWheel(false);
d.setView(v);
@@ -294,7 +299,47 @@ public class SettingsActivity extends PreferenceActivity {
d.setPositiveButton(R.string.okay, (dialog, which) -> {
int unitValue= np.getValue();
int kilograms= (int)Math.round(UnitUtils.CHOSEN_SYSTEM.getKilogramFromUnit(unitValue));
- preferences.edit().putInt("weight", kilograms).apply();
+ preferences.edit().putInt(preferenceVariable, kilograms).apply();
+ });
+
+ d.create().show();
+
+ return true;
+ }
+
+ private boolean showSpeechConfig() {
+ UnitUtils.setUnit(this); // Maybe the user changed unit system
+
+ final AlertDialog.Builder d = new AlertDialog.Builder(this);
+ final SharedPreferences preferences= PreferenceManager.getDefaultSharedPreferences(this);
+ d.setTitle(getString(R.string.pref_spoken_updates_summary));
+ View v= getLayoutInflater().inflate(R.layout.dialog_spoken_updates_picker, null);
+
+ NumberPicker npT = v.findViewById(R.id.spokenUpdatesTimePicker);
+ npT.setMaxValue(60);
+ npT.setMinValue(0);
+ npT.setFormatter(value -> value == 0 ? "No speech" : value + " min");
+ final String updateTimeVariable = "spokenUpdateTimePeriod";
+ npT.setValue(preferences.getInt(updateTimeVariable, 0));
+ npT.setWrapSelectorWheel(false);
+
+ final String distanceUnit = " " + UnitUtils.CHOSEN_SYSTEM.getLongDistanceUnit();
+ NumberPicker npD = v.findViewById(R.id.spokenUpdatesDistancePicker);
+ npD.setMaxValue(10);
+ npD.setMinValue(0);
+ npD.setFormatter(value -> value == 0 ? "No speech" : value + distanceUnit);
+ final String updateDistanceVariable = "spokenUpdateDistancePeriod";
+ npD.setValue(preferences.getInt(updateDistanceVariable, 0));
+ npD.setWrapSelectorWheel(false);
+
+ d.setView(v);
+
+ d.setNegativeButton(R.string.cancel, null);
+ d.setPositiveButton(R.string.okay, (dialog, which) -> {
+ preferences.edit()
+ .putInt(updateTimeVariable, npT.getValue())
+ .putInt(updateDistanceVariable, npD.getValue())
+ .apply();
});
d.create().show();
diff --git a/app/src/main/java/de/tadris/fitness/data/UserPreferences.java b/app/src/main/java/de/tadris/fitness/data/UserPreferences.java
index 7fdb1f4..f9882c5 100644
--- a/app/src/main/java/de/tadris/fitness/data/UserPreferences.java
+++ b/app/src/main/java/de/tadris/fitness/data/UserPreferences.java
@@ -35,6 +35,14 @@ public class UserPreferences {
return preferences.getInt("weight", 80);
}
+ public int getSpokenUpdateTimePeriod(){
+ return preferences.getInt("spokenUpdateTimePeriod", 5);
+ }
+
+ public int getSpokenUpdateDistancePeriod(){
+ return preferences.getInt("spokenUpdateDistancePeriod", 1);
+ }
+
public String getMapStyle(){
return preferences.getString("mapStyle", "osm.mapnik");
}
diff --git a/app/src/main/java/de/tadris/fitness/map/MapManager.java b/app/src/main/java/de/tadris/fitness/map/MapManager.java
index caa54c7..23efa99 100644
--- a/app/src/main/java/de/tadris/fitness/map/MapManager.java
+++ b/app/src/main/java/de/tadris/fitness/map/MapManager.java
@@ -62,7 +62,6 @@ public class MapManager {
mapView.getLayerManager().redrawLayers();
mapView.setZoomLevel((byte) 18);
- mapView.setCenter(new LatLong(52, 13));
return downloadLayer;
}
diff --git a/app/src/main/java/de/tadris/fitness/map/tilesource/MapnikTileSource.java b/app/src/main/java/de/tadris/fitness/map/tilesource/MapnikTileSource.java
index 30dab49..d9ab541 100644
--- a/app/src/main/java/de/tadris/fitness/map/tilesource/MapnikTileSource.java
+++ b/app/src/main/java/de/tadris/fitness/map/tilesource/MapnikTileSource.java
@@ -30,7 +30,7 @@ public class MapnikTileSource extends FitoTrackTileSource {
"a.tile.openstreetmap.org", "b.tile.openstreetmap.org", "c.tile.openstreetmap.org"}, 443);
private static final int PARALLEL_REQUESTS_LIMIT = 8;
private static final String PROTOCOL = "https";
- private static final int ZOOM_LEVEL_MAX = 18;
+ private static final int ZOOM_LEVEL_MAX = 19;
private static final int ZOOM_LEVEL_MIN = 0;
private static final String NAME = "OSM Mapnik";
diff --git a/app/src/main/java/de/tadris/fitness/recording/WorkoutRecorder.java b/app/src/main/java/de/tadris/fitness/recording/WorkoutRecorder.java
index 07b25a3..856166a 100644
--- a/app/src/main/java/de/tadris/fitness/recording/WorkoutRecorder.java
+++ b/app/src/main/java/de/tadris/fitness/recording/WorkoutRecorder.java
@@ -47,7 +47,7 @@ public class WorkoutRecorder implements LocationListener.LocationChangeListener
}
}
- private static final int PAUSE_TIME= 10000;
+ private static final int PAUSE_TIME= 1000*1000;
/**
* Time after which the workout is stopped and saved automatically because there is no activity anymore
diff --git a/app/src/main/res/layout/dialog_spoken_updates_picker.xml b/app/src/main/res/layout/dialog_spoken_updates_picker.xml
new file mode 100644
index 0000000..3df099f
--- /dev/null
+++ b/app/src/main/res/layout/dialog_spoken_updates_picker.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index b0cde6c..4459871 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -50,6 +50,11 @@
Bevorzugtes Einheitensystem
Dein Gewicht
Dein Gewicht ist zur Kalorienberechnung wichtig
+
+
+ Spoken Updates
+ Choose the time and distance between spoken updates
+
Einstellungen
Workout aufzeichnen
Wiederherstellen
@@ -107,4 +112,4 @@
Upload fehlgeschlagen
Upload erfolgreich
Nicht autorisiert, nocheinmal versuchen
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index da6a17b..522bf2d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -57,7 +57,7 @@
Pace
Route
Speed
- Avg. Speed
+ Average Speed
Top Speed
Burned Energy
Total Energy
@@ -112,6 +112,8 @@
Export as GPX-File
Your Weight
Your weight is needed to calculate the burned calories
+ Spoken Updates
+ Choose the time and distance between spoken updates
Preferred system of units
Settings
Export Data
diff --git a/app/src/main/res/xml/preferences_main.xml b/app/src/main/res/xml/preferences_main.xml
index 8757058..3342d39 100644
--- a/app/src/main/res/xml/preferences_main.xml
+++ b/app/src/main/res/xml/preferences_main.xml
@@ -40,6 +40,13 @@
android:key="mapStyle"
android:title="@string/mapStyle" />
+
+
@@ -54,4 +61,4 @@
-
\ No newline at end of file
+
diff --git a/build.gradle b/build.gradle
index 608be65..820a5ba 100644
--- a/build.gradle
+++ b/build.gradle
@@ -23,11 +23,11 @@ buildscript {
repositories {
google()
jcenter()
-
+
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
-
+
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
@@ -37,7 +37,7 @@ allprojects {
repositories {
google()
jcenter()
-
+
}
}