diff --git a/app/build.gradle b/app/build.gradle
index 6368865..7d03c09 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -35,8 +35,8 @@ android {
applicationId "de.tadris.fitness"
minSdkVersion 21
targetSdkVersion 28
- versionCode 111
- versionName "1.1.1"
+ versionCode 200
+ versionName "2.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a8d2f92..2bfbb15 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,13 +22,14 @@
xmlns:tools="http://schemas.android.com/tools"
package="de.tadris.fitness">
-
+
+
-
+
+
+
@@ -56,15 +62,17 @@
+
+ android:exported="false"
+ android:grantUriPermissions="true">
+
diff --git a/app/src/main/java/de/tadris/fitness/activity/ListWorkoutsActivity.java b/app/src/main/java/de/tadris/fitness/activity/ListWorkoutsActivity.java
index ac9134c..17c1c1c 100644
--- a/app/src/main/java/de/tadris/fitness/activity/ListWorkoutsActivity.java
+++ b/app/src/main/java/de/tadris/fitness/activity/ListWorkoutsActivity.java
@@ -37,6 +37,7 @@ import com.github.clans.fab.FloatingActionMenu;
import de.tadris.fitness.Instance;
import de.tadris.fitness.R;
import de.tadris.fitness.data.Workout;
+import de.tadris.fitness.util.DialogUtils;
import de.tadris.fitness.view.WorkoutAdapter;
public class ListWorkoutsActivity extends Activity implements WorkoutAdapter.WorkoutAdapterListener {
@@ -73,8 +74,13 @@ public class ListWorkoutsActivity extends Activity implements WorkoutAdapter.Wor
findViewById(R.id.workoutListRecordHiking) .setOnClickListener(v -> startRecording(Workout.WORKOUT_TYPE_HIKING));
findViewById(R.id.workoutListRecordCycling).setOnClickListener(v -> startRecording(Workout.WORKOUT_TYPE_CYCLING));
+ loadData();
+
checkFirstStart();
+ adapter= new WorkoutAdapter(workouts, this);
+ listView.setAdapter(adapter);
+
}
private void checkFirstStart(){
@@ -101,9 +107,8 @@ public class ListWorkoutsActivity extends Activity implements WorkoutAdapter.Wor
public void onResume() {
super.onResume();
- workouts= Instance.getInstance(this).db.workoutDao().getWorkouts();
- adapter= new WorkoutAdapter(workouts, this);
- listView.setAdapter(adapter);
+ loadData();
+ adapter.notifyDataSetChanged();
}
@Override
@@ -112,6 +117,19 @@ public class ListWorkoutsActivity extends Activity implements WorkoutAdapter.Wor
startActivity(new Intent(this, ShowWorkoutActivity.class));
}
+ @Override
+ public void onItemLongClick(int pos, Workout workout) {
+ DialogUtils.showDeleteWorkoutDialog(this, () -> {
+ Instance.getInstance(ListWorkoutsActivity.this).db.workoutDao().deleteWorkout(workout);
+ loadData();
+ adapter.notifyItemRemoved(pos);
+ });
+ }
+
+ private void loadData(){
+ workouts= Instance.getInstance(this).db.workoutDao().getWorkouts();
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
@@ -131,6 +149,4 @@ public class ListWorkoutsActivity extends Activity implements WorkoutAdapter.Wor
return super.onOptionsItemSelected(item);
}
-
-
}
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 12bd640..fa4d3f4 100644
--- a/app/src/main/java/de/tadris/fitness/activity/RecordWorkoutActivity.java
+++ b/app/src/main/java/de/tadris/fitness/activity/RecordWorkoutActivity.java
@@ -20,6 +20,7 @@
package de.tadris.fitness.activity;
import android.Manifest;
+import android.animation.Animator;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
@@ -32,6 +33,7 @@ import android.os.Handler;
import android.os.PowerManager;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
@@ -71,6 +73,8 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
List latLongList= new ArrayList<>();
InfoViewHolder[] infoViews= new InfoViewHolder[4];
TextView timeView, gpsStatusView;
+ View waitingForGPSOverlay;
+ boolean gpsFound= false;
boolean isResumed= false;
private Handler mHandler= new Handler();
PowerManager.WakeLock wakeLock;
@@ -89,6 +93,8 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
setupMap();
((ViewGroup)findViewById(R.id.recordMapViewrRoot)).addView(mapView);
+ waitingForGPSOverlay= findViewById(R.id.recorderWaitingOverlay);
+ waitingForGPSOverlay.setVisibility(View.VISIBLE);
checkPermissions();
@@ -119,6 +125,20 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
wakeLock.acquire(1000*60*120);
}
+ private void hideWaitOverlay(){
+ waitingForGPSOverlay.clearAnimation();
+ waitingForGPSOverlay.animate().alpha(0f).setDuration(1000).setListener(new Animator.AnimatorListener() {
+ @Override public void onAnimationStart(Animator animator) { }
+ @Override public void onAnimationCancel(Animator animator) { }
+ @Override public void onAnimationRepeat(Animator animator) { }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ waitingForGPSOverlay.setVisibility(View.GONE);
+ }
+ }).start();
+ }
+
private void setupMap(){
this.mapView= new MapView(this);
TileSources.Purpose purpose;
@@ -336,7 +356,13 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
@Override
public void onGPSStateChanged(WorkoutRecorder.GpsState oldState, WorkoutRecorder.GpsState state) {
- mHandler.post(() -> gpsStatusView.setTextColor(state.color));
+ mHandler.post(() -> {
+ gpsStatusView.setTextColor(state.color);
+ if(!gpsFound && (state != WorkoutRecorder.GpsState.SIGNAL_LOST)){
+ gpsFound= true;
+ hideWaitOverlay();
+ }
+ });
}
public static class InfoViewHolder{
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 d36f871..567789d 100644
--- a/app/src/main/java/de/tadris/fitness/activity/SettingsActivity.java
+++ b/app/src/main/java/de/tadris/fitness/activity/SettingsActivity.java
@@ -22,7 +22,6 @@ package de.tadris.fitness.activity;
import android.Manifest;
import android.app.ActionBar;
import android.app.AlertDialog;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
@@ -44,7 +43,6 @@ import android.widget.NumberPicker;
import androidx.annotation.StringRes;
import androidx.core.app.ActivityCompat;
-import androidx.core.app.NavUtils;
import androidx.core.content.FileProvider;
import java.io.BufferedInputStream;
@@ -53,7 +51,6 @@ import java.io.FileNotFoundException;
import de.tadris.fitness.R;
import de.tadris.fitness.util.export.Exporter;
-import de.tadris.fitness.util.gpx.GpxExporter;
import de.tadris.fitness.util.unit.UnitUtils;
import de.tadris.fitness.view.ProgressDialogController;
@@ -160,6 +157,7 @@ public class SettingsActivity extends PreferenceActivity {
addPreferencesFromResource(R.xml.preferences_main);
bindPreferenceSummaryToValue(findPreference("unitSystem"));
+ bindPreferenceSummaryToValue(findPreference("mapStyle"));
findPreference("weight").setOnPreferenceClickListener(preference -> showWeightPicker());
findPreference("import").setOnPreferenceClickListener(preference -> showImportDialog());
@@ -259,10 +257,8 @@ public class SettingsActivity extends PreferenceActivity {
Exporter.importData(getBaseContext(), uri,
(progress, action) -> mHandler.post(() -> dialogController.setProgress(progress, action)));
- mHandler.post(() -> {
- // DO on backup finished
- dialogController.cancel();
- });
+ // DO on backup finished
+ mHandler.post(dialogController::cancel);
}catch (Exception e){
e.printStackTrace();
mHandler.post(() -> {
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 86e8cb3..0036a13 100644
--- a/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java
+++ b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java
@@ -20,88 +20,44 @@
package de.tadris.fitness.activity;
import android.app.AlertDialog;
-import android.content.res.Resources;
-import android.graphics.Color;
+import android.content.Intent;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import androidx.core.content.FileProvider;
-import com.github.mikephil.charting.charts.LineChart;
-import com.github.mikephil.charting.components.Description;
-import com.github.mikephil.charting.data.Entry;
-import com.github.mikephil.charting.data.LineData;
-import com.github.mikephil.charting.data.LineDataSet;
-import com.github.mikephil.charting.highlight.Highlight;
-import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
-
-import org.mapsforge.core.graphics.Paint;
-import org.mapsforge.core.model.BoundingBox;
-import org.mapsforge.core.model.MapPosition;
-import org.mapsforge.core.util.LatLongUtils;
-import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
-import org.mapsforge.map.android.view.MapView;
-import org.mapsforge.map.layer.download.TileDownloadLayer;
-import org.mapsforge.map.layer.overlay.FixedPixelCircle;
-
import java.io.File;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Date;
-import java.util.List;
import de.tadris.fitness.Instance;
import de.tadris.fitness.R;
-import de.tadris.fitness.data.Workout;
-import de.tadris.fitness.data.WorkoutManager;
-import de.tadris.fitness.data.WorkoutSample;
-import de.tadris.fitness.map.MapManager;
-import de.tadris.fitness.map.WorkoutLayer;
-import de.tadris.fitness.map.tilesource.TileSources;
-import de.tadris.fitness.util.ThemeManager;
-import de.tadris.fitness.util.WorkoutTypeCalculator;
+import de.tadris.fitness.util.DialogUtils;
import de.tadris.fitness.util.gpx.GpxExporter;
import de.tadris.fitness.util.unit.UnitUtils;
import de.tadris.fitness.view.ProgressDialogController;
-public class ShowWorkoutActivity extends FitoTrackActivity {
- static Workout selectedWorkout;
+public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.WorkoutDeleter {
- List samples;
- Workout workout;
- ViewGroup root;
- Resources.Theme theme;
- MapView map;
- TileDownloadLayer downloadLayer;
- FixedPixelCircle highlightingCircle;
- Handler mHandler= new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- workout= selectedWorkout;
- samples= Arrays.asList(Instance.getInstance(this).db.workoutDao().getAllSamplesOfWorkout(workout.id));
- setTheme(ThemeManager.getThemeByWorkout(workout));
+ initBeforeContent();
+
setContentView(R.layout.activity_show_workout);
-
- getActionBar().setDisplayHomeAsUpEnabled(true);
- setTitle(WorkoutTypeCalculator.getType(workout));
-
- theme= getTheme();
-
root= findViewById(R.id.showWorkoutRoot);
+ initAfterContent();
+
addText(getString(R.string.comment) + ": " + workout.comment).setOnClickListener(v -> {
TextView textView= (TextView)v;
openEditCommentDialog(textView);
@@ -120,6 +76,9 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
addMap();
+ map.setClickable(false);
+ mapRoot.setOnClickListener(v -> startActivity(new Intent(ShowWorkoutActivity.this, ShowWorkoutMapActivity.class)));
+
addTitle(getString(R.string.workoutSpeed));
addKeyValue(getString(R.string.workoutAvgSpeed), UnitUtils.getSpeed(workout.avgSpeed),
@@ -127,6 +86,8 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
addSpeedDiagram();
+ speedDiagram.setOnClickListener(v -> startDiagramActivity(ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE_SPEED));
+
addTitle(getString(R.string.workoutBurnedEnergy));
addKeyValue(getString(R.string.workoutTotalEnergy), workout.calorie + " kcal",
getString(R.string.workoutEnergyConsumption), UnitUtils.getRelativeEnergyConsumption((double)workout.calorie / ((double)workout.length / 1000)));
@@ -138,9 +99,17 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
addHeightDiagram();
+ heightDiagram.setOnClickListener(v -> startDiagramActivity(ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE_HEIGHT));
+
}
+ void startDiagramActivity(String diagramType){
+ ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE= diagramType;
+ startActivity(new Intent(ShowWorkoutActivity.this, ShowWorkoutMapDiagramActivity.class));
+ }
+
+
void openEditCommentDialog(final TextView change){
final EditText editText= new EditText(this);
editText.setText(workout.comment);
@@ -206,186 +175,6 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
root.addView(v);
}
- void addDiagram(SampleConverter converter){
- LineChart chart= new LineChart(this);
-
- 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, converter.getValue(sample));
- entries.add(e);
- converter.sampleGetsEntry(sample, e);
- }
-
- LineDataSet dataSet = new LineDataSet(entries, converter.getName()); // add entries to dataset
- dataSet.setColor(getThemePrimaryColor());
- dataSet.setValueTextColor(getThemePrimaryColor());
- dataSet.setDrawCircles(false);
- dataSet.setLineWidth(4);
- dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
-
- Description description= new Description();
- description.setText(converter.getDescription());
-
- LineData lineData = new LineData(dataSet);
- chart.setData(lineData);
- chart.setScaleXEnabled(true);
- chart.setScaleYEnabled(false);
- chart.setDescription(description);
- chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
- @Override
- public void onValueSelected(Entry e, Highlight h) {
- onNothingSelected();
- Paint p= AndroidGraphicFactory.INSTANCE.createPaint();
- p.setColor(Color.BLUE);
- highlightingCircle= new FixedPixelCircle(findSample(converter, e).toLatLong(), 10, p, null);
- map.addLayer(highlightingCircle);
- }
-
- @Override
- public void onNothingSelected() {
- if(highlightingCircle != null){
- map.getLayerManager().getLayers().remove(highlightingCircle);
- }
- }
- });
- chart.invalidate();
-
- root.addView(chart, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getWindowManager().getDefaultDisplay().getWidth()*3/4));
- }
-
- 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(converter.compare(sample, entry)){
- return sample;
- }
- }
- return null;
- }
-
- void addMap(){
- map= new MapView(this);
- downloadLayer= MapManager.setupMap(map, TileSources.Purpose.DEFAULT);
-
- WorkoutLayer workoutLayer= new WorkoutLayer(samples, getThemePrimaryColor());
- map.addLayer(workoutLayer);
-
- final BoundingBox bounds= new BoundingBox(workoutLayer.getLatLongs()).extendMeters(50);
- mHandler.postDelayed(() -> {
- map.getModel().mapViewPosition.setMapPosition(new MapPosition(bounds.getCenterPoint(),
- (LatLongUtils.zoomForBounds(map.getDimension(), bounds, map.getModel().displayModel.getTileSize()))));
- map.animate().alpha(1f).setDuration(1000).start();
- }, 1000);
-
- map.getModel().mapViewPosition.setMapLimit(bounds);
-
-
- root.addView(map, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getWindowManager().getDefaultDisplay().getWidth()*3/4));
- map.setAlpha(0);
-
-
- Paint pGreen= AndroidGraphicFactory.INSTANCE.createPaint();
- pGreen.setColor(Color.GREEN);
- map.addLayer(new FixedPixelCircle(samples.get(0).toLatLong(), 20, pGreen, null));
- Paint pRed= AndroidGraphicFactory.INSTANCE.createPaint();
- pRed.setColor(Color.RED);
- map.addLayer(new FixedPixelCircle(samples.get(samples.size()-1).toLatLong(), 20, pRed, null));
- }
-
- @Override
- protected void onDestroy() {
- map.destroyAll();
- AndroidGraphicFactory.clearResourceMemoryCache();
- super.onDestroy();
- }
-
- @Override
- public void onPause(){
- super.onPause();
- downloadLayer.onPause();
- }
-
- public void onResume(){
- super.onResume();
- downloadLayer.onResume();
- }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
@@ -394,17 +183,13 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
return true;
}
- private void deleteWorkout(){
+ public void deleteWorkout(){
Instance.getInstance(this).db.workoutDao().deleteWorkout(workout);
finish();
}
private void showDeleteDialog(){
- new AlertDialog.Builder(this).setTitle(R.string.deleteWorkout)
- .setMessage(R.string.deleteWorkoutMessage)
- .setNegativeButton(R.string.cancel, null)
- .setPositiveButton(R.string.delete, (dialog, which) -> deleteWorkout())
- .create().show();
+ DialogUtils.showDeleteWorkoutDialog(this, this);
}
private void exportToGpx(){
@@ -438,9 +223,6 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
case R.id.actionExportGpx:
exportToGpx();
return true;
- case android.R.id.home:
- finish();
- return true;
}
return super.onOptionsItemSelected(item);
}
diff --git a/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutMapActivity.java b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutMapActivity.java
new file mode 100644
index 0000000..b801c3c
--- /dev/null
+++ b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutMapActivity.java
@@ -0,0 +1,46 @@
+/*
+ * 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.activity;
+
+import android.os.Bundle;
+
+import de.tadris.fitness.R;
+
+public class ShowWorkoutMapActivity extends WorkoutActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ initBeforeContent();
+
+ setContentView(R.layout.activity_show_workout_map);
+ root= findViewById(R.id.showWorkoutMapParent);
+
+ initAfterContent();
+
+ fullScreenItems = true;
+ addMap();
+
+ map.setClickable(true);
+ }
+
+
+}
diff --git a/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutMapDiagramActivity.java b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutMapDiagramActivity.java
new file mode 100644
index 0000000..74915c5
--- /dev/null
+++ b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutMapDiagramActivity.java
@@ -0,0 +1,57 @@
+/*
+ * 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.activity;
+
+import android.os.Bundle;
+
+import de.tadris.fitness.R;
+
+public class ShowWorkoutMapDiagramActivity extends WorkoutActivity {
+
+ public static final String DIAGRAM_TYPE_HEIGHT= "height";
+ public static final String DIAGRAM_TYPE_SPEED= "speed";
+
+ static String DIAGRAM_TYPE;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ initBeforeContent();
+
+ setContentView(R.layout.activity_show_workout_map_diagram);
+ root= findViewById(R.id.showWorkoutMapParent);
+
+ initAfterContent();
+
+ fullScreenItems = true;
+ addMap();
+ map.setClickable(true);
+
+ diagramsInteractive= true;
+ root= findViewById(R.id.showWorkoutDiagramParent);
+ switch (DIAGRAM_TYPE){
+ case DIAGRAM_TYPE_HEIGHT: addHeightDiagram(); break;
+ case DIAGRAM_TYPE_SPEED: addSpeedDiagram(); break;
+ }
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/tadris/fitness/activity/WorkoutActivity.java b/app/src/main/java/de/tadris/fitness/activity/WorkoutActivity.java
new file mode 100644
index 0000000..4914a1d
--- /dev/null
+++ b/app/src/main/java/de/tadris/fitness/activity/WorkoutActivity.java
@@ -0,0 +1,316 @@
+/*
+ * 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.activity;
+
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.os.Handler;
+import android.view.MenuItem;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.github.mikephil.charting.charts.LineChart;
+import com.github.mikephil.charting.components.Description;
+import com.github.mikephil.charting.data.Entry;
+import com.github.mikephil.charting.data.LineData;
+import com.github.mikephil.charting.data.LineDataSet;
+import com.github.mikephil.charting.highlight.Highlight;
+import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
+
+import org.mapsforge.core.graphics.Paint;
+import org.mapsforge.core.model.BoundingBox;
+import org.mapsforge.core.model.MapPosition;
+import org.mapsforge.core.util.LatLongUtils;
+import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
+import org.mapsforge.map.android.view.MapView;
+import org.mapsforge.map.layer.download.TileDownloadLayer;
+import org.mapsforge.map.layer.overlay.FixedPixelCircle;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import de.tadris.fitness.Instance;
+import de.tadris.fitness.R;
+import de.tadris.fitness.data.Workout;
+import de.tadris.fitness.data.WorkoutManager;
+import de.tadris.fitness.data.WorkoutSample;
+import de.tadris.fitness.map.MapManager;
+import de.tadris.fitness.map.WorkoutLayer;
+import de.tadris.fitness.map.tilesource.TileSources;
+import de.tadris.fitness.util.ThemeManager;
+import de.tadris.fitness.util.WorkoutTypeCalculator;
+import de.tadris.fitness.util.unit.UnitUtils;
+
+public abstract class WorkoutActivity extends FitoTrackActivity {
+
+ public static Workout selectedWorkout;
+
+ protected List samples;
+ protected Workout workout;
+ protected ViewGroup root;
+ protected Resources.Theme theme;
+ protected MapView map;
+ protected TileDownloadLayer downloadLayer;
+ protected FixedPixelCircle highlightingCircle;
+ protected Handler mHandler= new Handler();
+
+ protected LineChart speedDiagram, heightDiagram;
+
+ protected void initBeforeContent(){
+ workout= selectedWorkout;
+ samples= Arrays.asList(Instance.getInstance(this).db.workoutDao().getAllSamplesOfWorkout(workout.id));
+ setTheme(ThemeManager.getThemeByWorkout(workout));
+ }
+
+ protected void initAfterContent(){
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ setTitle(WorkoutTypeCalculator.getType(workout));
+
+ theme= getTheme();
+ }
+
+ void addDiagram(SampleConverter converter){
+ root.addView(getDiagram(converter), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, fullScreenItems ? ViewGroup.LayoutParams.MATCH_PARENT : getWindowManager().getDefaultDisplay().getWidth()*3/4));
+ }
+
+ protected boolean diagramsInteractive= false;
+
+ LineChart getDiagram(SampleConverter converter){
+ LineChart chart= new LineChart(this);
+
+ 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, converter.getValue(sample));
+ entries.add(e);
+ converter.sampleGetsEntry(sample, e);
+ }
+
+ LineDataSet dataSet = new LineDataSet(entries, converter.getName()); // add entries to dataset
+ dataSet.setColor(getThemePrimaryColor());
+ dataSet.setValueTextColor(getThemePrimaryColor());
+ dataSet.setDrawCircles(false);
+ dataSet.setLineWidth(4);
+ dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
+
+ Description description= new Description();
+ description.setText(converter.getDescription());
+
+ LineData lineData = new LineData(dataSet);
+ chart.setData(lineData);
+ chart.setScaleXEnabled(diagramsInteractive);
+ chart.setScaleYEnabled(false);
+ chart.setDescription(description);
+ if(diagramsInteractive){
+ chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
+ @Override
+ public void onValueSelected(Entry e, Highlight h) {
+ onNothingSelected();
+ Paint p= AndroidGraphicFactory.INSTANCE.createPaint();
+ p.setColor(0xff693cff);
+ highlightingCircle= new FixedPixelCircle(findSample(converter, e).toLatLong(), 20, p, null);
+ map.addLayer(highlightingCircle);
+ }
+
+ @Override
+ public void onNothingSelected() {
+ if(highlightingCircle != null){
+ map.getLayerManager().getLayers().remove(highlightingCircle);
+ }
+ }
+ });
+ }
+ chart.invalidate();
+
+ converter.afterAdd(chart);
+
+ return chart;
+ }
+
+ 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 afterAdd(LineChart chart);
+ }
+
+ WorkoutSample findSample(SampleConverter converter, Entry entry){
+ for(WorkoutSample sample : samples){
+ if(converter.compare(sample, entry)){
+ return sample;
+ }
+ }
+ return null;
+ }
+
+ 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);
+ }
+
+ @Override
+ public void afterAdd(LineChart chart) {
+ heightDiagram= chart;
+ }
+ });
+ }
+
+ 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);
+ }
+
+ @Override
+ public void afterAdd(LineChart chart) {
+ speedDiagram= chart;
+ }
+ });
+ }
+
+ protected boolean fullScreenItems = false;
+ protected LinearLayout mapRoot;
+
+ void addMap(){
+ map= new MapView(this);
+ downloadLayer= MapManager.setupMap(map, TileSources.Purpose.DEFAULT);
+
+ WorkoutLayer workoutLayer= new WorkoutLayer(samples, getThemePrimaryColor());
+ map.addLayer(workoutLayer);
+
+ final BoundingBox bounds= new BoundingBox(workoutLayer.getLatLongs()).extendMeters(50);
+ mHandler.postDelayed(() -> {
+ map.getModel().mapViewPosition.setMapPosition(new MapPosition(bounds.getCenterPoint(),
+ (LatLongUtils.zoomForBounds(map.getDimension(), bounds, map.getModel().displayModel.getTileSize()))));
+ map.animate().alpha(1f).setDuration(1000).start();
+ }, 1000);
+
+ map.getModel().mapViewPosition.setMapLimit(bounds);
+
+ mapRoot= new LinearLayout(this);
+ mapRoot.setOrientation(LinearLayout.VERTICAL);
+ mapRoot.addView(map);
+
+ root.addView(mapRoot, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, fullScreenItems ? ViewGroup.LayoutParams.MATCH_PARENT : getMapHeight()));
+ map.setAlpha(0);
+
+
+ Paint pGreen= AndroidGraphicFactory.INSTANCE.createPaint();
+ pGreen.setColor(Color.GREEN);
+ map.addLayer(new FixedPixelCircle(samples.get(0).toLatLong(), 20, pGreen, null));
+ Paint pRed= AndroidGraphicFactory.INSTANCE.createPaint();
+ pRed.setColor(Color.RED);
+
+ map.addLayer(new FixedPixelCircle(samples.get(samples.size()-1).toLatLong(), 20, pRed, null));
+
+ map.setClickable(false);
+
+ }
+
+ int getMapHeight(){
+ return getWindowManager().getDefaultDisplay().getWidth()*3/4;
+ }
+
+ @Override
+ protected void onDestroy() {
+ map.destroyAll();
+ AndroidGraphicFactory.clearResourceMemoryCache();
+ super.onDestroy();
+ }
+
+ @Override
+ public void onPause(){
+ super.onPause();
+ downloadLayer.onPause();
+ }
+
+ public void onResume(){
+ super.onResume();
+ downloadLayer.onResume();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if (id == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+}
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 831ac6b..385be76 100644
--- a/app/src/main/java/de/tadris/fitness/data/UserPreferences.java
+++ b/app/src/main/java/de/tadris/fitness/data/UserPreferences.java
@@ -35,4 +35,8 @@ public class UserPreferences {
return preferences.getInt("weight", 80);
}
+ 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 5c700f3..caa54c7 100644
--- a/app/src/main/java/de/tadris/fitness/map/MapManager.java
+++ b/app/src/main/java/de/tadris/fitness/map/MapManager.java
@@ -26,21 +26,24 @@ import org.mapsforge.map.android.view.MapView;
import org.mapsforge.map.layer.cache.TileCache;
import org.mapsforge.map.layer.download.TileDownloadLayer;
+import de.tadris.fitness.Instance;
import de.tadris.fitness.map.tilesource.FitoTrackTileSource;
+import de.tadris.fitness.map.tilesource.HumanitarianTileSource;
import de.tadris.fitness.map.tilesource.MapnikTileSource;
+import de.tadris.fitness.map.tilesource.ThunderforestTileSource;
import de.tadris.fitness.map.tilesource.TileSources;
public class MapManager {
public static TileDownloadLayer setupMap(MapView mapView, TileSources.Purpose purpose){
FitoTrackTileSource tileSource;
- switch (purpose){
- /*case OUTDOOR: tileSource= ThunderforestTileSource.OUTDOORS; break;
- case CYCLING: tileSource= ThunderforestTileSource.CYLE_MAP; break;*/
- case DEFAULT:
- default:
- tileSource= MapnikTileSource.INSTANCE; break;
+ String chosenTileLayer= Instance.getInstance(mapView.getContext()).userPreferences.getMapStyle();
+ switch (chosenTileLayer){
+ case "osm.humanitarian": tileSource= HumanitarianTileSource.INSTANCE; break;
+ case "thunderforest.outdoors": tileSource= ThunderforestTileSource.OUTDOORS; break;
+ case "thunderforest.cycle": tileSource= ThunderforestTileSource.CYLE_MAP; break;
+ default: tileSource= MapnikTileSource.INSTANCE; break; // Inclusive "osm.mapnik"
}
tileSource.setUserAgent("mapsforge-android");
diff --git a/app/src/main/java/de/tadris/fitness/util/DialogUtils.java b/app/src/main/java/de/tadris/fitness/util/DialogUtils.java
new file mode 100644
index 0000000..9aa8d53
--- /dev/null
+++ b/app/src/main/java/de/tadris/fitness/util/DialogUtils.java
@@ -0,0 +1,22 @@
+package de.tadris.fitness.util;
+
+import android.app.AlertDialog;
+import android.content.Context;
+
+import de.tadris.fitness.R;
+
+public class DialogUtils {
+
+ public static void showDeleteWorkoutDialog(Context context, WorkoutDeleter deleter){
+ new AlertDialog.Builder(context).setTitle(R.string.deleteWorkout)
+ .setMessage(R.string.deleteWorkoutMessage)
+ .setNegativeButton(R.string.cancel, null)
+ .setPositiveButton(R.string.delete, (dialog, which) -> deleter.deleteWorkout())
+ .create().show();
+ }
+
+ public interface WorkoutDeleter{
+ void deleteWorkout();
+ }
+
+}
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 d93fc0c..c2e165b 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
@@ -29,7 +29,6 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -59,6 +58,7 @@ public class Exporter {
listener.onStatusChanged(10, context.getString(R.string.preferences));
FitoTrackSettings settings= new FitoTrackSettings();
settings.weight= preferences.getUserWeight();
+ settings.mapStyle= preferences.getMapStyle();
settings.preferredUnitSystem= String.valueOf(UnitUtils.CHOSEN_SYSTEM.getId());
container.settings= settings;
@@ -76,14 +76,14 @@ public class Exporter {
}
@SuppressLint("ApplySharedPref")
- public static void importData(Context context, Uri input, ExportStatusListener listener) throws IOException{
+ public static void importData(Context context, Uri input, ExportStatusListener listener) throws IOException, UnsupportedVersionException {
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){
- throw new UnsupportedEncodingException("Version Code" + container.version + " is unsupported!");
+ throw new UnsupportedVersionException("Version Code" + container.version + " is unsupported!");
}
listener.onStatusChanged(40, context.getString(R.string.preferences));
@@ -91,25 +91,29 @@ public class Exporter {
.edit().clear()
.putInt("weight", container.settings.weight)
.putString("unitSystem", container.settings.preferredUnitSystem)
- .putBoolean("firstStart", false)
+ .putBoolean("firstStart", false).putString("mapStyle", container.settings.mapStyle)
.commit();
AppDatabase database= Instance.getInstance(context).db;
- database.clearAllTables();
- listener.onStatusChanged(60, context.getString(R.string.workouts));
- if(container.workouts != null){
- for(Workout workout : container.workouts){
- database.workoutDao().insertWorkout(workout);
- }
- }
+ database.runInTransaction(() -> {
+ database.clearAllTables();
- listener.onStatusChanged(80, context.getString(R.string.locationData));
- if(container.samples != null){
- for(WorkoutSample sample : container.samples){
- database.workoutDao().insertSample(sample);
+ listener.onStatusChanged(60, context.getString(R.string.workouts));
+ if(container.workouts != null){
+ for(Workout workout : container.workouts){
+ database.workoutDao().insertWorkout(workout);
+ }
}
- }
+
+ listener.onStatusChanged(80, context.getString(R.string.locationData));
+ if(container.samples != null){
+ for(WorkoutSample sample : container.samples){
+ database.workoutDao().insertSample(sample);
+ }
+ }
+ });
+
listener.onStatusChanged(100, context.getString(R.string.finished));
}
diff --git a/app/src/main/java/de/tadris/fitness/util/export/FitoTrackSettings.java b/app/src/main/java/de/tadris/fitness/util/export/FitoTrackSettings.java
index 645b9af..7d6527c 100644
--- a/app/src/main/java/de/tadris/fitness/util/export/FitoTrackSettings.java
+++ b/app/src/main/java/de/tadris/fitness/util/export/FitoTrackSettings.java
@@ -1,15 +1,36 @@
+/*
+ * 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;
public class FitoTrackSettings {
String preferredUnitSystem;
int weight;
+ String mapStyle;
public FitoTrackSettings(){}
- public FitoTrackSettings(String preferredUnitSystem, int weight) {
+ public FitoTrackSettings(String preferredUnitSystem, int weight, String mapStyle) {
this.preferredUnitSystem = preferredUnitSystem;
this.weight = weight;
+ this.mapStyle = mapStyle;
}
public String getPreferredUnitSystem() {
@@ -27,4 +48,12 @@ public class FitoTrackSettings {
public void setWeight(int weight) {
this.weight = weight;
}
+
+ public String getMapStyle() {
+ return mapStyle;
+ }
+
+ public void setMapStyle(String mapStyle) {
+ this.mapStyle = mapStyle;
+ }
}
diff --git a/app/src/main/java/de/tadris/fitness/view/WorkoutAdapter.java b/app/src/main/java/de/tadris/fitness/view/WorkoutAdapter.java
index a84c797..c3ece53 100644
--- a/app/src/main/java/de/tadris/fitness/view/WorkoutAdapter.java
+++ b/app/src/main/java/de/tadris/fitness/view/WorkoutAdapter.java
@@ -87,6 +87,10 @@ public class WorkoutAdapter extends RecyclerView.Adapter listener.onItemClick(workout));
+ holder.root.setOnLongClickListener(v -> {
+ listener.onItemLongClick(position, workout);
+ return true;
+ });
}
// Return the size of your dataset (invoked by the layout manager)
@@ -97,6 +101,7 @@ public class WorkoutAdapter extends RecyclerView.Adapter
+
+
diff --git a/app/src/main/res/drawable-hdpi/ic_gps_no_fix.png b/app/src/main/res/drawable-hdpi/ic_gps_no_fix.png
new file mode 100644
index 0000000..d61ce27
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_gps_no_fix.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_gps_no_fix.png b/app/src/main/res/drawable-mdpi/ic_gps_no_fix.png
new file mode 100644
index 0000000..b5f2f30
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_gps_no_fix.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_gps_no_fix.png b/app/src/main/res/drawable-xhdpi/ic_gps_no_fix.png
new file mode 100644
index 0000000..6511d1a
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_gps_no_fix.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_gps_no_fix.png b/app/src/main/res/drawable-xxhdpi/ic_gps_no_fix.png
new file mode 100644
index 0000000..5fe4c25
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_gps_no_fix.png differ
diff --git a/app/src/main/res/layout/activity_record_workout.xml b/app/src/main/res/layout/activity_record_workout.xml
index 25196e2..7a81e31 100644
--- a/app/src/main/res/layout/activity_record_workout.xml
+++ b/app/src/main/res/layout/activity_record_workout.xml
@@ -197,4 +197,34 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_show_workout.xml b/app/src/main/res/layout/activity_show_workout.xml
index 01db9ba..f9eaf4e 100644
--- a/app/src/main/res/layout/activity_show_workout.xml
+++ b/app/src/main/res/layout/activity_show_workout.xml
@@ -18,16 +18,25 @@
~ along with this program. If not, see .
-->
-
-
-
\ No newline at end of file
+ android:layout_height="match_parent">
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_show_workout_map.xml b/app/src/main/res/layout/activity_show_workout_map.xml
new file mode 100644
index 0000000..6d054ab
--- /dev/null
+++ b/app/src/main/res/layout/activity_show_workout_map.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_show_workout_map_diagram.xml b/app/src/main/res/layout/activity_show_workout_map_diagram.xml
new file mode 100644
index 0000000..7444c92
--- /dev/null
+++ b/app/src/main/res/layout/activity_show_workout_map_diagram.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-de/map_layers.xml b/app/src/main/res/values-de/map_layers.xml
new file mode 100644
index 0000000..311b125
--- /dev/null
+++ b/app/src/main/res/values-de/map_layers.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ - Mapnik\nStandard OSM Kartenstil
+ - Humanitarian\nSchöne Karte, aber manchmal nicht verfügbar
+ - Outdoors\nLimitierter Zugriff
+ - Cyclemap\nLimitierter Zugriff
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index f4b1a5a..ccdc23e 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -94,4 +94,6 @@
Bitte aktiviere GPS, damit dein Workout aufgezeichnet werden kann.
Aufstieg
Abstieg
+ Daten
+ Kartenstil
\ No newline at end of file
diff --git a/app/src/main/res/values/map_layers.xml b/app/src/main/res/values/map_layers.xml
new file mode 100644
index 0000000..e08ae72
--- /dev/null
+++ b/app/src/main/res/values/map_layers.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+ - Mapnik\nDefault OSM Mapstyle
+ - Humanitarian\nClean map but sometimes not available
+ - Outdoors\nLimited access
+ - Cyclemap\nLimited access
+
+
+
+ - osm.mapnik
+ - osm.humanitarian
+ - thunderforest.outdoors
+ - thunderforest.cycle
+
+
+
\ 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 c3dc599..924d17e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -112,4 +112,7 @@
Import Data Backup
Restore a taken backup
GPS
+ Data
+ Map Style
+ Waiting for GPS
diff --git a/app/src/main/res/values/unit_systems.xml b/app/src/main/res/values/unit_systems.xml
index 40df41a..4513bf0 100644
--- a/app/src/main/res/values/unit_systems.xml
+++ b/app/src/main/res/values/unit_systems.xml
@@ -22,7 +22,7 @@
- Metric
- - Metric Physical (m/s)
+ - Metric with m/s
- Imperial
- Imperial with meters
diff --git a/app/src/main/res/xml/preferences_main.xml b/app/src/main/res/xml/preferences_main.xml
index e8a0ec8..dd24e5a 100644
--- a/app/src/main/res/xml/preferences_main.xml
+++ b/app/src/main/res/xml/preferences_main.xml
@@ -1,11 +1,31 @@
+
+
+ android:title="@string/pref_unit_system"
+ android:defaultValue="1" />
-
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/metadata/en-US/changelogs/200.txt b/metadata/en-US/changelogs/200.txt
new file mode 100644
index 0000000..8fbd1f3
--- /dev/null
+++ b/metadata/en-US/changelogs/200.txt
@@ -0,0 +1,6 @@
+**2.0:**
+- Screen to compare height/elevation diagram and the map
+- Show overlay if GPS signal wasn't found yet
+- Set preferred map layer (#15)
+
+- Speed up data import
\ No newline at end of file