diff --git a/app/build.gradle b/app/build.gradle
index e9d848e..61dda2c 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -35,8 +35,8 @@ android {
applicationId "de.tadris.fitness"
minSdkVersion 21
targetSdkVersion 28
- versionCode 103
- versionName "1.0.3"
+ versionCode 110
+ versionName "1.1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2101dcd..a8d2f92 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,4 +1,23 @@
+
+
@@ -46,7 +65,8 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
-
+
+
\ No newline at end of file
diff --git a/app/src/main/java/de/tadris/fitness/Instance.java b/app/src/main/java/de/tadris/fitness/Instance.java
index 629e249..889fc8c 100644
--- a/app/src/main/java/de/tadris/fitness/Instance.java
+++ b/app/src/main/java/de/tadris/fitness/Instance.java
@@ -21,14 +21,17 @@ package de.tadris.fitness;
import android.content.Context;
+import androidx.annotation.NonNull;
import androidx.room.Room;
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
import java.util.ArrayList;
import java.util.List;
import de.tadris.fitness.data.AppDatabase;
import de.tadris.fitness.data.UserPreferences;
-import de.tadris.fitness.location.LocationListener;
+import de.tadris.fitness.recording.LocationListener;
import de.tadris.fitness.util.unit.UnitUtils;
public class Instance {
@@ -48,9 +51,45 @@ public class Instance {
public List locationChangeListeners= new ArrayList<>();
public UserPreferences userPreferences;
+ public boolean pressureAvailable= false;
+ public float lastPressure= 0;
+
private Instance(Context context) {
userPreferences= new UserPreferences(context);
db = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME)
+ .addMigrations(new Migration(1, 2) {
+ @Override
+ public void migrate(@NonNull SupportSQLiteDatabase database) {
+ try{
+ database.beginTransaction();
+
+ database.execSQL("ALTER table workout add descent REAL NOT NULL DEFAULT 0;");
+ database.execSQL("ALTER table workout add ascent REAL NOT NULL DEFAULT 0");
+
+ database.execSQL("ALTER TABLE workout_sample RENAME TO workout_sample2;");
+
+ database.execSQL("CREATE TABLE workout_sample (" +
+ "id INTEGER NOT NULL DEFAULT NULL PRIMARY KEY," +
+ "relativeTime INTEGER NOT NULL DEFAULT NULL," +
+ "elevation REAL NOT NULL DEFAULT NULL," +
+ "absoluteTime INTEGER NOT NULL DEFAULT NULL," +
+ "lat REAL NOT NULL DEFAULT NULL," +
+ "lon REAL NOT NULL DEFAULT NULL," +
+ "speed REAL NOT NULL DEFAULT NULL," +
+ "workout_id INTEGER NOT NULL DEFAULT NULL," +
+ "FOREIGN KEY (workout_id) REFERENCES workout(id) ON DELETE CASCADE);");
+
+ database.execSQL("INSERT INTO workout_sample (id, relativeTime, elevation, absoluteTime, lat, lon, speed, workout_id) " +
+ "SELECT id, relativeTime, elevation, absoluteTime, lat, lon, speed, workout_id FROM workout_sample2");
+
+ database.execSQL("DROP TABLE workout_sample2");
+
+ database.setTransactionSuccessful();
+ }finally {
+ database.endTransaction();
+ }
+ }
+ })
.allowMainThreadQueries()
.build();
UnitUtils.setUnit(context);
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 4314f15..12bd640 100644
--- a/app/src/main/java/de/tadris/fitness/activity/RecordWorkoutActivity.java
+++ b/app/src/main/java/de/tadris/fitness/activity/RecordWorkoutActivity.java
@@ -21,9 +21,11 @@ package de.tadris.fitness.activity;
import android.Manifest;
import android.app.AlertDialog;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
+import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -50,10 +52,11 @@ import java.util.List;
import de.tadris.fitness.Instance;
import de.tadris.fitness.R;
import de.tadris.fitness.data.Workout;
-import de.tadris.fitness.location.LocationListener;
-import de.tadris.fitness.location.WorkoutRecorder;
import de.tadris.fitness.map.MapManager;
import de.tadris.fitness.map.tilesource.TileSources;
+import de.tadris.fitness.recording.LocationListener;
+import de.tadris.fitness.recording.PressureService;
+import de.tadris.fitness.recording.WorkoutRecorder;
import de.tadris.fitness.util.ThemeManager;
import de.tadris.fitness.util.unit.UnitUtils;
@@ -72,6 +75,7 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
private Handler mHandler= new Handler();
PowerManager.WakeLock wakeLock;
Intent locationListener;
+ Intent pressureService;
private boolean saved= false;
@Override
@@ -154,7 +158,10 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
}).start();
}
+ int i= 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");
@@ -228,19 +235,42 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
public void stopListener(){
stopService(locationListener);
+ stopService(pressureService);
}
public void startListener(){
if(locationListener == null){
locationListener= new Intent(this, LocationListener.class);
+ pressureService= new Intent(this, PressureService.class);
}else{
stopListener();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(locationListener);
+ startService(pressureService);
}else{
startService(locationListener);
+ startService(pressureService);
}
+ checkGpsStatus();
+ }
+
+ private void checkGpsStatus(){
+ final LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
+
+ if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
+ openDialogNoGps();
+ }
+ }
+
+ private void openDialogNoGps(){
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.noGpsTitle)
+ .setMessage(R.string.noGpsMessage)
+ .setNegativeButton(R.string.cancel, (dialog, which) -> finish())
+ .setPositiveButton(R.string.enable, (dialog, which) -> startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)))
+ .setCancelable(false)
+ .create().show();
}
@Override
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 e898a4e..d36f871 100644
--- a/app/src/main/java/de/tadris/fitness/activity/SettingsActivity.java
+++ b/app/src/main/java/de/tadris/fitness/activity/SettingsActivity.java
@@ -325,9 +325,7 @@ public class SettingsActivity extends PreferenceActivity {
public boolean onMenuItemSelected(int featureId, MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
- if (!super.onMenuItemSelected(featureId, item)) {
- NavUtils.navigateUpFromSameTask(this);
- }
+ finish();
return true;
}
return super.onMenuItemSelected(featureId, item);
diff --git a/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java
index 58f35ef..86e8cb3 100644
--- a/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java
+++ b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java
@@ -131,6 +131,13 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
addKeyValue(getString(R.string.workoutTotalEnergy), workout.calorie + " kcal",
getString(R.string.workoutEnergyConsumption), UnitUtils.getRelativeEnergyConsumption((double)workout.calorie / ((double)workout.length / 1000)));
+ addTitle(getString(R.string.height));
+
+ addKeyValue(getString(R.string.workoutAscent), UnitUtils.getDistance((int)workout.ascent),
+ getString(R.string.workoutDescent), UnitUtils.getDistance((int)workout.descent));
+
+ addHeightDiagram();
+
}
@@ -199,20 +206,20 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
root.addView(v);
}
- void addSpeedDiagram(){
+ void addDiagram(SampleConverter converter){
LineChart chart= new LineChart(this);
- WorkoutManager.roundSpeedValues(samples);
+ converter.onCreate();
List entries = new ArrayList<>();
for (WorkoutSample sample : samples) {
// turn your data into Entry objects
- Entry e= new Entry((float)(sample.relativeTime) / 1000f / 60f, (float)sample.tmpRoundedSpeed*3.6f);
+ Entry e= new Entry((float)(sample.relativeTime) / 1000f / 60f, converter.getValue(sample));
entries.add(e);
- sample.tmpEntry= e;
+ converter.sampleGetsEntry(sample, e);
}
- LineDataSet dataSet = new LineDataSet(entries, "Speed"); // add entries to dataset // TODO: localisatoin
+ LineDataSet dataSet = new LineDataSet(entries, converter.getName()); // add entries to dataset
dataSet.setColor(getThemePrimaryColor());
dataSet.setValueTextColor(getThemePrimaryColor());
dataSet.setDrawCircles(false);
@@ -220,11 +227,12 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
Description description= new Description();
- description.setText("min - km/h");
+ description.setText(converter.getDescription());
LineData lineData = new LineData(dataSet);
chart.setData(lineData);
- chart.setScaleEnabled(false);
+ chart.setScaleXEnabled(true);
+ chart.setScaleYEnabled(false);
chart.setDescription(description);
chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
@@ -232,7 +240,7 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
onNothingSelected();
Paint p= AndroidGraphicFactory.INSTANCE.createPaint();
p.setColor(Color.BLUE);
- highlightingCircle= new FixedPixelCircle(getSamplebyTime(e).toLatLong(), 10, p, null);
+ highlightingCircle= new FixedPixelCircle(findSample(converter, e).toLatLong(), 10, p, null);
map.addLayer(highlightingCircle);
}
@@ -248,9 +256,84 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
root.addView(chart, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getWindowManager().getDefaultDisplay().getWidth()*3/4));
}
- WorkoutSample getSamplebyTime(Entry entry){
+ interface SampleConverter{
+ void onCreate();
+ float getValue(WorkoutSample sample);
+ void sampleGetsEntry(WorkoutSample sample, Entry entry);
+ String getName();
+ String getDescription();
+ boolean compare(WorkoutSample sample, Entry entry);
+ }
+
+ void addHeightDiagram(){
+ addDiagram(new SampleConverter() {
+ @Override
+ public void onCreate() { }
+
+ @Override
+ public float getValue(WorkoutSample sample) {
+ return (float)UnitUtils.CHOSEN_SYSTEM.getDistanceFromMeters(sample.elevation);
+ }
+
+ @Override
+ public void sampleGetsEntry(WorkoutSample sample, Entry entry) {
+ sample.tmpHeightEntry= entry;
+ }
+
+ @Override
+ public String getName() {
+ return getString(R.string.height);
+ }
+
+ @Override
+ public String getDescription() {
+ return "min - " + UnitUtils.CHOSEN_SYSTEM.getShortDistanceUnit();
+ }
+
+ @Override
+ public boolean compare(WorkoutSample sample, Entry entry) {
+ return sample.tmpHeightEntry.equalTo(entry);
+ }
+ });
+ }
+
+ void addSpeedDiagram(){
+ addDiagram(new SampleConverter() {
+ @Override
+ public void onCreate() {
+ WorkoutManager.roundSpeedValues(samples);
+ }
+
+ @Override
+ public float getValue(WorkoutSample sample) {
+ return (float)UnitUtils.CHOSEN_SYSTEM.getSpeedFromMeterPerSecond(sample.tmpRoundedSpeed);
+ }
+
+ @Override
+ public void sampleGetsEntry(WorkoutSample sample, Entry entry) {
+ sample.tmpSpeedEntry= entry;
+ }
+
+ @Override
+ public String getName() {
+ return getString(R.string.workoutSpeed);
+ }
+
+ @Override
+ public String getDescription() {
+ return "min - " + UnitUtils.CHOSEN_SYSTEM.getSpeedUnit();
+ }
+
+ @Override
+ public boolean compare(WorkoutSample sample, Entry entry) {
+ return sample.tmpSpeedEntry.equalTo(entry);
+ }
+ });
+ }
+
+ WorkoutSample findSample(SampleConverter converter, Entry entry){
for(WorkoutSample sample : samples){
- if(sample.tmpEntry.equalTo(entry)){
+ if(converter.compare(sample, entry)){
return sample;
}
}
diff --git a/app/src/main/java/de/tadris/fitness/data/AppDatabase.java b/app/src/main/java/de/tadris/fitness/data/AppDatabase.java
index cd1fc75..73ba188 100644
--- a/app/src/main/java/de/tadris/fitness/data/AppDatabase.java
+++ b/app/src/main/java/de/tadris/fitness/data/AppDatabase.java
@@ -22,7 +22,7 @@ package de.tadris.fitness.data;
import androidx.room.Database;
import androidx.room.RoomDatabase;
-@Database(version = 1, entities = {Workout.class, WorkoutSample.class})
+@Database(version = 2, entities = {Workout.class, WorkoutSample.class})
public abstract class AppDatabase extends RoomDatabase {
public abstract WorkoutDao workoutDao();
}
diff --git a/app/src/main/java/de/tadris/fitness/data/Workout.java b/app/src/main/java/de/tadris/fitness/data/Workout.java
index 90141b2..159ac91 100644
--- a/app/src/main/java/de/tadris/fitness/data/Workout.java
+++ b/app/src/main/java/de/tadris/fitness/data/Workout.java
@@ -22,10 +22,13 @@ package de.tadris.fitness.data;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
import java.text.SimpleDateFormat;
import java.util.Date;
@Entity(tableName = "workout")
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Workout{
public static final String WORKOUT_TYPE_RUNNING= "running";
@@ -66,6 +69,11 @@ public class Workout{
public String workoutType;
+
+ public float ascent;
+
+ public float descent;
+
public int calorie;
public String toString(){
diff --git a/app/src/main/java/de/tadris/fitness/data/WorkoutManager.java b/app/src/main/java/de/tadris/fitness/data/WorkoutManager.java
index a98bb78..8aea9c6 100644
--- a/app/src/main/java/de/tadris/fitness/data/WorkoutManager.java
+++ b/app/src/main/java/de/tadris/fitness/data/WorkoutManager.java
@@ -20,6 +20,7 @@
package de.tadris.fitness.data;
import android.content.Context;
+import android.hardware.SensorManager;
import android.util.Log;
import java.util.List;
@@ -61,10 +62,14 @@ public class WorkoutManager {
// Setting workoutId in the samples
int i= 0;
double topSpeed= 0;
+ double elevationSum= 0; // Sum of elevation
+ double pressureSum= 0; // Sum of elevation
for(WorkoutSample sample : samples){
i++;
sample.id= workout.id + i;
sample.workoutId= workout.id;
+ elevationSum+= sample.elevation;
+ pressureSum+= sample.tmpPressure;
if(sample.speed > topSpeed){
topSpeed= sample.speed;
}
@@ -72,6 +77,36 @@ public class WorkoutManager {
workout.topSpeed= topSpeed;
+ // Calculating height data
+ boolean pressureDataAvailable= samples.get(0).tmpPressure != -1;
+ double avgElevation= elevationSum / samples.size();
+ double avgPressure= pressureSum / samples.size();
+
+ workout.ascent = 0;
+ workout.descent = 0;
+
+ for(i= 0; i < samples.size(); i++){
+ WorkoutSample sample= samples.get(i);
+
+ if(pressureDataAvailable){
+ // Altitude Difference to Average Elevation in meters
+ float altitude_difference =
+ SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, sample.tmpPressure) -
+ SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, (float) avgPressure);
+ sample.elevation= avgElevation + altitude_difference;
+ } // Else: use already set GPS elevation in WorkoutSample.elevation
+
+ if(i >= 1){
+ WorkoutSample lastSample= samples.get(i-1);
+ double diff= sample.elevation - lastSample.elevation;
+ if(diff > 0){
+ workout.ascent += diff;
+ }else{
+ workout.descent += Math.abs(diff);
+ }
+ }
+ }
+
// Saving workout and samples
db.workoutDao().insertWorkoutAndSamples(workout, samples.toArray(new WorkoutSample[0]));
@@ -91,4 +126,15 @@ public class WorkoutManager {
}
}
+ public static void calculateInclination(List samples){
+ samples.get(0).tmpInclination= 0;
+ for(int i= 1; i < samples.size(); i++){
+ WorkoutSample sample= samples.get(i);
+ WorkoutSample lastSample= samples.get(i);
+ double elevationDifference= sample.elevation - sample.elevation;
+ double distance= sample.toLatLong().sphericalDistance(lastSample.toLatLong());
+ sample.tmpInclination= (float)(elevationDifference*100/distance);
+ }
+ }
+
}
diff --git a/app/src/main/java/de/tadris/fitness/data/WorkoutSample.java b/app/src/main/java/de/tadris/fitness/data/WorkoutSample.java
index 79ae50a..00ea796 100644
--- a/app/src/main/java/de/tadris/fitness/data/WorkoutSample.java
+++ b/app/src/main/java/de/tadris/fitness/data/WorkoutSample.java
@@ -26,6 +26,7 @@ import androidx.room.Ignore;
import androidx.room.PrimaryKey;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.github.mikephil.charting.data.Entry;
import org.mapsforge.core.model.LatLong;
@@ -38,6 +39,7 @@ import static androidx.room.ForeignKey.CASCADE;
parentColumns = "id",
childColumns = "workout_id",
onDelete = CASCADE))
+@JsonIgnoreProperties(ignoreUnknown = true)
public class WorkoutSample{
@PrimaryKey
@@ -56,18 +58,28 @@ public class WorkoutSample{
public double elevation;
- public double relativeElevation;
-
public double speed;
@JsonIgnore
@Ignore
- public Entry tmpEntry;
+ public Entry tmpHeightEntry;
+
+ @JsonIgnore
+ @Ignore
+ public Entry tmpSpeedEntry;
@JsonIgnore
@Ignore
public double tmpRoundedSpeed;
+ @JsonIgnore
+ @Ignore
+ public float tmpPressure;
+
+ @JsonIgnore
+ @Ignore
+ public float tmpInclination;
+
public LatLong toLatLong(){
return new LatLong(lat, lon);
}
diff --git a/app/src/main/java/de/tadris/fitness/location/MyLocationOverlay.java b/app/src/main/java/de/tadris/fitness/location/MyLocationOverlay.java
deleted file mode 100644
index 7393240..0000000
--- a/app/src/main/java/de/tadris/fitness/location/MyLocationOverlay.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2019 Jannis Scheibe
- *
- * This file is part of FitoTrack
- *
- * FitoTrack is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * FitoTrack is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package de.tadris.fitness.location;
-
-import android.graphics.drawable.Drawable;
-
-import org.mapsforge.core.graphics.Canvas;
-import org.mapsforge.core.graphics.Paint;
-import org.mapsforge.core.graphics.Style;
-import org.mapsforge.core.model.BoundingBox;
-import org.mapsforge.core.model.LatLong;
-import org.mapsforge.core.model.Point;
-import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
-import org.mapsforge.map.layer.Layer;
-import org.mapsforge.map.layer.overlay.Circle;
-import org.mapsforge.map.layer.overlay.Marker;
-
-public class MyLocationOverlay extends Layer {
-
- private final Circle circle;
- private final Marker marker;
- private final LocationListener locationListener;
-
- private static Paint getDefaultFixedPixelCircleFill() {
- return getPaint(AndroidGraphicFactory.INSTANCE.createColor(255, 0, 0, 255), 0, Style.FILL);
- }
-
- private static Paint getDefaultOuterFixedPixelCircleFill(){
- return getPaint(AndroidGraphicFactory.INSTANCE.createColor(30, 30, 30, 255), 0, Style.FILL);
- }
-
- private static Paint getDefaultFixedPixelCircleStroke() {
- return getPaint(AndroidGraphicFactory.INSTANCE.createColor(255, 255, 255, 255), 7, Style.STROKE);
- }
-
- private static Paint getPaint(int color, int strokeWidth, Style style) {
- Paint paint = AndroidGraphicFactory.INSTANCE.createPaint();
- paint.setColor(color);
- paint.setStrokeWidth(strokeWidth);
- paint.setStyle(style);
- return paint;
- }
-
- public MyLocationOverlay(LocationListener locationListener, Drawable icon) {
- this.locationListener= locationListener;
- this.circle= new Circle(null, 0f, getDefaultFixedPixelCircleFill(), null);
- this.marker= new Marker(null, AndroidGraphicFactory.convertToBitmap(icon), 26, 26);
- }
-
- @Override
- public synchronized void draw(BoundingBox boundingBox, byte zoomLevel, Canvas canvas, Point topLeftPoint) {
- if (this.circle != null) {
- this.circle.draw(boundingBox, zoomLevel, canvas, topLeftPoint);
- }
- this.marker.draw(boundingBox, zoomLevel, canvas, topLeftPoint);
- }
-
- @Override
- protected void onAdd() {
- this.circle.setDisplayModel(this.displayModel);
- this.marker.setDisplayModel(this.displayModel);
- }
-
- @Override
- public void onDestroy() {
- this.marker.onDestroy();
- }
-
- public void setPosition(double latitude, double longitude, float accuracy) {
- synchronized (this) {
- LatLong latLong = new LatLong(latitude, longitude);
- this.marker.setLatLong(latLong);
- if (this.circle != null) {
- this.circle.setLatLong(latLong);
- this.circle.setRadius(accuracy);
- }
- requestRedraw();
- }
- }
-
-}
diff --git a/app/src/main/java/de/tadris/fitness/location/LocationListener.java b/app/src/main/java/de/tadris/fitness/recording/LocationListener.java
similarity index 99%
rename from app/src/main/java/de/tadris/fitness/location/LocationListener.java
rename to app/src/main/java/de/tadris/fitness/recording/LocationListener.java
index ede574f..3c0f15d 100644
--- a/app/src/main/java/de/tadris/fitness/location/LocationListener.java
+++ b/app/src/main/java/de/tadris/fitness/recording/LocationListener.java
@@ -18,7 +18,7 @@
* along with this program. If not, see .
*/
-package de.tadris.fitness.location;
+package de.tadris.fitness.recording;
import android.app.Notification;
import android.app.Service;
diff --git a/app/src/main/java/de/tadris/fitness/recording/PressureService.java b/app/src/main/java/de/tadris/fitness/recording/PressureService.java
new file mode 100644
index 0000000..cb84c53
--- /dev/null
+++ b/app/src/main/java/de/tadris/fitness/recording/PressureService.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019 Jannis Scheibe
+ *
+ * This file is part of FitoTrack
+ *
+ * FitoTrack is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FitoTrack is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package de.tadris.fitness.recording;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.IBinder;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import de.tadris.fitness.Instance;
+
+public class PressureService extends Service {
+
+ private static final String TAG = "PressureService";
+
+ private SensorManager sensorManager;
+ private Instance instance;
+ private Sensor pressureSensor;
+ private PressureListener pressureListener;
+
+ private class PressureListener implements SensorEventListener {
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ instance.lastPressure= event.values[0];
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) { }
+ }
+
+ @Override
+ public void onCreate() {
+ Log.d(TAG, "onCreate");
+ super.onCreate();
+ instance= Instance.getInstance(this);
+ sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
+
+ pressureSensor= sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
+
+ pressureListener= new PressureListener();
+
+ if (pressureSensor != null){
+ instance.pressureAvailable= true;
+ sensorManager.registerListener(pressureListener, pressureSensor, SensorManager.SENSOR_DELAY_NORMAL);
+ } else {
+ instance.pressureAvailable= false;
+ }
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.d(TAG, "onStartCommand");
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(TAG, "onDestroy");
+ super.onDestroy();
+ sensorManager.unregisterListener(pressureListener);
+ }
+
+ @Nullable @Override public IBinder onBind(Intent intent) { return null; }
+}
diff --git a/app/src/main/java/de/tadris/fitness/location/WorkoutRecorder.java b/app/src/main/java/de/tadris/fitness/recording/WorkoutRecorder.java
similarity index 96%
rename from app/src/main/java/de/tadris/fitness/location/WorkoutRecorder.java
rename to app/src/main/java/de/tadris/fitness/recording/WorkoutRecorder.java
index 9051404..a99bac7 100644
--- a/app/src/main/java/de/tadris/fitness/location/WorkoutRecorder.java
+++ b/app/src/main/java/de/tadris/fitness/recording/WorkoutRecorder.java
@@ -17,7 +17,7 @@
* along with this program. If not, see .
*/
-package de.tadris.fitness.location;
+package de.tadris.fitness.recording;
import android.content.Context;
import android.graphics.Color;
@@ -224,10 +224,14 @@ public class WorkoutRecorder implements LocationListener.LocationChangeListener
sample.lat= location.getLatitude();
sample.lon= location.getLongitude();
sample.elevation= location.getAltitude();
- sample.relativeElevation= 0.0;
sample.speed= location.getSpeed();
sample.relativeTime= location.getTime() - workout.start - pauseTime;
sample.absoluteTime= location.getTime();
+ if(Instance.getInstance(context).pressureAvailable){
+ sample.tmpPressure= Instance.getInstance(context).lastPressure;
+ }else{
+ sample.tmpPressure= -1;
+ }
synchronized (samples){
samples.add(sample);
}
@@ -282,6 +286,10 @@ public class WorkoutRecorder implements LocationListener.LocationChangeListener
workout.comment= comment;
}
+ public boolean isPaused(){
+ return state == RecordingState.PAUSED;
+ }
+
enum RecordingState{
IDLE, RUNNING, PAUSED, STOPPED
diff --git a/app/src/main/java/de/tadris/fitness/util/CalorieCalculator.java b/app/src/main/java/de/tadris/fitness/util/CalorieCalculator.java
index d6064aa..3a50270 100644
--- a/app/src/main/java/de/tadris/fitness/util/CalorieCalculator.java
+++ b/app/src/main/java/de/tadris/fitness/util/CalorieCalculator.java
@@ -48,14 +48,10 @@ public class CalorieCalculator {
*/
public static double getMET(Workout workout){
double speedInKmh= workout.avgSpeed * 3.6;
- if(workout.workoutType.equals(Workout.WORKOUT_TYPE_RUNNING)){
+ if(workout.workoutType.equals(Workout.WORKOUT_TYPE_RUNNING) || workout.workoutType.equals(Workout.WORKOUT_TYPE_HIKING)){
// This is a linear graph based on the website linked above
return Math.max(1.5, speedInKmh*1.117 - 2.1906);
}
- if(workout.workoutType.equals(Workout.WORKOUT_TYPE_HIKING)){
- // Use fixed MET because no more precise calculation was found
- return 6.0;
- }
if(workout.workoutType.equals(Workout.WORKOUT_TYPE_CYCLING)){
// This is a linear graph based on the website linked above
return Math.max(3, (speedInKmh-10) / 1.5);
diff --git a/app/src/main/java/de/tadris/fitness/util/export/Exporter.java b/app/src/main/java/de/tadris/fitness/util/export/Exporter.java
index ab887ac..d93fc0c 100644
--- a/app/src/main/java/de/tadris/fitness/util/export/Exporter.java
+++ b/app/src/main/java/de/tadris/fitness/util/export/Exporter.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.net.Uri;
import android.preference.PreferenceManager;
+import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File;
@@ -78,6 +79,7 @@ public class Exporter {
public static void importData(Context context, Uri input, ExportStatusListener listener) throws IOException{
listener.onStatusChanged(0, context.getString(R.string.loadingFile));
XmlMapper xmlMapper = new XmlMapper();
+ xmlMapper.configure(JsonParser.Feature.IGNORE_UNDEFINED, true);
FitoTrackDataContainer container = xmlMapper.readValue(context.getContentResolver().openInputStream(input), FitoTrackDataContainer.class);
if(container.version != 1){
@@ -89,6 +91,7 @@ public class Exporter {
.edit().clear()
.putInt("weight", container.settings.weight)
.putString("unitSystem", container.settings.preferredUnitSystem)
+ .putBoolean("firstStart", false)
.commit();
AppDatabase database= Instance.getInstance(context).db;
diff --git a/app/src/main/java/de/tadris/fitness/util/export/FitoTrackDataContainer.java b/app/src/main/java/de/tadris/fitness/util/export/FitoTrackDataContainer.java
index 2ad55bb..c1c9c0a 100644
--- a/app/src/main/java/de/tadris/fitness/util/export/FitoTrackDataContainer.java
+++ b/app/src/main/java/de/tadris/fitness/util/export/FitoTrackDataContainer.java
@@ -1,5 +1,25 @@
+/*
+ * Copyright (c) 2019 Jannis Scheibe
+ *
+ * This file is part of FitoTrack
+ *
+ * FitoTrack is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FitoTrack is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
package de.tadris.fitness.util.export;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.util.List;
@@ -8,6 +28,7 @@ import de.tadris.fitness.data.Workout;
import de.tadris.fitness.data.WorkoutSample;
@JacksonXmlRootElement(localName = "fito-track")
+@JsonIgnoreProperties(ignoreUnknown = true)
public class FitoTrackDataContainer {
int version;
diff --git a/app/src/main/java/de/tadris/fitness/util/unit/ImperialWithMeters.java b/app/src/main/java/de/tadris/fitness/util/unit/ImperialWithMeters.java
index caf47fa..406e767 100644
--- a/app/src/main/java/de/tadris/fitness/util/unit/ImperialWithMeters.java
+++ b/app/src/main/java/de/tadris/fitness/util/unit/ImperialWithMeters.java
@@ -11,13 +11,9 @@ public class ImperialWithMeters extends Imperial {
public double getDistanceFromMeters(double meters) {
return meters;
}
- @Override
- public String getLongDistanceUnit() {
- return "m";
- }
@Override
public String getShortDistanceUnit() {
- return "yd";
+ return "m";
}
}
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 26c3a5b..f4b1a5a 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -36,7 +36,7 @@
Der Datenimport ist fehlgeschlagen.
Als GPX-Datei exportieren
Daten exportieren
- "Es wird ein Backup von all deinen Einstallungen und "
+ Erstellt ein Backup von all deinen Einstellungen und deiner Workoutdaten
Exportieren
Fertig
GPS
@@ -88,4 +88,10 @@
Gehen
Hinzufügen
Workouts
+ Aktivieren
+ Höhe
+ GPS deaktiviert
+ Bitte aktiviere GPS, damit dein Workout aufgezeichnet werden kann.
+ Aufstieg
+ Abstieg
\ 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 c43104d..c3dc599 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -63,6 +63,12 @@
Total Energy
Energy Consumption
+ Ascent
+ Descent
+
+ Height
+
+
Running
Walking
Jogging
@@ -72,6 +78,10 @@
Record Workout
+ GPS disabled
+ Please enable GPS for tracking your workout.
+ Enable
+
Comment
Enter Comment
Okay
diff --git a/app/src/test/java/de/tadris/fitness/CalorieCalculatorTest.java b/app/src/test/java/de/tadris/fitness/CalorieCalculatorTest.java
new file mode 100644
index 0000000..4c40451
--- /dev/null
+++ b/app/src/test/java/de/tadris/fitness/CalorieCalculatorTest.java
@@ -0,0 +1,22 @@
+package de.tadris.fitness;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import de.tadris.fitness.data.Workout;
+import de.tadris.fitness.util.CalorieCalculator;
+
+public class CalorieCalculatorTest {
+
+ @Test
+ public void testCalculation(){
+ Workout workout= new Workout();
+ workout.avgSpeed= 2.7d;
+ workout.workoutType= Workout.WORKOUT_TYPE_RUNNING;
+ workout.duration= 1000L * 60 * 10;
+ int calorie= CalorieCalculator.calculateCalories(workout, 80);
+ System.out.println("Calories: " + calorie);
+ Assert.assertEquals(120, calorie, 50);
+ }
+
+}
diff --git a/app/src/test/java/de/tadris/fitness/ExampleUnitTest.java b/app/src/test/java/de/tadris/fitness/ExampleUnitTest.java
deleted file mode 100644
index b12eb70..0000000
--- a/app/src/test/java/de/tadris/fitness/ExampleUnitTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2019 Jannis Scheibe
- *
- * This file is part of FitoTrack
- *
- * FitoTrack is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * FitoTrack is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package de.tadris.fitness;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see Testing documentation
- */
-public class ExampleUnitTest {
- @Test
- public void addition_isCorrect() {
- assertEquals(4, 2 + 2);
- }
-}
\ No newline at end of file
diff --git a/metadata/en-US/changelogs/110.txt b/metadata/en-US/changelogs/110.txt
new file mode 100644
index 0000000..86a16a4
--- /dev/null
+++ b/metadata/en-US/changelogs/110.txt
@@ -0,0 +1,8 @@
+New:
+- Height measurement via GPS and pressure sensor
+- Show height diagram
+- Show dialog if GPS is disabled
+
+Fix:
+- Back-Button in Settings crashes on earlier Android versions (#20)
+- Fix Unit system "Imperial with meters"
\ No newline at end of file