From ec73699411f9be2eea084b0703244a47e4574e1f Mon Sep 17 00:00:00 2001 From: jannis Date: Mon, 2 Sep 2019 12:55:09 +0200 Subject: [PATCH 01/10] Scenes in ShowWorkoutActivity --- .../fitness/activity/ShowWorkoutActivity.java | 64 ++++++++++++++++++- .../main/res/layout/activity_show_workout.xml | 23 +++++-- 2 files changed, 79 insertions(+), 8 deletions(-) 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..7b58ca9 100644 --- a/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java +++ b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java @@ -26,12 +26,15 @@ import android.graphics.Typeface; import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.transition.Scene; +import android.transition.TransitionManager; 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.LinearLayout; import android.widget.TextView; import androidx.core.content.FileProvider; @@ -86,6 +89,14 @@ public class ShowWorkoutActivity extends FitoTrackActivity { FixedPixelCircle highlightingCircle; Handler mHandler= new Handler(); + Scene sceneOverview; + Scene speedDiagramScene; + Scene heightDiagramScene; + Scene mapScene; + LineChart speedDiagram; + LineChart heightDiagram; + ViewGroup sceneRoot; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -101,6 +112,9 @@ public class ShowWorkoutActivity extends FitoTrackActivity { theme= getTheme(); root= findViewById(R.id.showWorkoutRoot); + sceneRoot= findViewById(R.id.showWorkoutSceneRoot); + ViewGroup sceneLayout= findViewById(R.id.showWorkoutDefaultSceneRoot); + sceneOverview= new Scene(sceneRoot, sceneLayout); addText(getString(R.string.comment) + ": " + workout.comment).setOnClickListener(v -> { TextView textView= (TextView)v; @@ -138,9 +152,24 @@ public class ShowWorkoutActivity extends FitoTrackActivity { addHeightDiagram(); + createScenes(); } + void createScenes(){ + speedDiagramScene= createDiagramScene(speedDiagram); + heightDiagramScene= createDiagramScene(heightDiagram); + mapScene= new Scene(sceneRoot, map); + } + + Scene createDiagramScene(LineChart chart){ + LinearLayout layout= new LinearLayout(this); + layout.setOrientation(LinearLayout.VERTICAL); + layout.addView(map, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getMapHeight())); + layout.addView(chart, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + return new Scene(sceneRoot, layout); + } + void openEditCommentDialog(final TextView change){ final EditText editText= new EditText(this); editText.setText(workout.comment); @@ -253,6 +282,8 @@ public class ShowWorkoutActivity extends FitoTrackActivity { }); chart.invalidate(); + converter.afterAdd(chart); + root.addView(chart, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getWindowManager().getDefaultDisplay().getWidth()*3/4)); } @@ -263,6 +294,7 @@ public class ShowWorkoutActivity extends FitoTrackActivity { String getName(); String getDescription(); boolean compare(WorkoutSample sample, Entry entry); + void afterAdd(LineChart chart); } void addHeightDiagram(){ @@ -294,6 +326,12 @@ public class ShowWorkoutActivity extends FitoTrackActivity { public boolean compare(WorkoutSample sample, Entry entry) { return sample.tmpHeightEntry.equalTo(entry); } + + @Override + public void afterAdd(LineChart chart) { + heightDiagram= chart; + heightDiagram.setOnClickListener(v -> TransitionManager.go(heightDiagramScene)); + } }); } @@ -328,6 +366,12 @@ public class ShowWorkoutActivity extends FitoTrackActivity { public boolean compare(WorkoutSample sample, Entry entry) { return sample.tmpSpeedEntry.equalTo(entry); } + + @Override + public void afterAdd(LineChart chart) { + speedDiagram= chart; + heightDiagram.setOnClickListener(v -> TransitionManager.go(speedDiagramScene)); + } }); } @@ -357,7 +401,7 @@ public class ShowWorkoutActivity extends FitoTrackActivity { map.getModel().mapViewPosition.setMapLimit(bounds); - root.addView(map, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getWindowManager().getDefaultDisplay().getWidth()*3/4)); + root.addView(map, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getMapHeight())); map.setAlpha(0); @@ -367,6 +411,24 @@ public class ShowWorkoutActivity extends FitoTrackActivity { Paint pRed= AndroidGraphicFactory.INSTANCE.createPaint(); pRed.setColor(Color.RED); map.addLayer(new FixedPixelCircle(samples.get(samples.size()-1).toLatLong(), 20, pRed, null)); + + map.setOnClickListener(v -> goToMapScene()); + + goToMapScene(); + } + + private void goToMapScene(){ + TransitionManager.go(mapScene); + map.setOnClickListener(null); + } + + private void leaveMapScene(){ + TransitionManager.go(sceneOverview); + map.setOnClickListener(v -> goToMapScene()); + } + + int getMapHeight(){ + return getWindowManager().getDefaultDisplay().getWidth()*3/4; } @Override 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 From b8a0012f7d1a9bb64b944546d3fba28a0fcda699 Mon Sep 17 00:00:00 2001 From: jannis Date: Mon, 2 Sep 2019 20:37:23 +0200 Subject: [PATCH 02/10] Better layout for workout map and diagrams --- app/src/main/AndroidManifest.xml | 16 +- .../fitness/activity/ShowWorkoutActivity.java | 309 +---------------- .../activity/ShowWorkoutMapActivity.java | 46 +++ .../ShowWorkoutMapDiagramActivity.java | 57 ++++ .../fitness/activity/WorkoutActivity.java | 316 ++++++++++++++++++ .../res/layout/activity_show_workout_map.xml | 37 ++ .../activity_show_workout_map_diagram.xml | 63 ++++ 7 files changed, 547 insertions(+), 297 deletions(-) create mode 100644 app/src/main/java/de/tadris/fitness/activity/ShowWorkoutMapActivity.java create mode 100644 app/src/main/java/de/tadris/fitness/activity/ShowWorkoutMapDiagramActivity.java create mode 100644 app/src/main/java/de/tadris/fitness/activity/WorkoutActivity.java create mode 100644 app/src/main/res/layout/activity_show_workout_map.xml create mode 100644 app/src/main/res/layout/activity_show_workout_map_diagram.xml 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/ShowWorkoutActivity.java b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java index 7b58ca9..317de40 100644 --- a/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java +++ b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java @@ -20,101 +20,42 @@ 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.transition.Scene; -import android.transition.TransitionManager; 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.LinearLayout; 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.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 { - List samples; - Workout workout; - ViewGroup root; - Resources.Theme theme; - MapView map; - TileDownloadLayer downloadLayer; - FixedPixelCircle highlightingCircle; - Handler mHandler= new Handler(); - - Scene sceneOverview; - Scene speedDiagramScene; - Scene heightDiagramScene; - Scene mapScene; - LineChart speedDiagram; - LineChart heightDiagram; - ViewGroup sceneRoot; @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); - sceneRoot= findViewById(R.id.showWorkoutSceneRoot); - ViewGroup sceneLayout= findViewById(R.id.showWorkoutDefaultSceneRoot); - sceneOverview= new Scene(sceneRoot, sceneLayout); + + initAfterContent(); addText(getString(R.string.comment) + ": " + workout.comment).setOnClickListener(v -> { TextView textView= (TextView)v; @@ -134,6 +75,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), @@ -141,6 +85,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))); @@ -152,23 +98,16 @@ public class ShowWorkoutActivity extends FitoTrackActivity { addHeightDiagram(); - createScenes(); + heightDiagram.setOnClickListener(v -> startDiagramActivity(ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE_HEIGHT)); + } - void createScenes(){ - speedDiagramScene= createDiagramScene(speedDiagram); - heightDiagramScene= createDiagramScene(heightDiagram); - mapScene= new Scene(sceneRoot, map); + void startDiagramActivity(String diagramType){ + ShowWorkoutMapDiagramActivity.DIAGRAM_TYPE= diagramType; + startActivity(new Intent(ShowWorkoutActivity.this, ShowWorkoutMapDiagramActivity.class)); } - Scene createDiagramScene(LineChart chart){ - LinearLayout layout= new LinearLayout(this); - layout.setOrientation(LinearLayout.VERTICAL); - layout.addView(map, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getMapHeight())); - layout.addView(chart, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - return new Scene(sceneRoot, layout); - } void openEditCommentDialog(final TextView change){ final EditText editText= new EditText(this); @@ -235,219 +174,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(); - - converter.afterAdd(chart); - - 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 afterAdd(LineChart chart); - } - - 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; - heightDiagram.setOnClickListener(v -> TransitionManager.go(heightDiagramScene)); - } - }); - } - - 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; - heightDiagram.setOnClickListener(v -> TransitionManager.go(speedDiagramScene)); - } - }); - } - - 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, 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.setOnClickListener(v -> goToMapScene()); - - goToMapScene(); - } - - private void goToMapScene(){ - TransitionManager.go(mapScene); - map.setOnClickListener(null); - } - - private void leaveMapScene(){ - TransitionManager.go(sceneOverview); - map.setOnClickListener(v -> goToMapScene()); - } - - 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 onCreateOptionsMenu(Menu menu) { @@ -500,9 +226,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..897e10a --- /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(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(); + + 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/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 From e2e0efea3285188690ce2930d324aa5aad7cacac Mon Sep 17 00:00:00 2001 From: jannis Date: Tue, 10 Sep 2019 18:23:50 +0200 Subject: [PATCH 03/10] #15 Choose the map layers in settings --- .../fitness/activity/SettingsActivity.java | 4 +- .../de/tadris/fitness/map/MapManager.java | 16 +++--- app/src/main/res/values-de/map_layers.xml | 30 ++++++++++++ app/src/main/res/values-de/strings.xml | 2 + app/src/main/res/values/map_layers.xml | 37 ++++++++++++++ app/src/main/res/values/strings.xml | 2 + app/src/main/res/values/unit_systems.xml | 2 +- app/src/main/res/xml/preferences_main.xml | 49 +++++++++++++++---- 8 files changed, 123 insertions(+), 19 deletions(-) create mode 100644 app/src/main/res/values-de/map_layers.xml create mode 100644 app/src/main/res/values/map_layers.xml 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..1841eab 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()); 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..786c7c4 100644 --- a/app/src/main/java/de/tadris/fitness/map/MapManager.java +++ b/app/src/main/java/de/tadris/fitness/map/MapManager.java @@ -19,6 +19,8 @@ package de.tadris.fitness.map; +import android.preference.PreferenceManager; + import org.mapsforge.core.model.LatLong; import org.mapsforge.map.android.graphics.AndroidGraphicFactory; import org.mapsforge.map.android.util.AndroidUtil; @@ -27,20 +29,22 @@ import org.mapsforge.map.layer.cache.TileCache; import org.mapsforge.map.layer.download.TileDownloadLayer; 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= PreferenceManager.getDefaultSharedPreferences(mapView.getContext()).getString("mapStyle", "osm.mapnik"); + 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/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..3fe8b31 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -112,4 +112,6 @@ Import Data Backup Restore a taken backup GPS + Data + Map Style 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 From 99182791f9c6a23c3f3eba3a4cd8181799457bbe Mon Sep 17 00:00:00 2001 From: jannis Date: Tue, 10 Sep 2019 20:01:14 +0200 Subject: [PATCH 04/10] put map style setting into data backup --- .../fitness/activity/SettingsActivity.java | 6 ++-- .../tadris/fitness/data/UserPreferences.java | 4 +++ .../de/tadris/fitness/map/MapManager.java | 5 ++- .../tadris/fitness/util/export/Exporter.java | 8 ++--- .../util/export/FitoTrackSettings.java | 31 ++++++++++++++++++- 5 files changed, 42 insertions(+), 12 deletions(-) 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 1841eab..567789d 100644 --- a/app/src/main/java/de/tadris/fitness/activity/SettingsActivity.java +++ b/app/src/main/java/de/tadris/fitness/activity/SettingsActivity.java @@ -257,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/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 786c7c4..caa54c7 100644 --- a/app/src/main/java/de/tadris/fitness/map/MapManager.java +++ b/app/src/main/java/de/tadris/fitness/map/MapManager.java @@ -19,8 +19,6 @@ package de.tadris.fitness.map; -import android.preference.PreferenceManager; - import org.mapsforge.core.model.LatLong; import org.mapsforge.map.android.graphics.AndroidGraphicFactory; import org.mapsforge.map.android.util.AndroidUtil; @@ -28,6 +26,7 @@ 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; @@ -39,7 +38,7 @@ public class MapManager { public static TileDownloadLayer setupMap(MapView mapView, TileSources.Purpose purpose){ FitoTrackTileSource tileSource; - String chosenTileLayer= PreferenceManager.getDefaultSharedPreferences(mapView.getContext()).getString("mapStyle", "osm.mapnik"); + String chosenTileLayer= Instance.getInstance(mapView.getContext()).userPreferences.getMapStyle(); switch (chosenTileLayer){ case "osm.humanitarian": tileSource= HumanitarianTileSource.INSTANCE; break; case "thunderforest.outdoors": tileSource= ThunderforestTileSource.OUTDOORS; break; 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..6914fe6 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,7 +91,7 @@ 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; 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; + } } From 82e383e9537e3a3fc603080136a744ce4519aa82 Mon Sep 17 00:00:00 2001 From: jannis Date: Tue, 10 Sep 2019 20:01:44 +0200 Subject: [PATCH 05/10] Data Import up to 5 times faster and more secure if it fails --- .../tadris/fitness/util/export/Exporter.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) 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 6914fe6..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 @@ -95,21 +95,25 @@ public class Exporter { .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)); } From 9c3e4021f82e0ba6ce65f57366399654321b1407 Mon Sep 17 00:00:00 2001 From: jannis Date: Wed, 11 Sep 2019 18:07:10 +0200 Subject: [PATCH 06/10] Delete workouts via long press in workout list --- .../activity/ListWorkoutsActivity.java | 24 +++++++++++++++---- .../fitness/activity/ShowWorkoutActivity.java | 11 ++++----- .../de/tadris/fitness/util/DialogUtils.java | 22 +++++++++++++++++ .../tadris/fitness/view/WorkoutAdapter.java | 5 ++++ 4 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/de/tadris/fitness/util/DialogUtils.java 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..4d7f71c 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 { @@ -75,6 +76,9 @@ public class ListWorkoutsActivity extends Activity implements WorkoutAdapter.Wor checkFirstStart(); + adapter= new WorkoutAdapter(workouts, this); + listView.setAdapter(adapter); + } private void checkFirstStart(){ @@ -101,9 +105,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 +115,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 +147,4 @@ public class ListWorkoutsActivity extends Activity implements WorkoutAdapter.Wor return super.onOptionsItemSelected(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 317de40..0036a13 100644 --- a/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java +++ b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java @@ -39,11 +39,12 @@ import java.util.Date; import de.tadris.fitness.Instance; import de.tadris.fitness.R; +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 WorkoutActivity { +public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.WorkoutDeleter { @Override @@ -182,17 +183,13 @@ public class ShowWorkoutActivity extends WorkoutActivity { 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(){ 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/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 Date: Wed, 2 Oct 2019 09:53:16 +0200 Subject: [PATCH 07/10] Show 'Waiting for GPS' overlay when starting recorder --- .../activity/RecordWorkoutActivity.java | 24 ++++++++++++++ .../res/drawable-anydpi/ic_gps_no_fix.xml | 11 +++++++ .../main/res/drawable-hdpi/ic_gps_no_fix.png | Bin 0 -> 358 bytes .../main/res/drawable-mdpi/ic_gps_no_fix.png | Bin 0 -> 247 bytes .../main/res/drawable-xhdpi/ic_gps_no_fix.png | Bin 0 -> 439 bytes .../res/drawable-xxhdpi/ic_gps_no_fix.png | Bin 0 -> 670 bytes .../res/layout/activity_record_workout.xml | 30 ++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + 8 files changed, 66 insertions(+) create mode 100644 app/src/main/res/drawable-anydpi/ic_gps_no_fix.xml create mode 100644 app/src/main/res/drawable-hdpi/ic_gps_no_fix.png create mode 100644 app/src/main/res/drawable-mdpi/ic_gps_no_fix.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_gps_no_fix.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_gps_no_fix.png 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..50e6c7e 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; @@ -337,6 +357,10 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location @Override public void onGPSStateChanged(WorkoutRecorder.GpsState oldState, WorkoutRecorder.GpsState state) { 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/res/drawable-anydpi/ic_gps_no_fix.xml b/app/src/main/res/drawable-anydpi/ic_gps_no_fix.xml new file mode 100644 index 0000000..8647a37 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_gps_no_fix.xml @@ -0,0 +1,11 @@ + + + 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 0000000000000000000000000000000000000000..d61ce270b3b9dd634b4eeeb02903fe09563727ab GIT binary patch literal 358 zcmV-s0h#`ZP)ps+tkV6P6cCAYg3v(%%bZC<_tz}(p zOw$ws5=1CL&@AMGNNzzyhy!>48X~B{Ip<#@Y`_yx0|p|5V?dkP);>#&4`??;tYPN( zrp3g7_rhW?Kmo`Q1TmH+?% literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..b5f2f30f6d2ac800c0555a73d8a161f948ac0d83 GIT binary patch literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gj`#fD7Ln>}1CrJ1_`2YWZw_`;{ zB!fu+cgN+19n5KrQ+S0gFFKOIsj$w?NJN}%taGi))s6S&8Plmq8DC=3C7Kdg$g0ALT$s=Gj1>FnGH9xvXQWtDZt6qO2c<^xP+5++G$D7666sqI`Rvb5 zoWCqfEz&m6^Ya}^KoStU0C2JbbN~(brULMr#(%2+;`9!10t|qOaoU6l`z(ETf8~4w z7%iMOVc}>(M_pS+{5KiVn`Z+I>;YdZ(d+>&;0P!XNBq{WWNqQzZ{_>}@MAE11}F`8#7h-d8+1pGc`YM0`#n`PrA?ipZ z?g3Z(JF(sQD4l&k0ljlcg-$m@(gqaJ65BWH0|)~ZP=H$V=Mw=%KmkP(AZ`eWpTsei zQSl3z?5%|O&0H+oY1s!F@kh!i4)sx7tBAkYisEW9ip$+7uGg7t$b8^1?44viG1;84 hGifaeNCHv|(_YG>`T9g4J{14}002ovPDHLkV1krYzbgO$ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5fe4c25712b1b1656aafac20dee84290199b81e6 GIT binary patch literal 670 zcmV;P0%84$P)2k!uQx!ILi_rhRxUeoe~n(H(#35*VNKtQq*8^hgSC@DuWT z_nN+nn0yxi>A-m>jSTu6@t8_TuBTOz7Kx1~$=}>WBlVVb7UYv8un*Fpf;a~3OBBbc z^1{tixooz2B}Em+6R}U(?AEO+n3iIl^G0gd@QrS>Z`nGjRYf2ZMOsBQ*2GAWZj&nZ zRtHHz9(Xky*QBFlTN2oGK9fA1#G$oWB8hWmv-V_?b&l^4AYZah%B<8P?&pY}%E)uf zcrhu8cWA@mM&NAc@aB0Zh + + + + + + + + + + \ 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 3fe8b31..924d17e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -114,4 +114,5 @@ GPS Data Map Style + Waiting for GPS From e28a2ad9c22c31f6a1761a13d0e4a341eddf18f0 Mon Sep 17 00:00:00 2001 From: jannis Date: Wed, 2 Oct 2019 09:57:27 +0200 Subject: [PATCH 08/10] Changed color of WorkoutMap pointer --- .../main/java/de/tadris/fitness/activity/WorkoutActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/de/tadris/fitness/activity/WorkoutActivity.java b/app/src/main/java/de/tadris/fitness/activity/WorkoutActivity.java index 897e10a..4914a1d 100644 --- a/app/src/main/java/de/tadris/fitness/activity/WorkoutActivity.java +++ b/app/src/main/java/de/tadris/fitness/activity/WorkoutActivity.java @@ -127,8 +127,8 @@ public abstract class WorkoutActivity extends FitoTrackActivity { 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); + p.setColor(0xff693cff); + highlightingCircle= new FixedPixelCircle(findSample(converter, e).toLatLong(), 20, p, null); map.addLayer(highlightingCircle); } From fa0a9ea095ca46f14a11222699974119d6c5ed6b Mon Sep 17 00:00:00 2001 From: jannis Date: Fri, 4 Oct 2019 13:13:35 +0200 Subject: [PATCH 09/10] Fix Crash --- .../fitness/activity/ListWorkoutsActivity.java | 2 ++ .../fitness/activity/RecordWorkoutActivity.java | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) 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 4d7f71c..17c1c1c 100644 --- a/app/src/main/java/de/tadris/fitness/activity/ListWorkoutsActivity.java +++ b/app/src/main/java/de/tadris/fitness/activity/ListWorkoutsActivity.java @@ -74,6 +74,8 @@ 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); 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 50e6c7e..fa4d3f4 100644 --- a/app/src/main/java/de/tadris/fitness/activity/RecordWorkoutActivity.java +++ b/app/src/main/java/de/tadris/fitness/activity/RecordWorkoutActivity.java @@ -356,11 +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)); - if(!gpsFound && (state != WorkoutRecorder.GpsState.SIGNAL_LOST)){ - gpsFound= true; - hideWaitOverlay(); - } + mHandler.post(() -> { + gpsStatusView.setTextColor(state.color); + if(!gpsFound && (state != WorkoutRecorder.GpsState.SIGNAL_LOST)){ + gpsFound= true; + hideWaitOverlay(); + } + }); } public static class InfoViewHolder{ From 607850b8c66d10727ce048c25268966824385c65 Mon Sep 17 00:00:00 2001 From: jannis Date: Fri, 4 Oct 2019 13:16:03 +0200 Subject: [PATCH 10/10] Version code 2.0, changelogs --- app/build.gradle | 4 ++-- metadata/en-US/changelogs/200.txt | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 metadata/en-US/changelogs/200.txt 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/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