Elevation now visible in statistics sheet - works for new tracks only (see #28)

master
y20k 2018-02-06 17:10:36 +01:00
parent ed0d53e336
commit 03d5513df6
13 changed files with 514 additions and 50 deletions

View File

@ -27,6 +27,7 @@ import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.Group;
import android.support.design.widget.BottomSheetBehavior;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
@ -41,6 +42,7 @@ import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import org.osmdroid.api.IMapController;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
@ -89,6 +91,11 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
private TextView mDurationView;
private TextView mRecordingStartView;
private TextView mRecordingStopView;
private TextView mMaxAltitudeView;
private TextView mMinAltitudeView;
private TextView mPositiveElevationView;
private TextView mNegativeElevationView;
private Group mElevationDataViews;
private BottomSheetBehavior mStatisticsSheetBehavior;
private int mCurrentTrack;
private Track mTrack;
@ -204,6 +211,14 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
mDurationView = (TextView) mRootView.findViewById(R.id.statistics_data_duration);
mRecordingStartView = (TextView) mRootView.findViewById(R.id.statistics_data_recording_start);
mRecordingStopView = (TextView) mRootView.findViewById(R.id.statistics_data_recording_stop);
mMaxAltitudeView = (TextView) mRootView.findViewById(R.id.statistics_data_max_altitude);
mMinAltitudeView = (TextView) mRootView.findViewById(R.id.statistics_data_min_altitude);
mPositiveElevationView = (TextView) mRootView.findViewById(R.id.statistics_data_positive_elevation);
mNegativeElevationView = (TextView) mRootView.findViewById(R.id.statistics_data_negative_elevation);
mElevationDataViews = (Group) mRootView.findViewById(R.id.elevation_data);
// attach listners for taps on elevation views
attachTapListeners();
// display map and statistics
if (savedInstanceState != null) {
@ -359,9 +374,23 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
mDurationView.setText(mTrack.getTrackDurationString());
mRecordingStartView.setText(recordingStart);
mRecordingStopView.setText(recordingStop);
mPositiveElevationView.setText(mTrack.getPositiveElevationString());
mNegativeElevationView.setText(mTrack.getNegativeElevationString());
mMaxAltitudeView.setText(mTrack.getMaxAltitudeString());
mMinAltitudeView.setText(mTrack.getMinAltitudeString());
// show/hide elevation views depending on file format version
if (mTrack.getTrackFormatVersion() > 1 || mTrack.getMinAltitude() > 0) {
// show elevation views
mElevationDataViews.setVisibility(View.VISIBLE);
} else {
// hide elevation views
mElevationDataViews.setVisibility(View.GONE);
}
// draw track on map
drawTrackOverlay(mTrack);
} else {
position = new GeoPoint(DEFAULT_LATITUDE, DEFAULT_LONGITUDE);
}
@ -531,6 +560,21 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
}
/* Add tap listners to elevation data views */
private void attachTapListeners() {
int referencedIds[] = mElevationDataViews.getReferencedIds();
for (int id : referencedIds) {
mRootView.findViewById(id).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// inform user about possible issues with altitude measurements
Toast.makeText(mActivity, R.string.toast_message_elevation_info, Toast.LENGTH_LONG).show();
}
});
}
}
/**
* Inner class: Loads track from external storage using AsyncTask
*/
@ -559,10 +603,6 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// todo remove
StorageHelper storageHelper = new StorageHelper(mActivity);
storageHelper.calculateTrackElevation(mTrack);
// display track on map
displayTrack();
}

View File

@ -49,6 +49,32 @@ public class Track implements TrackbookKeys, Parcelable {
private float mStepCount;
private final Date mRecordingStart;
private Date mRecordingStop;
private double mMaxAltitude;
private double mMinAltitude;
private double mPositiveElevation;
private double mNegativeElevation;
/* Generic Constructor */
public Track(int trackFormatVersion, List<WayPoint> wayPoints, float trackLength, long duration, float stepCount, Date recordingStart, Date recordingStop, double maxAltitude, double minAltitude, double positiveElevation, double negativeElevation) {
mTrackFormatVersion = trackFormatVersion;
mWayPoints = wayPoints;
mTrackLength = trackLength;
mDuration = duration;
mStepCount = stepCount;
mRecordingStart = recordingStart;
mRecordingStop = recordingStop;
mMaxAltitude = maxAltitude;
mMinAltitude = minAltitude;
mPositiveElevation = positiveElevation;
mNegativeElevation = negativeElevation;
}
/* Copy Constructor */
public Track(Track track) {
this(track.getTrackFormatVersion(), track.getWayPoints(), track.getTrackLength(), track.getTrackDuration(), track.getStepCount(), track.getRecordingStart(), track.getRecordingStop(), track.getMaxAltitude(), track.getMinAltitude(), track.getPositiveElevation(), track.getNegativeElevation());
}
/* Constructor */
@ -60,6 +86,10 @@ public class Track implements TrackbookKeys, Parcelable {
mStepCount = 0f;
mRecordingStart = GregorianCalendar.getInstance().getTime();
mRecordingStop = mRecordingStart;
mMaxAltitude = 0f;
mMinAltitude = 0f;
mPositiveElevation = 0f;
mNegativeElevation = 0f;
}
@ -72,6 +102,10 @@ public class Track implements TrackbookKeys, Parcelable {
mStepCount = in.readFloat();
mRecordingStart = new Date(in.readLong());
mRecordingStop = new Date(in.readLong());
mMaxAltitude = in.readDouble();
mMinAltitude = in.readDouble();
mPositiveElevation = in.readDouble();
mNegativeElevation = in.readDouble();
}
@ -136,6 +170,36 @@ public class Track implements TrackbookKeys, Parcelable {
}
/* Setter for maximum altitude of recording */
public void setMaxAltitude(double maxAltitude) {
mMaxAltitude = maxAltitude;
}
/* Setter for lowest altitude of recording */
public void setMinAltitude(double minAltitude) {
mMinAltitude = minAltitude;
}
/* Setter for positive elevation of recording (cumulative altitude difference) */
public void setPositiveElevation(double positiveElevation) {
mPositiveElevation = positiveElevation;
}
/* Setter for negative elevation of recording (cumulative altitude difference) */
public void setNegativeElevation(double megativeElevation) {
mNegativeElevation = megativeElevation;
}
/* Getter for file/track fornat version */
public int getTrackFormatVersion() {
return mTrackFormatVersion;
}
/* Getter for mWayPoints */
public List<WayPoint> getWayPoints() {
return mWayPoints;
@ -148,6 +212,12 @@ public class Track implements TrackbookKeys, Parcelable {
}
/* Getter for track length */
public float getTrackLength() {
return mTrackLength;
}
/* Getter for duration of track */
public long getTrackDuration() {
return mDuration;
@ -171,26 +241,64 @@ public class Track implements TrackbookKeys, Parcelable {
}
/* Getter for maximum altitude of recording */
public double getMaxAltitude() {
return mMaxAltitude;
}
/* Getter for lowest altitude of recording */
public double getMinAltitude() {
return mMinAltitude;
}
/* Getter for positive elevation of recording (cumulative altitude difference) */
public double getPositiveElevation() {
return mPositiveElevation;
}
/* Getter for negative elevation of recording (cumulative altitude difference) */
public double getNegativeElevation() {
return mNegativeElevation;
}
/* Getter for string representation of maximum altitude of recording */
public String getMaxAltitudeString() {
return convertDistanceToString(mMaxAltitude);
}
/* Getter for string representation of lowest altitude of recording */
public String getMinAltitudeString() {
return convertDistanceToString(mMinAltitude);
}
/* Getter for string representation of positive elevation of recording (cumulative altitude difference) */
public String getPositiveElevationString() {
return convertDistanceToString(mPositiveElevation);
}
/* Getter for string representation of negative elevation of recording (cumulative altitude difference) */
public String getNegativeElevationString() {
return convertDistanceToString(mNegativeElevation);
}
/* Getter for string representation of track duration */
public String getTrackDurationString() {
return LocationHelper.convertToReadableTime(mDuration, true);
}
/* Getter for string representation of track distance */
public String getTrackDistanceString() {
float trackDistance;
String unit;
if (getUnitSystem(Locale.getDefault()) == IMPERIAL) {
// get track distance and convert to feet
trackDistance = mWayPoints.get(mWayPoints.size()-1).getDistanceToStartingPoint() * 3.28084f;
unit = "ft";
} else {
// get track distance
trackDistance = mWayPoints.get(mWayPoints.size()-1).getDistanceToStartingPoint();
unit = "m";
}
return String.format (Locale.ENGLISH, "%.0f", trackDistance) + unit;
double trackDistance = (double) mWayPoints.get(mWayPoints.size()-1).getDistanceToStartingPoint();
return convertDistanceToString(trackDistance);
}
@ -216,6 +324,23 @@ public class Track implements TrackbookKeys, Parcelable {
}
/* Converts a given distance value to a readable string */
private String convertDistanceToString(double distance) {
// check for locale and set unit system accordingly
String unit;
if (getUnitSystem(Locale.getDefault()) == IMPERIAL) {
// convert distance to feet
distance = distance * 3.28084f;
// set measurement unit
unit = "ft";
} else {
// set measurement unit
unit = "m";
}
return String.format (Locale.ENGLISH, "%.0f", distance) + unit;
}
/* Determines which unit system the device is using (metric or imperial) */
private int getUnitSystem(Locale locale) {
// America (US), Liberia (LR), Myanmar(MM) use the imperial system
@ -245,8 +370,11 @@ public class Track implements TrackbookKeys, Parcelable {
parcel.writeFloat(mStepCount);
parcel.writeLong(mRecordingStart.getTime());
parcel.writeLong(mRecordingStop.getTime());
parcel.writeDouble(mMaxAltitude);
parcel.writeDouble(mMinAltitude);
parcel.writeDouble(mPositiveElevation);
parcel.writeDouble(mNegativeElevation);
}
}

View File

@ -0,0 +1,80 @@
/**
* TrackBuilder.java
* Implements a builder for the Track class
* A TrackBuilder can build a track object depending on the version of its file format
*
* This file is part of
* TRACKBOOK - Movement Recorder for Android
*
* Copyright (c) 2016-18 - Y20K.org
* Licensed under the MIT-License
* http://opensource.org/licenses/MIT
*
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
* https://github.com/osmdroid/osmdroid
*/
package org.y20k.trackbook.core;
import org.y20k.trackbook.helpers.LogHelper;
import java.util.Date;
import java.util.List;
/**
* TrackBuilder class
*/
public class TrackBuilder {
/* Define log tag */
private static final String LOG_TAG = TrackBuilder.class.getSimpleName();
/* Main class variables */
private final int mTrackFormatVersion;
private final List<WayPoint> mWayPoints;
private float mTrackLength;
private long mDuration;
private float mStepCount;
private final Date mRecordingStart;
private Date mRecordingStop;
private double mMaxAltitude;
private double mMinAltitude;
private double mPositiveElevation;
private double mNegativeElevation;
/* Generic Constructor */
public TrackBuilder(int trackFormatVersion, List<WayPoint> wayPoints, float trackLength, long duration, float stepCount, Date recordingStart, Date recordingStop, double maxAltitude, double minAltitude, double positiveElevation, double negativeElevation) {
mTrackFormatVersion = trackFormatVersion;
mWayPoints = wayPoints;
mTrackLength = trackLength;
mDuration = duration;
mStepCount = stepCount;
mRecordingStart = recordingStart;
mRecordingStop = recordingStop;
mMaxAltitude = maxAltitude;
mMinAltitude = minAltitude;
mPositiveElevation = positiveElevation;
mNegativeElevation = negativeElevation;
}
/* Builds and return a Track object */
public Track toTrack() {
switch (mTrackFormatVersion) {
case 1:
// file format version 1 - does not have elevation data stored
return new Track(mTrackFormatVersion, mWayPoints, mTrackLength, mDuration, mStepCount, mRecordingStart, mRecordingStop, 0f, 0f, 0f, 0f);
case 2:
// file format version 2 (current version)
return new Track(mTrackFormatVersion, mWayPoints, mTrackLength, mDuration, mStepCount, mRecordingStart, mRecordingStop, mMaxAltitude, mMinAltitude, mPositiveElevation, mNegativeElevation);
default:
LogHelper.e(LOG_TAG, "Unknown file format version: " + mTrackFormatVersion);
return null;
}
}
}

View File

@ -17,7 +17,6 @@
package org.y20k.trackbook.helpers;
import android.content.Context;
import android.location.Location;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v4.os.EnvironmentCompat;
@ -28,6 +27,7 @@ import com.google.gson.GsonBuilder;
import org.y20k.trackbook.R;
import org.y20k.trackbook.core.Track;
import org.y20k.trackbook.core.TrackBuilder;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@ -101,6 +101,9 @@ public class StorageHelper implements TrackbookKeys {
}
if (mFolder != null && mFolder.exists() && mFolder.isDirectory() && mFolder.canWrite() && recordingStart != null && track != null) {
// calculate elevation and store it in track
track = calculateElevation(track);
// create file object
String fileName;
if (fileType == FILE_TEMP_TRACK) {
@ -221,22 +224,19 @@ public class StorageHelper implements TrackbookKeys {
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
LogHelper.v(LOG_TAG, "Loading track from external storage: " + file.toString());
// read until last line reached
String line;
StringBuilder sb = new StringBuilder("");
// read until last line reached
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
// TODO implement a format version check before handing the file to GSON
// get track from JSON
// prepare GsonBuilder and return Track object
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("M/d/yy hh:mm a");
Gson gson = gsonBuilder.create();
return gson.fromJson(sb.toString(), Track.class);
return gson.fromJson(sb.toString(), TrackBuilder.class).toTrack();
} catch (IOException e) {
LogHelper.e(LOG_TAG, "Unable to read file from external storage: " + file.toString());
@ -360,38 +360,105 @@ public class StorageHelper implements TrackbookKeys {
}
/* Calculates positive and negative elevation of track */ // todo make private
public Track calculateTrackElevation(@Nullable Track track) {
/* Calculates positive and negative elevation of track */
private Track calculateElevation(@Nullable Track track) {
double maxAltitude = 0;
double minAltitude = 0;
double positiveElevation = 0;
double negativeElevation = 0;
double LIKELY_MEASUREMENT_ERROR = 25; // move to TrackbookKeys
if (track != null && track.getWayPoints().size() > 0 && track.getWayPointLocation(0).getAltitude() != 0) {
Location previousLocation;
Location nextLocation;
double previousLocationHeight;
double currentLocationHeight;
long previousTimeStamp;
long currentTimeStamp;
// initial values for max height and min height - first waypoint
maxAltitude = track.getWayPointLocation(0).getAltitude();
minAltitude = maxAltitude;
// apply filter & smooth data
// track = lowPass(track, 15f, 35f);
// iterate over track
for (int i = 0; i < track.getWayPoints().size() - 1; i++ ) {
// calculate elevation difference
previousLocation = track.getWayPointLocation(i);
nextLocation = track.getWayPointLocation(i + 1);
double difference = nextLocation.getAltitude() - previousLocation.getAltitude();
LogHelper.i(LOG_TAG, "next:" + nextLocation.getAltitude() + " | prev:" + previousLocation.getAltitude() + " | diff:" + difference); // todo remove
for (int i = 1; i < track.getWayPoints().size(); i++ ) {
// add difference to elevation
if (difference > 0 && difference < LIKELY_MEASUREMENT_ERROR) {
positiveElevation = positiveElevation + difference;
} else if (difference < 0 && difference > -LIKELY_MEASUREMENT_ERROR) {
negativeElevation = negativeElevation + difference;
// get time difference
previousTimeStamp = track.getWayPointLocation(i -1).getTime();
currentTimeStamp = track.getWayPointLocation(i).getTime();
double timeDiff = (currentTimeStamp - previousTimeStamp);
// factor is bigger than 1 if the time stamp difference is larger than the movement recording interval (usually 15 seconds)
double timeDiffFactor = timeDiff / FIFTEEN_SECONDS_IN_MILLISECONDS;
// height of previous and current waypoints
previousLocationHeight = track.getWayPointLocation(i -1).getAltitude();
currentLocationHeight = track.getWayPointLocation(i).getAltitude();
// check for new min and max heights
if (currentLocationHeight > maxAltitude) {
maxAltitude = currentLocationHeight;
} else if (minAltitude == 0 || currentLocationHeight < minAltitude) {
minAltitude = currentLocationHeight;
}
// get elevation difference and sum it up
double altitudeDiff = currentLocationHeight - previousLocationHeight;
if (altitudeDiff > 0 && altitudeDiff < MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationHeight != 0) {
positiveElevation = positiveElevation + altitudeDiff;
} else if (altitudeDiff < 0 && altitudeDiff > -MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationHeight != 0) {
negativeElevation = negativeElevation + altitudeDiff;
}
}
String toastString = "Calculated elevation: +" + positiveElevation + " / " + negativeElevation + " meters"; // todo remove
Toast.makeText(mContext, toastString, Toast.LENGTH_LONG).show(); // todo remove
LogHelper.i(LOG_TAG, toastString); // todo remove
// store elevation data in track
track.setMaxAltitude(maxAltitude);
track.setMinAltitude(minAltitude);
track.setPositiveElevation(positiveElevation);
track.setNegativeElevation(negativeElevation);
}
return track;
}
/* Tries to smooth the elevation data using a low pass filter */
private Track lowPass(Track input, float dt, float rc) {
/* The following code is adapted from https://en.wikipedia.org/wiki/Low-pass_filter
*
* // Return RC low-pass filter output samples, given input samples,
* // time interval dt, and time constant RC
* function lowpass(real[0..n] x, real dt, real RC)
* var real[0..n] y
* var real α := dt / (RC + dt)
* y[0] := α * x[0]
* for i from 1 to n
* y[i] := α * x[i] + (1-α) * y[i-1]
* return y
*/
// copy input track
Track output = new Track(input);
// calculate alpha
float alpha = dt / (rc + dt);
// set initial value for first waypoint
double outputInitialAltituteValue = alpha * input.getWayPoints().get(0).getLocation().getAltitude();
output.getWayPoints().get(0).getLocation().setAltitude(outputInitialAltituteValue);
double inputCurrentAltitudeValue;
double outputPreviousAltitudeValue;
double outputCurrentAltitudeValue;
for (int i = 1; i < input.getSize(); i++) {
inputCurrentAltitudeValue = input.getWayPoints().get(i).getLocation().getAltitude();
outputPreviousAltitudeValue = output.getWayPoints().get(i-1).getLocation().getAltitude();
outputCurrentAltitudeValue = alpha * inputCurrentAltitudeValue + (1 - alpha) * outputPreviousAltitudeValue;
output.getWayPoints().get(i).getLocation().setAltitude(outputCurrentAltitudeValue);
}
return output;
}
}

View File

@ -111,10 +111,10 @@ public interface TrackbookKeys {
String NOTIFICATION_CHANEL_ID_RECORDING_CHANNEL ="notificationChannelIdRecordingChannel";
/* MISC */
int CURRENT_TRACK_FORMAT_VERSION = 2; // incremental version number to prevent issues in case the Track format evolves
double DEFAULT_LATITUDE = 49.41667; // latitude Nordkapp, Norway
double DEFAULT_LONGITUDE = 8.67201; // longitude Nordkapp, Norway
int CURRENT_TRACK_FORMAT_VERSION = 1; // incremental version number to prevent issues in case the Track format evolves
int MEASUREMENT_ERROR_THRESHOLD = 10; // altitude changes of 10 meter or more (per 15 seconds) are being discarded
int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
int INFOSHEET_CONTENT_ABOUT = 1;
}

View File

@ -5,6 +5,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.constraint.Group
android:id="@+id/elevation_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="statistics_p_positive_elevation, statistics_data_positive_elevation, statistics_p_negative_elevation, statistics_data_negative_elevation, statistics_p_max_altitude, statistics_data_max_altitude, statistics_p_min_altitude, statistics_data_min_altitude" />
<TextView
android:id="@+id/statistics_headline"
android:layout_width="0dp"
@ -148,11 +154,9 @@
android:id="@+id/statistics_p_recording_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginTop="16dp"
android:contentDescription="@string/descr_statistics_sheet_p_recording_end"
android:text="@string/statistics_sheet_p_recording_stop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/statistics_p_recording_start"
app:layout_constraintTop_toBottomOf="@+id/statistics_p_recording_start" />
@ -168,4 +172,90 @@
app:layout_constraintStart_toEndOf="@+id/statistics_p_recording_stop"
app:layout_constraintTop_toTopOf="@+id/statistics_p_recording_stop" />
<TextView
android:id="@+id/statistics_p_positive_elevation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:contentDescription="@string/descr_statistics_sheet_p_positive_elevation"
android:text="@string/statistics_sheet_p_positive_elevation"
app:layout_constraintStart_toStartOf="@+id/statistics_p_recording_stop"
app:layout_constraintTop_toBottomOf="@+id/statistics_p_recording_stop" />
<TextView
android:id="@+id/statistics_data_positive_elevation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/statistics_sheet_p_default_data"
android:textAppearance="@android:style/TextAppearance.Material.Medium"
app:layout_constraintBottom_toBottomOf="@+id/statistics_p_positive_elevation"
app:layout_constraintStart_toEndOf="@+id/statistics_p_positive_elevation"
app:layout_constraintTop_toTopOf="@+id/statistics_p_positive_elevation" />
<TextView
android:id="@+id/statistics_p_negative_elevation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:contentDescription="@string/descr_statistics_sheet_p_negative_elevation"
android:text="@string/statistics_sheet_p_negative_elevation"
app:layout_constraintStart_toStartOf="@+id/statistics_p_positive_elevation"
app:layout_constraintTop_toBottomOf="@+id/statistics_p_positive_elevation" />
<TextView
android:id="@+id/statistics_data_negative_elevation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/statistics_sheet_p_default_data"
android:textAppearance="@android:style/TextAppearance.Material.Medium"
app:layout_constraintBottom_toBottomOf="@+id/statistics_p_negative_elevation"
app:layout_constraintStart_toEndOf="@+id/statistics_p_negative_elevation"
app:layout_constraintTop_toTopOf="@+id/statistics_p_negative_elevation" />
<TextView
android:id="@+id/statistics_p_max_altitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:contentDescription="@string/descr_statistics_sheet_p_max_altitude"
android:text="@string/statistics_sheet_p_max_altitude"
app:layout_constraintStart_toStartOf="@+id/statistics_p_negative_elevation"
app:layout_constraintTop_toBottomOf="@+id/statistics_p_negative_elevation" />
<TextView
android:id="@+id/statistics_data_max_altitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/statistics_sheet_p_default_data"
android:textAppearance="@android:style/TextAppearance.Material.Medium"
app:layout_constraintBottom_toBottomOf="@+id/statistics_p_max_altitude"
app:layout_constraintStart_toEndOf="@+id/statistics_p_max_altitude"
app:layout_constraintTop_toTopOf="@+id/statistics_p_max_altitude" />
<TextView
android:id="@+id/statistics_p_min_altitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginTop="16dp"
android:contentDescription="@string/descr_statistics_sheet_p_min_altitude"
android:text="@string/statistics_sheet_p_min_altitude"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/statistics_p_max_altitude"
app:layout_constraintTop_toBottomOf="@+id/statistics_p_max_altitude" />
<TextView
android:id="@+id/statistics_data_min_altitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/statistics_sheet_p_default_data"
android:textAppearance="@android:style/TextAppearance.Material.Medium"
app:layout_constraintBottom_toBottomOf="@+id/statistics_p_min_altitude"
app:layout_constraintStart_toEndOf="@+id/statistics_p_min_altitude"
app:layout_constraintTop_toTopOf="@+id/statistics_p_min_altitude" />
</android.support.constraint.ConstraintLayout>

View File

@ -56,8 +56,9 @@
<string name="toast_message_save_track">Aufzeichnung wird gespeichert.</string>
<string name="toast_message_last_location_age_one_hour">über eine Stunde</string>
<string name="toast_message_track_clear">Aufzeichnung zurückgesetzt.</string>
<string name="toast_message_export_success">GPX export successful:</string>
<string name="toast_message_export_fail">GPX export failed:</string>
<string name="toast_message_export_success">GPX-Export erfolgreich:</string>
<string name="toast_message_export_fail">GPX-Export fehlgeschlagen:</string>
<string name="toast_message_elevation_info">Hinweis: Die Genauogkeit der Höhenmeter-Werte ist geräteabhängig. Gemessen werden die Steigungen und Gefälle der Gesamtstrecke.</string>
<!-- map markers -->
<string name="marker_description_source">Quelle</string>
@ -74,6 +75,10 @@
<string name="statistics_sheet_p_duration">Dauer (gesamt):</string>
<string name="statistics_sheet_p_recording_start">Start der Aufzeichnung:</string>
<string name="statistics_sheet_p_recording_stop">Ende der Aufzeichnung:</string>
<string name="statistics_sheet_p_max_altitude">Höchster Wegpunkt:</string>
<string name="statistics_sheet_p_min_altitude">Tiefster Wegpunkt:</string>
<string name="statistics_sheet_p_positive_elevation">Höhenmeter (bergauf):</string>
<string name="statistics_sheet_p_negative_elevation">Höhenmeter (bergab):</string>
<!-- onboarding layout -->
<string name="layout_onboarding_h1_welcome">Hallo</string>
@ -114,6 +119,10 @@
<string name="descr_statistics_sheet_p_duration_value">Wert: Dauer</string>
<string name="descr_statistics_sheet_p_recording_start_value">Wert: Start der Aufzeichnung</string>
<string name="descr_statistics_sheet_p_recording_end_value">Wert: Ende der Aufzeichnung</string>
<string name="descr_statistics_sheet_p_max_altitude">Wert: Höchster Wegpunkt</string>
<string name="descr_statistics_sheet_p_min_altitude">Wert: Tiefster Wegpunkt:</string>
<string name="descr_statistics_sheet_p_positive_elevation">Wert: Höhenmeter (bergauf)</string>
<string name="descr_statistics_sheet_p_negative_elevation">Wert Höhenmeter (bergab)</string>
<string name="descr_track_selector">Auswahl-Menü für weitere Aufzeichnungen</string>
<string name="descr_export_button">Button Track Exportierem</string>
<string name="descr_delete_button">Button Track Löschen</string>

View File

@ -58,6 +58,7 @@
<string name="toast_message_track_clear">Current track data removed.</string>
<string name="toast_message_export_success">GPX export successful:</string>
<string name="toast_message_export_fail">GPX export failed:</string>
<string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string>
<!-- map markers -->
<string name="marker_description_source">Source</string>
@ -74,6 +75,10 @@
<string name="statistics_sheet_p_duration">Total duration:</string>
<string name="statistics_sheet_p_recording_start">Recording started:</string>
<string name="statistics_sheet_p_recording_stop">Recording stopped:</string>
<string name="statistics_sheet_p_max_altitude">Highest waypoint:</string>
<string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string>
<string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string>
<string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string>
<!-- onboarding layout -->
<string name="layout_onboarding_h1_welcome">Hello</string>
@ -114,6 +119,10 @@
<string name="descr_statistics_sheet_p_duration_value">Value: Duration</string>
<string name="descr_statistics_sheet_p_recording_start_value">Value: Start of recording</string>
<string name="descr_statistics_sheet_p_recording_end_value">Value: End of recording</string>
<string name="descr_statistics_sheet_p_max_altitude">Value: Highest waypoint</string>
<string name="descr_statistics_sheet_p_min_altitude">Value: Lowest waypoint</string>
<string name="descr_statistics_sheet_p_positive_elevation">Value: Elevation (uphill)</string>
<string name="descr_statistics_sheet_p_negative_elevation">Value: Elevation (downhill)</string>
<string name="descr_track_selector">Dropdown menu for further tracks</string>
<string name="descr_export_button">Track export button</string>
<string name="descr_delete_button">Track delete button</string>

View File

@ -58,6 +58,7 @@
<string name="toast_message_track_clear">Dati della traccia corrente rimossi.</string>
<string name="toast_message_export_success">L\'esportazione GPX è riuscita:</string>
<string name="toast_message_export_fail">L\'esportazione GPX non è riuscita:</string>
<string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string>
<!-- map markers -->
<string name="marker_description_source">Fonte</string>
@ -74,6 +75,10 @@
<string name="statistics_sheet_p_duration">Durata totale:</string>
<string name="statistics_sheet_p_recording_start">Registrazione avviata il:</string>
<string name="statistics_sheet_p_recording_stop">Registrazione interrotta il:</string>
<string name="statistics_sheet_p_max_altitude">Highest waypoint:</string>
<string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string>
<string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string>
<string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string>
<!-- onboarding layout -->
<string name="layout_onboarding_h1_welcome">Ciao</string>
@ -114,6 +119,10 @@
<string name="descr_statistics_sheet_p_duration_value">Valore: Durata</string>
<string name="descr_statistics_sheet_p_recording_start_value">Valore: Inizio della registrazione</string>
<string name="descr_statistics_sheet_p_recording_end_value">Valore: Fine della registrazione</string>
<string name="descr_statistics_sheet_p_max_altitude">Value: Highest waypoint</string>
<string name="descr_statistics_sheet_p_min_altitude">Value: Lowest waypoint</string>
<string name="descr_statistics_sheet_p_positive_elevation">Value: Elevation (uphill)</string>
<string name="descr_statistics_sheet_p_negative_elevation">Value: Elevation (downhill)</string>
<string name="descr_track_selector">Elenco registrazioni</string>
<string name="descr_export_button">Pulsante di esportazione della traccia</string>
<string name="descr_delete_button">Pulsante di eliminazione della traccia</string>

View File

@ -58,6 +58,7 @@
<string name="toast_message_track_clear">現在のトレース データを削除しました。</string>
<string name="toast_message_export_success">GPX export successful:</string>
<string name="toast_message_export_fail">GPX export failed:</string>
<string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string>
<!-- map markers -->
<string name="marker_description_source">ソース</string>
@ -74,6 +75,10 @@
<string name="statistics_sheet_p_duration">合計時間:</string>
<string name="statistics_sheet_p_recording_start">記録の開始:</string>
<string name="statistics_sheet_p_recording_stop">記録の停止:</string>
<string name="statistics_sheet_p_max_altitude">Highest waypoint:</string>
<string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string>
<string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string>
<string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string>
<!-- onboarding layout -->
<string name="layout_onboarding_h1_welcome">こんにちは</string>
@ -114,6 +119,10 @@
<string name="descr_statistics_sheet_p_duration_value">値: 期間</string>
<string name="descr_statistics_sheet_p_recording_start_value">値: 記録の開始</string>
<string name="descr_statistics_sheet_p_recording_end_value">値: 記録の終了</string>
<string name="descr_statistics_sheet_p_max_altitude">Value: Highest waypoint</string>
<string name="descr_statistics_sheet_p_min_altitude">Value: Lowest waypoint</string>
<string name="descr_statistics_sheet_p_positive_elevation">Value: Elevation (uphill)</string>
<string name="descr_statistics_sheet_p_negative_elevation">Value: Elevation (downhill)</string>
<string name="descr_track_selector">ドロップダウン メニューでさらにトレース</string>
<string name="descr_export_button">Track export button</string>
<string name="descr_delete_button">トレース削除ボタン</string>

View File

@ -58,6 +58,7 @@
<string name="toast_message_track_clear">Nåværende turdata fjernet.</string>
<string name="toast_message_export_success">GPX-eksportering vellykket:</string>
<string name="toast_message_export_fail">GPX-eksportering mislyktes:</string>
<string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string>
<!-- map markers -->
<string name="marker_description_source">Kilde</string>
@ -74,6 +75,10 @@
<string name="statistics_sheet_p_duration">Total varighet:</string>
<string name="statistics_sheet_p_recording_start">Opptak startet:</string>
<string name="statistics_sheet_p_recording_stop">Opptak stoppet:</string>
<string name="statistics_sheet_p_max_altitude">Highest waypoint:</string>
<string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string>
<string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string>
<string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string>
<!-- onboarding layout -->
<string name="layout_onboarding_h1_welcome">Hallo</string>
@ -114,6 +119,10 @@
<string name="descr_statistics_sheet_p_duration_value">Verdi: Varighet</string>
<string name="descr_statistics_sheet_p_recording_start_value">Verdi: Opptaksstart</string>
<string name="descr_statistics_sheet_p_recording_end_value">Verdi: Opptaksslutt</string>
<string name="descr_statistics_sheet_p_max_altitude">Value: Highest waypoint</string>
<string name="descr_statistics_sheet_p_min_altitude">Value: Lowest waypoint</string>
<string name="descr_statistics_sheet_p_positive_elevation">Value: Elevation (uphill)</string>
<string name="descr_statistics_sheet_p_negative_elevation">Value: Elevation (downhill)</string>
<string name="descr_track_selector">Nedtrekksmeny for ytterligere turer</string>
<string name="descr_export_button">Tureksportknapp</string>
<string name="descr_delete_button">Turslettingsknapp</string>

View File

@ -58,6 +58,7 @@
<string name="toast_message_track_clear">Huidige baangegevens verwijderd.</string>
<string name="toast_message_export_success">GPX export successful:</string>
<string name="toast_message_export_fail">GPX export failed:</string>
<string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string>
<!-- map markers -->
<string name="marker_description_source">Bron</string>
@ -74,6 +75,10 @@
<string name="statistics_sheet_p_duration">Totale duur:</string>
<string name="statistics_sheet_p_recording_start">Bijhouden gestart:</string>
<string name="statistics_sheet_p_recording_stop">Bijhouden gestopt:</string>
<string name="statistics_sheet_p_max_altitude">Highest waypoint:</string>
<string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string>
<string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string>
<string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string>
<!-- onboarding layout -->
<string name="layout_onboarding_h1_welcome">Hallo</string>

View File

@ -58,6 +58,7 @@
<string name="toast_message_track_clear">Current track data removed.</string>
<string name="toast_message_export_success">GPX export successful:</string>
<string name="toast_message_export_fail">GPX export failed:</string>
<string name="toast_message_elevation_info">Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured.</string>
<!-- map markers -->
<string name="marker_description_source">Source</string>
@ -74,6 +75,10 @@
<string name="statistics_sheet_p_duration">Total duration:</string>
<string name="statistics_sheet_p_recording_start">Recording started:</string>
<string name="statistics_sheet_p_recording_stop">Recording stopped:</string>
<string name="statistics_sheet_p_max_altitude">Highest waypoint:</string>
<string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string>
<string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string>
<string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string>
<!-- onboarding layout -->
<string name="layout_onboarding_h1_welcome">Hello</string>
@ -114,6 +119,10 @@
<string name="descr_statistics_sheet_p_duration_value">Value: Duration</string>
<string name="descr_statistics_sheet_p_recording_start_value">Value: Start of recording</string>
<string name="descr_statistics_sheet_p_recording_end_value">Value: End of recording</string>
<string name="descr_statistics_sheet_p_max_altitude">Value: Highest waypoint</string>
<string name="descr_statistics_sheet_p_min_altitude">Value: Lowest waypoint</string>
<string name="descr_statistics_sheet_p_positive_elevation">Value: Elevation (uphill)</string>
<string name="descr_statistics_sheet_p_negative_elevation">Value: Elevation (downhill)</string>
<string name="descr_track_selector">Dropdown menu for further tracks</string>
<string name="descr_export_button">Track export button</string>
<string name="descr_delete_button">Track delete button</string>