Use stats_core.xml layout for

- AggregatedStatsActivity
- StatsFragment
- MarkerDetailActivity
Remove StatsUtilities. Use StatsUtils to set all stats labels and values.
This commit is contained in:
Jimmy Shih
2012-04-20 12:50:22 -07:00
parent 8f7c44d1e7
commit aaef92b139
20 changed files with 630 additions and 1211 deletions
@@ -1,3 +1,19 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
@@ -5,88 +21,41 @@ import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import com.google.android.apps.mytracks.util.IntentUtils;
import com.google.android.apps.mytracks.util.StatsUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.speech.tts.TextToSpeech;
import android.view.MenuItem;
import android.widget.ScrollView;
import android.widget.TextView;
import java.util.List;
/**
* Activity for viewing the combined statistics for all the recorded tracks.
*
* Other features to add - menu items to change setings.
* An activity to view aggregated stats from all recorded tracks.
*
* @author Fergus Nelson
*/
public class AggregatedStatsActivity extends Activity implements
OnSharedPreferenceChangeListener {
private final StatsUtilities utils;
private MyTracksProviderUtils tracksProvider;
private boolean metricUnits = true;
public AggregatedStatsActivity() {
this.utils = new StatsUtilities(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
Log.d(Constants.TAG, "StatsActivity: onSharedPreferences changed "
+ key);
if (key != null) {
if (key.equals(getString(R.string.metric_units_key))) {
metricUnits = sharedPreferences.getBoolean(
getString(R.string.metric_units_key), true);
utils.setMetricUnits(metricUnits);
utils.updateUnits();
loadAggregatedStats();
}
}
}
public class AggregatedStatsActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.tracksProvider = MyTracksProviderUtils.Factory.get(this);
setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
ApiAdapterFactory.getApiAdapter().configureActionBarHomeAsUp(this);
setContentView(R.layout.stats);
ScrollView sv = ((ScrollView) findViewById(R.id.scrolly));
sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
setContentView(R.layout.aggregated_stats);
SharedPreferences preferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (preferences != null) {
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
preferences.registerOnSharedPreferenceChangeListener(this);
}
utils.setMetricUnits(metricUnits);
utils.updateUnits();
utils.setSpeedLabel(R.id.speed_label, R.string.stat_speed, R.string.stat_pace);
utils.setSpeedLabels();
boolean metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
boolean reportSpeed = preferences.getBoolean(getString(R.string.report_speed_key), true);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
if (metrics.heightPixels > 600) {
((TextView) findViewById(R.id.speed_register)).setTextSize(80.0f);
}
loadAggregatedStats();
StatsUtils.setSpeedLabels(this, reportSpeed, false);
StatsUtils.setTripStatisticsValues(this, getTripStatistics(), metricUnits, reportSpeed);
StatsUtils.setLocationElevationValue(this, Double.NaN, metricUnits);
}
@Override
@@ -100,30 +69,18 @@ public class AggregatedStatsActivity extends Activity implements
}
/**
* 1. Reads tracks from the db
* 2. Merges the trip stats from the tracks
* 3. Updates the view
* Gets the aggregated trip statistics for all the recorded tracks or null if
* there is no track.
*/
private void loadAggregatedStats() {
List<Track> tracks = retrieveTracks();
TripStatistics rollingStats = null;
private TripStatistics getTripStatistics() {
List<Track> tracks = MyTracksProviderUtils.Factory.get(this).getAllTracks();
TripStatistics tripStatistics = null;
if (!tracks.isEmpty()) {
rollingStats = new TripStatistics(tracks.iterator().next()
.getStatistics());
tripStatistics = new TripStatistics(tracks.iterator().next().getStatistics());
for (int i = 1; i < tracks.size(); i++) {
rollingStats.merge(tracks.get(i).getStatistics());
tripStatistics.merge(tracks.get(i).getStatistics());
}
}
updateView(rollingStats);
}
private List<Track> retrieveTracks() {
return tracksProvider.getAllTracks();
}
private void updateView(TripStatistics aggStats) {
if (aggStats != null) {
utils.setAllStats(aggStats);
}
return tripStatistics;
}
}
@@ -215,7 +215,7 @@ public class ChartView extends View {
R.color.elevation_border,
new ZoomSettings(MAX_INTERVALS,
new int[] {5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000}),
R.string.stat_elevation);
R.string.stats_elevation);
series[SPEED_SERIES] =
new ChartValueSeries(context,
@@ -223,7 +223,7 @@ public class ChartView extends View {
R.color.speed_border,
new ZoomSettings(MAX_INTERVALS, 0, Integer.MIN_VALUE,
new int[] {1, 5, 10, 20, 50}),
R.string.stat_speed);
R.string.stats_speed);
series[POWER_SERIES] =
new ChartValueSeries(context,
R.color.power_fill,
@@ -270,8 +270,8 @@ public class ChartView extends View {
public void setReportSpeed(boolean reportSpeed, Context c) {
series[SPEED_SERIES].setTitle(c.getString(reportSpeed
? R.string.stat_speed
: R.string.stat_pace));
? R.string.stats_speed
: R.string.stats_pace));
}
private void addDataPointInternal(double[] theData) {
@@ -19,7 +19,6 @@ package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.fragments.DeleteOneMarkerDialogFragment;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import com.google.android.apps.mytracks.util.IntentUtils;
import com.google.android.apps.mytracks.util.StatsUtils;
@@ -94,44 +93,9 @@ public class MarkerDetailActivity extends FragmentActivity {
boolean metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
boolean reportSpeed = preferences.getBoolean(getString(R.string.report_speed_key), true);
StatsUtils.setSpeedLabel(this, R.id.marker_detail_max_speed_label, R.string.stat_max_speed,
R.string.stat_fastest_pace, reportSpeed);
StatsUtils.setSpeedLabel(this, R.id.marker_detail_average_speed_label,
R.string.stat_average_speed, R.string.stat_average_pace, reportSpeed);
StatsUtils.setSpeedLabel(this, R.id.marker_detail_average_moving_speed_label,
R.string.stat_average_moving_speed, R.string.stat_average_moving_pace, reportSpeed);
TripStatistics tripStatistics = waypoint.getStatistics();
StatsUtils.setDistanceValue(this, R.id.marker_detail_total_distance_value,
tripStatistics.getTotalDistance(), metricUnits);
StatsUtils.setSpeedValue(this, R.id.marker_detail_max_speed_value,
tripStatistics.getMaxSpeed(), reportSpeed, metricUnits);
StatsUtils.setTimeValue(
this, R.id.marker_detail_total_time_value, tripStatistics.getTotalTime());
StatsUtils.setSpeedValue(this, R.id.marker_detail_average_speed_value,
tripStatistics.getAverageSpeed(), reportSpeed, metricUnits);
StatsUtils.setTimeValue(
this, R.id.marker_detail_moving_time_value, tripStatistics.getMovingTime());
StatsUtils.setSpeedValue(this, R.id.marker_detail_average_moving_speed_value,
tripStatistics.getAverageMovingSpeed(), reportSpeed, metricUnits);
StatsUtils.setAltitudeValue(this, R.id.marker_detail_elevation_value,
waypoint.getLocation().getAltitude(), metricUnits);
StatsUtils.setAltitudeValue(this, R.id.marker_detail_elevation_gain_value,
tripStatistics.getTotalElevationGain(), metricUnits);
StatsUtils.setAltitudeValue(this, R.id.marker_detail_min_elevation_value,
tripStatistics.getMinElevation(), metricUnits);
StatsUtils.setAltitudeValue(this, R.id.marker_detail_max_elevation_value,
tripStatistics.getMaxElevation(), metricUnits);
StatsUtils.setGradeValue(
this, R.id.marker_detail_min_grade_value, tripStatistics.getMinGrade());
StatsUtils.setGradeValue(
this, R.id.marker_detail_max_grade_value, tripStatistics.getMaxGrade());
StatsUtils.setSpeedLabels(this, reportSpeed, false);
StatsUtils.setTripStatisticsValues(this, waypoint.getStatistics(), metricUnits, reportSpeed);
StatsUtils.setLocationElevationValue(this, waypoint.getLocation().getAltitude(), metricUnits);
}
}
@@ -45,8 +45,6 @@ public class SensorStateActivity extends Activity {
private static final long REFRESH_PERIOD_MS = 250;
private final StatsUtilities utils;
/**
* This timer periodically invokes the refresh timer task.
*/
@@ -91,11 +89,6 @@ public class SensorStateActivity extends Activity {
*/
private boolean isVisible = false;
public SensorStateActivity() {
utils = new StatsUtilities(this);
Log.w(TAG, "SensorStateActivity()");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -239,18 +232,18 @@ public class SensorStateActivity extends Activity {
}
private void updateSensorData(Sensor.SensorDataSet sds) {
if (sds == null) {
utils.setUnknown(R.id.sensor_state_last_sensor_time);
utils.setUnknown(R.id.sensor_state_power);
utils.setUnknown(R.id.sensor_state_cadence);
utils.setUnknown(R.id.sensor_state_battery);
} else {
((TextView) findViewById(R.id.sensor_state_last_sensor_time)).setText(getLastSensorTime(sds));
((TextView) findViewById(R.id.sensor_state_power)).setText(getPower(sds));
((TextView) findViewById(R.id.sensor_state_cadence)).setText(getCadence(sds));
((TextView) findViewById(R.id.sensor_state_heart_rate)).setText(getHeartRate(sds));
((TextView) findViewById(R.id.sensor_state_battery)).setText(getBattery(sds));
}
String lastSensorTime = sds == null ? getString(R.string.value_unknown)
: getLastSensorTime(sds);
String power = sds == null ? getString(R.string.value_unknown) : getPower(sds);
String cadence = sds == null ? getString(R.string.value_unknown) : getCadence(sds);
String heartRate = sds == null ? getString(R.string.value_unknown) : getHeartRate(sds);
String battery = sds == null ? getString(R.string.value_unknown) : getBattery(sds);
((TextView) findViewById(R.id.sensor_state_last_sensor_time)).setText(lastSensorTime);
((TextView) findViewById(R.id.sensor_state_power)).setText(power);
((TextView) findViewById(R.id.sensor_state_cadence)).setText(cadence);
((TextView) findViewById(R.id.sensor_state_heart_rate)).setText(heartRate);
((TextView) findViewById(R.id.sensor_state_battery)).setText(battery);
}
/**
@@ -325,8 +318,7 @@ public class SensorStateActivity extends Activity {
String value;
if (sds.hasBatteryLevel() && sds.getBatteryLevel().hasValue()
&& sds.getBatteryLevel().getState() == Sensor.SensorState.SENDING) {
String format = getString(R.string.value_integer_percent);
value = String.format(format, sds.getBatteryLevel().getValue());
value = getString(R.string.value_integer_percent, sds.getBatteryLevel().getValue());
} else {
value = SensorUtils.getStateAsString(
sds.hasBatteryLevel() ? sds.getBatteryLevel().getState() : Sensor.SensorState.NONE, this);
@@ -1,270 +0,0 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.StatsUtils;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.util.Log;
import android.widget.TextView;
import java.text.NumberFormat;
/**
* Various utility functions for views that display statistics information.
*
* @deprecated use {@link StatsUtils}.
*
* @author Sandor Dornbush
*/
public class StatsUtilities {
private final Activity activity;
private static final NumberFormat LAT_LONG_FORMAT = NumberFormat.getNumberInstance();
private static final NumberFormat ALTITUDE_FORMAT = NumberFormat.getIntegerInstance();
private static final NumberFormat SPEED_FORMAT = NumberFormat.getNumberInstance();
private static final NumberFormat GRADE_FORMAT = NumberFormat.getPercentInstance();
static {
LAT_LONG_FORMAT.setMaximumFractionDigits(5);
LAT_LONG_FORMAT.setMinimumFractionDigits(5);
SPEED_FORMAT.setMaximumFractionDigits(2);
SPEED_FORMAT.setMinimumFractionDigits(2);
GRADE_FORMAT.setMaximumFractionDigits(1);
GRADE_FORMAT.setMinimumFractionDigits(1);
}
/**
* True if distances should be displayed in metric units (from shared
* preferences).
*/
private boolean metricUnits = true;
/**
* True - report speed
* False - report pace
*/
private boolean reportSpeed = true;
public StatsUtilities(Activity a) {
this.activity = a;
}
public boolean isMetricUnits() {
return metricUnits;
}
public void setMetricUnits(boolean metricUnits) {
this.metricUnits = metricUnits;
}
public boolean isReportSpeed() {
return reportSpeed;
}
public void setReportSpeed(boolean reportSpeed) {
this.reportSpeed = reportSpeed;
}
public void setUnknown(int id) {
((TextView) activity.findViewById(id)).setText(R.string.value_unknown);
}
public void setText(int id, double d, NumberFormat format) {
if (!Double.isNaN(d) && !Double.isInfinite(d)) {
setText(id, format.format(d));
} else {
setUnknown(id);
}
}
public void setText(int id, String s) {
int lengthLimit = 8;
String displayString = s.length() > lengthLimit
? s.substring(0, lengthLimit - 3) + "..."
: s;
((TextView) activity.findViewById(id)).setText(displayString);
}
public void setLatLong(int id, double d) {
TextView msgTextView = (TextView) activity.findViewById(id);
msgTextView.setText(LAT_LONG_FORMAT.format(d));
}
public void setAltitude(int id, double d) {
setText(id, (metricUnits ? d : (d * UnitConversions.M_TO_FT)),
ALTITUDE_FORMAT);
}
public void setDistance(int id, double d) {
setText(id, (metricUnits ? d : (d * UnitConversions.KM_TO_MI)),
SPEED_FORMAT);
}
public void setSpeed(int id, double d) {
if (d == 0) {
setUnknown(id);
return;
}
double speed = metricUnits ? d : d * UnitConversions.KM_TO_MI;
if (reportSpeed) {
setText(id, speed, SPEED_FORMAT);
} else {
// Format as milliseconds per unit
long pace = (long) (3600000.0 / speed);
setTime(id, pace);
}
}
public void setAltitudeUnits(int unitLabelId) {
TextView unitTextView = (TextView) activity.findViewById(unitLabelId);
unitTextView.setText(metricUnits ? R.string.unit_meter : R.string.unit_feet);
}
public void setDistanceUnits(int unitLabelId) {
TextView unitTextView = (TextView) activity.findViewById(unitLabelId);
unitTextView.setText(metricUnits ? R.string.unit_kilometer : R.string.unit_mile);
}
public void setSpeedUnits(int unitLabelId, int unitLabelBottomId) {
TextView unitTextView = (TextView) activity.findViewById(unitLabelId);
unitTextView.setText(reportSpeed
? (metricUnits ? R.string.unit_kilometer : R.string.unit_mile)
: R.string.unit_minute);
unitTextView = (TextView) activity.findViewById(unitLabelBottomId);
unitTextView.setText(reportSpeed
? R.string.unit_hour
: (metricUnits ? R.string.unit_kilometer : R.string.unit_mile));
}
public void setTime(int id, long l) {
setText(id, StringUtils.formatElapsedTime(l));
}
public void setGrade(int id, double d) {
setText(id, d, GRADE_FORMAT);
}
/**
* Updates the unit fields.
*/
public void updateUnits() {
setSpeedUnits(R.id.speed_unit_label_top, R.id.speed_unit_label_bottom);
updateWaypointUnits();
}
/**
* Updates the units fields used by waypoints.
*/
public void updateWaypointUnits() {
setSpeedUnits(R.id.average_moving_speed_unit_label_top,
R.id.average_moving_speed_unit_label_bottom);
setSpeedUnits(R.id.average_speed_unit_label_top,
R.id.average_speed_unit_label_bottom);
setDistanceUnits(R.id.total_distance_unit_label);
setSpeedUnits(R.id.max_speed_unit_label_top,
R.id.max_speed_unit_label_bottom);
setAltitudeUnits(R.id.elevation_unit_label);
setAltitudeUnits(R.id.elevation_gain_unit_label);
setAltitudeUnits(R.id.min_elevation_unit_label);
setAltitudeUnits(R.id.max_elevation_unit_label);
}
/**
* Sets all fields to "-" (unknown).
*/
public void setAllToUnknown() {
// "Instant" values:
setUnknown(R.id.elevation_register);
setUnknown(R.id.latitude_register);
setUnknown(R.id.longitude_register);
setUnknown(R.id.speed_register);
// Values from provider:
setUnknown(R.id.total_time_register);
setUnknown(R.id.moving_time_register);
setUnknown(R.id.total_distance_register);
setUnknown(R.id.average_speed_register);
setUnknown(R.id.average_moving_speed_register);
setUnknown(R.id.max_speed_register);
setUnknown(R.id.min_elevation_register);
setUnknown(R.id.max_elevation_register);
setUnknown(R.id.elevation_gain_register);
setUnknown(R.id.min_grade_register);
setUnknown(R.id.max_grade_register);
}
public void setAllStats(long movingTime, double totalDistance,
double averageSpeed, double averageMovingSpeed, double maxSpeed,
double minElevation, double maxElevation, double elevationGain,
double minGrade, double maxGrade) {
setTime(R.id.moving_time_register, movingTime);
setDistance(R.id.total_distance_register, totalDistance * UnitConversions.M_TO_KM);
setSpeed(R.id.average_speed_register, averageSpeed * UnitConversions.MS_TO_KMH);
setSpeed(R.id.average_moving_speed_register, averageMovingSpeed * UnitConversions.MS_TO_KMH);
setSpeed(R.id.max_speed_register, maxSpeed * UnitConversions.MS_TO_KMH);
setAltitude(R.id.min_elevation_register, minElevation);
setAltitude(R.id.max_elevation_register, maxElevation);
setAltitude(R.id.elevation_gain_register, elevationGain);
setGrade(R.id.min_grade_register, minGrade);
setGrade(R.id.max_grade_register, maxGrade);
}
public void setAllStats(TripStatistics stats) {
setTime(R.id.moving_time_register, stats.getMovingTime());
setDistance(R.id.total_distance_register, stats.getTotalDistance() * UnitConversions.M_TO_KM);
setSpeed(R.id.average_speed_register, stats.getAverageSpeed() * UnitConversions.MS_TO_KMH);
setSpeed(R.id.average_moving_speed_register,
stats.getAverageMovingSpeed() * UnitConversions.MS_TO_KMH);
setSpeed(R.id.max_speed_register, stats.getMaxSpeed() * UnitConversions.MS_TO_KMH);
setAltitude(R.id.min_elevation_register, stats.getMinElevation());
setAltitude(R.id.max_elevation_register, stats.getMaxElevation());
setAltitude(R.id.elevation_gain_register, stats.getTotalElevationGain());
setGrade(R.id.min_grade_register, stats.getMinGrade());
setGrade(R.id.max_grade_register, stats.getMaxGrade());
setTime(R.id.total_time_register, stats.getTotalTime());
}
public void setSpeedLabel(int id, int speedString, int paceString) {
Log.w(Constants.TAG, "Setting view " + id +
" to " + reportSpeed +
" speed: " + speedString +
" pace: " + paceString);
TextView tv = ((TextView) activity.findViewById(id));
if (tv != null) {
tv.setText(reportSpeed ? speedString : paceString);
} else {
Log.w(Constants.TAG, "Could not find id: " + id);
}
}
public void setSpeedLabels() {
setSpeedLabel(R.id.average_speed_label,
R.string.stat_average_speed,
R.string.stat_average_pace);
setSpeedLabel(R.id.average_moving_speed_label,
R.string.stat_average_moving_speed,
R.string.stat_average_moving_pace);
setSpeedLabel(R.id.max_speed_label,
R.string.stat_max_speed,
R.string.stat_fastest_pace);
}
}
@@ -63,7 +63,7 @@ public class ChartSettingsDialogFragment extends DialogFragment {
checkBoxes[i].setChecked(chartFragment.isChartValueSeriesEnabled(i));
}
checkBoxes[ChartView.SPEED_SERIES].setText(chartFragment.isReportSpeed()
? R.string.stat_speed : R.string.stat_pace);
? R.string.stats_speed : R.string.stats_pace);
return new AlertDialog.Builder(getActivity())
.setCancelable(true)
@@ -16,17 +16,20 @@
package com.google.android.apps.mytracks.fragments;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksApplication;
import com.google.android.apps.mytracks.StatsUtilities;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TrackDataHub;
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
import com.google.android.apps.mytracks.content.TrackDataListener;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.apps.mytracks.util.StatsUtils;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.Fragment;
@@ -34,7 +37,6 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ScrollView;
import java.util.EnumSet;
@@ -48,18 +50,22 @@ public class StatsFragment extends Fragment implements TrackDataListener {
private static final String TAG = StatsFragment.class.getSimpleName();
private StatsUtilities statsUtilities;
private TrackDataHub trackDataHub;
private UiUpdateThread uiUpdateThread;
// The start time of the current track.
private long startTime = -1L;
private boolean metricUnits = true;
private boolean reportSpeed = true;
private Location lastLocation = null;
private TripStatistics lastTripStatistics = null;
// A runnable to update the total time field.
private final Runnable updateTotalTime = new Runnable() {
public void run() {
if (isRecording()) {
statsUtilities.setTime(R.id.total_time_register, System.currentTimeMillis() - startTime);
StatsUtils.setTotalTimeValue(getActivity(), System.currentTimeMillis() - startTime);
}
}
};
@@ -68,7 +74,6 @@ public class StatsFragment extends Fragment implements TrackDataListener {
* A thread that updates the total time field every second.
*/
private class UiUpdateThread extends Thread {
@Override
public void run() {
Log.d(TAG, "UI update thread started");
@@ -85,12 +90,6 @@ public class StatsFragment extends Fragment implements TrackDataListener {
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
statsUtilities = new StatsUtilities(getActivity());
}
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -100,10 +99,11 @@ public class StatsFragment extends Fragment implements TrackDataListener {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ScrollView scrollView = (ScrollView) getActivity().findViewById(R.id.scrolly);
scrollView.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
updateLabels();
setLocationUnknown();
SharedPreferences preferences = getActivity().getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
reportSpeed = preferences.getBoolean(getString(R.string.report_speed_key), true);
updateUi();
}
@Override
@@ -128,7 +128,8 @@ public class StatsFragment extends Fragment implements TrackDataListener {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
setLocationUnknown();
lastLocation = null;
StatsUtils.setLocationValues(getActivity(), lastLocation, metricUnits, reportSpeed);
}
});
}
@@ -140,11 +141,8 @@ public class StatsFragment extends Fragment implements TrackDataListener {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (location != null) {
setLocation(location);
} else {
setLocationUnknown();
}
lastLocation = location;
StatsUtils.setLocationValues(getActivity(), lastLocation, metricUnits, reportSpeed);
}
});
}
@@ -172,16 +170,18 @@ public class StatsFragment extends Fragment implements TrackDataListener {
@Override
public void run() {
if (track == null || track.getStatistics() == null) {
statsUtilities.setAllToUnknown();
lastLocation = null;
lastTripStatistics = null;
updateUi();
return;
}
lastTripStatistics = track.getStatistics();
startTime = track.getStatistics().getStartTime();
if (!isRecording()) {
statsUtilities.setTime(R.id.total_time_register, track.getStatistics().getTotalTime());
setLocationUnknown();
lastLocation = null;
}
statsUtilities.setAllStats(track.getStatistics());
updateUi();
}
});
}
@@ -227,30 +227,24 @@ public class StatsFragment extends Fragment implements TrackDataListener {
}
@Override
public boolean onUnitsChanged(boolean metric) {
if (statsUtilities.isMetricUnits() == metric) {
return false;
}
statsUtilities.setMetricUnits(metric);
public boolean onUnitsChanged(final boolean metric) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
updateLabels();
metricUnits = metric;
updateUi();
}
});
return true;
}
@Override
public boolean onReportSpeedChanged(boolean speed) {
if (statsUtilities.isReportSpeed() == speed) {
return false;
}
statsUtilities.setReportSpeed(speed);
public boolean onReportSpeedChanged(final boolean speed) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
updateLabels();
reportSpeed = speed;
updateUi();
}
});
return true;
@@ -285,35 +279,10 @@ public class StatsFragment extends Fragment implements TrackDataListener {
private synchronized boolean isRecording() {
return trackDataHub != null && trackDataHub.isRecordingSelected();
}
/**
* Updates the labels.
*/
private void updateLabels() {
statsUtilities.updateUnits();
statsUtilities.setSpeedLabel(R.id.speed_label, R.string.stat_speed, R.string.stat_pace);
statsUtilities.setSpeedLabels();
}
/**
* Sets the current location.
*
* @param location the current location
*/
private void setLocation(Location location) {
statsUtilities.setAltitude(R.id.elevation_register, location.getAltitude());
statsUtilities.setLatLong(R.id.latitude_register, location.getLatitude());
statsUtilities.setLatLong(R.id.longitude_register, location.getLongitude());
statsUtilities.setSpeed(R.id.speed_register, location.getSpeed() * UnitConversions.MS_TO_KMH);
}
/**
* Sets the current location to unknown.
*/
private void setLocationUnknown() {
statsUtilities.setUnknown(R.id.elevation_register);
statsUtilities.setUnknown(R.id.latitude_register);
statsUtilities.setUnknown(R.id.longitude_register);
statsUtilities.setUnknown(R.id.speed_register);
private void updateUi() {
StatsUtils.setSpeedLabels(getActivity(), reportSpeed, true);
StatsUtils.setTripStatisticsValues(getActivity(), lastTripStatistics, metricUnits, reportSpeed);
StatsUtils.setLocationValues(getActivity(), lastLocation, metricUnits, reportSpeed);
}
}
@@ -58,7 +58,7 @@ public class ChartURLGenerator {
}
return getChartUrl(distances, elevations, track,
context.getString(R.string.stat_elevation), metricUnits);
context.getString(R.string.stats_elevation), metricUnits);
}
/**
@@ -16,9 +16,11 @@
package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.location.Location;
import android.widget.TextView;
/**
@@ -30,6 +32,114 @@ public class StatsUtils {
private StatsUtils() {}
/**
* Sets the speed labels.
*
* @param activity the activity
* @param reportSpeed true to report speed
* @param includeLocationSpeed true to include the current location speed
*/
public static void setSpeedLabels(
Activity activity, boolean reportSpeed, boolean includeLocationSpeed) {
StatsUtils.setSpeedLabel(activity, R.id.stats_max_speed_label, R.string.stats_max_speed,
R.string.stats_fastest_pace, reportSpeed);
StatsUtils.setSpeedLabel(activity, R.id.stats_average_speed_label, R.string.stats_average_speed,
R.string.stats_average_pace, reportSpeed);
StatsUtils.setSpeedLabel(activity, R.id.stats_average_moving_speed_label,
R.string.stats_average_moving_speed, R.string.stats_average_moving_pace, reportSpeed);
if (includeLocationSpeed) {
StatsUtils.setSpeedLabel(
activity, R.id.stats_speed_label, R.string.stats_speed, R.string.stats_pace, reportSpeed);
}
}
/**
* Sets the trip statistics values.
*
* @param activity the activity
* @param tripStatistics the trip statistics
* @param metricUnits true to display in metric units
* @param reportSpeed true to report speed
*/
public static void setTripStatisticsValues(
Activity activity, TripStatistics tripStatistics, boolean metricUnits, boolean reportSpeed) {
double totalDistance = tripStatistics == null ? Double.NaN : tripStatistics.getTotalDistance();
double maxSpeed = tripStatistics == null ? Double.NaN : tripStatistics.getMaxSpeed();
long totalTime = tripStatistics == null ? -1L : tripStatistics.getTotalTime();
double averageSpeed = tripStatistics == null ? Double.NaN : tripStatistics.getAverageSpeed();
long movingTime = tripStatistics == null ? -1L : tripStatistics.getMovingTime();
double averageMovingSpeed = tripStatistics == null ? Double.NaN
: tripStatistics.getAverageMovingSpeed();
double elevationGain = tripStatistics == null ? Double.NaN
: tripStatistics.getTotalElevationGain();
double minElevation = tripStatistics == null ? Double.NaN : tripStatistics.getMinElevation();
double maxElevation = tripStatistics == null ? Double.NaN : tripStatistics.getMaxElevation();
double minGrade = tripStatistics == null ? Double.NaN : tripStatistics.getMinGrade();
double maxGrade = tripStatistics == null ? Double.NaN : tripStatistics.getMaxGrade();
StatsUtils.setDistanceValue(
activity, R.id.stats_total_distance_value, totalDistance, metricUnits);
StatsUtils.setSpeedValue(
activity, R.id.stats_max_speed_value, maxSpeed, metricUnits, reportSpeed);
StatsUtils.setTimeValue(activity, R.id.stats_total_time_value, totalTime);
StatsUtils.setSpeedValue(
activity, R.id.stats_average_speed_value, averageSpeed, metricUnits, reportSpeed);
StatsUtils.setTimeValue(activity, R.id.stats_moving_time_value, movingTime);
StatsUtils.setSpeedValue(activity, R.id.stats_average_moving_speed_value, averageMovingSpeed,
metricUnits, reportSpeed);
StatsUtils.setAltitudeValue(
activity, R.id.stats_elevation_gain_value, elevationGain, metricUnits);
StatsUtils.setAltitudeValue(
activity, R.id.stats_min_elevation_value, minElevation, metricUnits);
StatsUtils.setAltitudeValue(
activity, R.id.stats_max_elevation_value, maxElevation, metricUnits);
StatsUtils.setGradeValue(activity, R.id.stats_min_grade_value, minGrade);
StatsUtils.setGradeValue(activity, R.id.stats_max_grade_value, maxGrade);
}
/**
* Sets the location values.
*
* @param activity the activity
* @param location the location
* @param metricUnits true to display in metric units
* @param reportSpeed true to report speed
*/
public static void setLocationValues(
Activity activity, Location location, boolean metricUnits, boolean reportSpeed) {
double speed = location == null ? Double.NaN : location.getSpeed();
double altitude = location == null ? Double.NaN : location.getAltitude();
double latitude = location == null ? Double.NaN : location.getLatitude();
double longitude = location == null ? Double.NaN : location.getLongitude();
StatsUtils.setSpeedValue(activity, R.id.stats_speed_value, speed, metricUnits, reportSpeed);
StatsUtils.setAltitudeValue(activity, R.id.stats_elevation_value, altitude, metricUnits);
StatsUtils.setCoordinateValue(activity, R.id.stats_latitude_value, latitude);
StatsUtils.setCoordinateValue(activity, R.id.stats_longitude_value, longitude);
}
/**
* Sets the location elevation value.
*
* @param activity the activity
* @param elevation the elevation in meters
* @param metricUnits true to display in metric units
*/
public static void setLocationElevationValue(
Activity activity, double elevation, boolean metricUnits) {
StatsUtils.setAltitudeValue(activity, R.id.stats_elevation_value, elevation, metricUnits);
}
/**
* Sets the total time value.
*
* @param activity the activity
* @param totalTime the total time
*/
public static void setTotalTimeValue(Activity activity, long totalTime) {
StatsUtils.setTimeValue(activity, R.id.stats_total_time_value, totalTime);
}
/**
* Sets a speed label.
*
@@ -39,7 +149,7 @@ public class StatsUtils {
* @param paceId the pace string id
* @param reportSpeed true to report speed
*/
public static void setSpeedLabel(
private static void setSpeedLabel(
Activity activity, int id, int speedId, int paceId, boolean reportSpeed) {
TextView textView = (TextView) activity.findViewById(id);
textView.setText(reportSpeed ? speedId : paceId);
@@ -51,30 +161,34 @@ public class StatsUtils {
* @param activity the activity
* @param id the speed value resource id
* @param speed the speed in meters per second
* @param reportSpeed true to report speed
* @param metricUnits true to display in metric units
* @param reportSpeed true to report speed
*/
public static void setSpeedValue(
Activity activity, int id, double speed, boolean reportSpeed, boolean metricUnits) {
private static void setSpeedValue(
Activity activity, int id, double speed, boolean metricUnits, boolean reportSpeed) {
TextView textView = (TextView) activity.findViewById(id);
speed *= UnitConversions.MS_TO_KMH;
String value;
if (metricUnits) {
if (reportSpeed) {
value = activity.getString(R.string.value_float_kilometer_hour, speed);
} else {
// convert from hours to minutes
double pace = speed == 0 ? 0.0 : 60.0 / speed;
value = activity.getString(R.string.value_float_minute_kilometer, pace);
}
if (Double.isNaN(speed) || Double.isInfinite(speed)) {
value = activity.getString(R.string.value_unknown);
} else {
speed *= UnitConversions.KM_TO_MI;
if (reportSpeed) {
value = activity.getString(R.string.value_float_mile_hour, speed);
speed *= UnitConversions.MS_TO_KMH;
if (metricUnits) {
if (reportSpeed) {
value = activity.getString(R.string.value_float_kilometer_hour, speed);
} else {
// convert from hours to minutes
double pace = speed == 0 ? 0.0 : 60.0 / speed;
value = activity.getString(R.string.value_float_minute_kilometer, pace);
}
} else {
// convert from hours to minutes
double pace = speed == 0 ? 0.0 : 60.0 / speed;
value = activity.getString(R.string.value_float_minute_mile, pace);
speed *= UnitConversions.KM_TO_MI;
if (reportSpeed) {
value = activity.getString(R.string.value_float_mile_hour, speed);
} else {
// convert from hours to minutes
double pace = speed == 0 ? 0.0 : 60.0 / speed;
value = activity.getString(R.string.value_float_minute_mile, pace);
}
}
}
textView.setText(value);
@@ -88,16 +202,20 @@ public class StatsUtils {
* @param distance the distance in meters
* @param metricUnits true to display in metric units
*/
public static void setDistanceValue(
private static void setDistanceValue(
Activity activity, int id, double distance, boolean metricUnits) {
TextView textView = (TextView) activity.findViewById(id);
distance *= UnitConversions.M_TO_KM;
String value;
if (metricUnits) {
value = activity.getString(R.string.value_float_kilometer, distance);
if (Double.isNaN(distance) || Double.isInfinite(distance)) {
value = activity.getString(R.string.value_unknown);
} else {
distance *= UnitConversions.KM_TO_MI;
value = activity.getString(R.string.value_float_mile, distance);
distance *= UnitConversions.M_TO_KM;
if (metricUnits) {
value = activity.getString(R.string.value_float_kilometer, distance);
} else {
distance *= UnitConversions.KM_TO_MI;
value = activity.getString(R.string.value_float_mile, distance);
}
}
textView.setText(value);
}
@@ -109,9 +227,11 @@ public class StatsUtils {
* @param id the time value resource id
* @param time the time
*/
public static void setTimeValue(Activity activity, int id, long time) {
private static void setTimeValue(Activity activity, int id, long time) {
TextView textView = (TextView) activity.findViewById(id);
textView.setText(StringUtils.formatElapsedTime(time));
String value = time == -1L ? activity.getString(R.string.value_unknown)
: StringUtils.formatElapsedTime(time);
textView.setText(value);
}
/**
@@ -122,7 +242,7 @@ public class StatsUtils {
* @param altitude the altitude in meters
* @param metricUnits true to display in metric units
*/
public static void setAltitudeValue(
private static void setAltitudeValue(
Activity activity, int id, double altitude, boolean metricUnits) {
TextView textView = (TextView) activity.findViewById(id);
String value;
@@ -146,7 +266,7 @@ public class StatsUtils {
* @param id the grade value resource id
* @param grade the grade in fraction between 0 and 1
*/
public static void setGradeValue(Activity activity, int id, double grade) {
private static void setGradeValue(Activity activity, int id, double grade) {
TextView textView = (TextView) activity.findViewById(id);
String value;
if (Double.isNaN(grade) || Double.isInfinite(grade)) {
@@ -156,4 +276,23 @@ public class StatsUtils {
}
textView.setText(value);
}
/**
* Sets a coordinate value.
*
* @param activity the activity
* @param id the coordinate value resource id
* @param coordinate the coordinate in degrees
*/
private static void setCoordinateValue(Activity activity, int id, double coordinate) {
TextView textView = (TextView) activity.findViewById(id);
String value;
if (Double.isNaN(coordinate) || Double.isInfinite(coordinate)) {
value = activity.getString(R.string.value_unknown);
} else {
value = activity.getString(
R.string.value_coordinate_degree, Location.convert(coordinate, Location.FORMAT_DEGREES));
}
textView.setText(value);
}
}