diff --git a/MyTracks/res/layout/track_widget.xml b/MyTracks/res/layout/track_widget.xml
index c43096b4c..d6e33c462 100644
--- a/MyTracks/res/layout/track_widget.xml
+++ b/MyTracks/res/layout/track_widget.xml
@@ -14,71 +14,72 @@ 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.
-->
-
-
+ android:padding="@dimen/widget_margin" >
+ android:layout_width="fill_parent"
+ android:orientation="horizontal" >
+
-
-
-
-
-
-
-
-
-
-
-
-
+ android:clickable="true"
+ android:id="@+id/track_widget_statistics"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:orientation="vertical"
+ android:paddingLeft="8dp" >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/MyTracks/res/values-v14/dimens.xml b/MyTracks/res/values-v14/dimens.xml
new file mode 100644
index 000000000..344b6ad05
--- /dev/null
+++ b/MyTracks/res/values-v14/dimens.xml
@@ -0,0 +1,19 @@
+
+
+
+ 0dp
+
\ No newline at end of file
diff --git a/MyTracks/res/values/colors.xml b/MyTracks/res/values/colors.xml
index 7776ac17a..c2935ec0b 100644
--- a/MyTracks/res/values/colors.xml
+++ b/MyTracks/res/values/colors.xml
@@ -49,8 +49,8 @@ limitations under the License.
#FF401465
#40401465
-
- #99999999
+
+ #99999999
#F774DF00
diff --git a/MyTracks/res/values/dimens.xml b/MyTracks/res/values/dimens.xml
new file mode 100644
index 000000000..11c778950
--- /dev/null
+++ b/MyTracks/res/values/dimens.xml
@@ -0,0 +1,19 @@
+
+
+
+ 8dp
+
\ No newline at end of file
diff --git a/MyTracks/res/values/styles.xml b/MyTracks/res/values/styles.xml
index cd6dae0d8..04f9c5ae7 100644
--- a/MyTracks/res/values/styles.xml
+++ b/MyTracks/res/values/styles.xml
@@ -157,8 +157,13 @@ limitations under the License.
-
-
+
+
\ No newline at end of file
diff --git a/MyTracks/res/xml/stats_settings.xml b/MyTracks/res/xml/stats_settings.xml
index 9186c4a09..42c628a51 100644
--- a/MyTracks/res/xml/stats_settings.xml
+++ b/MyTracks/res/xml/stats_settings.xml
@@ -29,8 +29,8 @@ limitations under the License.
-
diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/StatsUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/StatsUtils.java
index 32e49af82..07ebe5634 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/util/StatsUtils.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/util/StatsUtils.java
@@ -220,31 +220,7 @@ public class StatsUtils {
private static void setSpeedValue(
Activity activity, int id, double speed, boolean metricUnits, boolean reportSpeed) {
TextView textView = (TextView) activity.findViewById(id);
- String value;
- if (Double.isNaN(speed) || Double.isInfinite(speed)) {
- value = activity.getString(R.string.value_unknown);
- } else {
- 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 {
- 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);
+ textView.setText(StringUtils.formatSpeed(activity, speed, metricUnits, reportSpeed));
}
/**
@@ -258,19 +234,7 @@ public class StatsUtils {
private static void setDistanceValue(
Activity activity, int id, double distance, boolean metricUnits) {
TextView textView = (TextView) activity.findViewById(id);
- String value;
- if (Double.isNaN(distance) || Double.isInfinite(distance)) {
- value = activity.getString(R.string.value_unknown);
- } else {
- 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);
+ textView.setText(StringUtils.formatDistance(activity, distance, metricUnits));
}
/**
diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java
index 4046d7f41..3ac00583f 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java
@@ -108,23 +108,26 @@ public class StringUtils {
/**
* Formats the distance.
- *
+ *
* @param context the context
* @param distance the distance in meters
- * @param metric true to use metric. False to use imperial
+ * @param metricUnits true to use metric units. False to use imperial units
*/
- public static String formatDistance(Context context, double distance, boolean metric) {
- if (metric) {
- if (distance > 2000.0) {
+ public static String formatDistance(Context context, double distance, boolean metricUnits) {
+ if (Double.isNaN(distance) || Double.isInfinite(distance)) {
+ return context.getString(R.string.value_unknown);
+ }
+ if (metricUnits) {
+ if (distance > 1000.0) {
distance *= UnitConversions.M_TO_KM;
return context.getString(R.string.value_float_kilometer, distance);
} else {
- return context.getString(R.string.value_float_meter, distance);
+ return context.getString(R.string.value_float_meter, distance);
}
} else {
- if (distance * UnitConversions.M_TO_MI > 2) {
+ if (distance * UnitConversions.M_TO_MI > 1) {
distance *= UnitConversions.M_TO_MI;
- return context.getString(R.string.value_float_mile, distance);
+ return context.getString(R.string.value_float_mile, distance);
} else {
distance *= UnitConversions.M_TO_FT;
return context.getString(R.string.value_float_feet, distance);
@@ -137,29 +140,31 @@ public class StringUtils {
*
* @param context the context
* @param speed the speed in meters per second
- * @param metric true to use metric. False to use imperial
+ * @param metricUnits true to use metric units. False to use imperial units
* @param reportSpeed true to report as speed. False to report as pace
*/
public static String formatSpeed(
- Context context, double speed, boolean metric, boolean reportSpeed) {
+ Context context, double speed, boolean metricUnits, boolean reportSpeed) {
if (Double.isNaN(speed) || Double.isInfinite(speed)) {
return context.getString(R.string.value_unknown);
}
- if (metric) {
- speed = speed * UnitConversions.MS_TO_KMH;
+ speed *= UnitConversions.MS_TO_KMH;
+ if (metricUnits) {
if (reportSpeed) {
return context.getString(R.string.value_float_kilometer_hour, speed);
} else {
- double paceInMinute = speed == 0 ? 0.0 : 60 / speed;
- return context.getString(R.string.value_float_minute_kilometer, paceInMinute);
+ // convert from hours to minutes
+ double pace = speed == 0 ? 0.0 : 60.0 / speed;
+ return context.getString(R.string.value_float_minute_kilometer, pace);
}
} else {
- speed = speed * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI;
+ speed *= UnitConversions.KM_TO_MI;
if (reportSpeed) {
return context.getString(R.string.value_float_mile_hour, speed);
} else {
- double paceInMinute = speed == 0 ? 0.0 : 60 / speed;
- return context.getString(R.string.value_float_minute_mile, paceInMinute);
+ // convert from hours to minutes
+ double pace = speed == 0 ? 0.0 : 60.0 / speed;
+ return context.getString(R.string.value_float_minute_mile, pace);
}
}
}
diff --git a/MyTracks/src/com/google/android/apps/mytracks/widgets/TrackWidgetProvider.java b/MyTracks/src/com/google/android/apps/mytracks/widgets/TrackWidgetProvider.java
index c92f92984..d02a5eb11 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/widgets/TrackWidgetProvider.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/widgets/TrackWidgetProvider.java
@@ -17,7 +17,6 @@
package com.google.android.apps.mytracks.widgets;
import static com.google.android.apps.mytracks.Constants.SETTINGS_NAME;
-import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.TrackDetailActivity;
import com.google.android.apps.mytracks.TrackListActivity;
@@ -41,66 +40,77 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.os.Handler;
-import android.util.Log;
import android.widget.RemoteViews;
/**
- * An AppWidgetProvider for displaying key track statistics (distance, time,
- * speed) from the current or most recent track.
- *
+ * A track widget to start/stop recording, launch My Tracks, and display track
+ * statistics (distance, time, speed) for the selected track or the last track.
+ *
* @author Sandor Dornbush
* @author Paul R. Saxman
*/
-public class TrackWidgetProvider
- extends AppWidgetProvider
+public class TrackWidgetProvider extends AppWidgetProvider
implements OnSharedPreferenceChangeListener {
- class TrackObserver extends ContentObserver {
+ /**
+ * Observer for track content.
+ *
+ * @author Jimmy Shih
+ */
+ private class TrackObserver extends ContentObserver {
public TrackObserver() {
- super(contentHandler);
+ super(handler);
}
+ @Override
public void onChange(boolean selfChange) {
updateTrack(null);
}
}
- private final Handler contentHandler;
- private MyTracksProviderUtils providerUtils;
+ private final Handler handler;
private Context context;
- private String unknown;
private TrackObserver trackObserver;
+ private MyTracksProviderUtils myTracksProviderUtils;
+
+ private String unknown;
+ private String trackStartedBroadcastAction;
+ private String trackStoppedBroadcastAction;
+
+ private SharedPreferences sharedPreferences;
+ private long selectedTrackId;
private boolean metricUnits;
private boolean reportSpeed;
- private long selectedTrackId;
- private SharedPreferences sharedPreferences;
- private String TRACK_STARTED_ACTION;
- private String TRACK_STOPPED_ACTION;
+ private boolean useTotalTime;
public TrackWidgetProvider() {
super();
- contentHandler = new Handler();
- selectedTrackId = PreferencesUtils.SELECTED_TRACK_ID_DEFAULT;
+ handler = new Handler();
}
- private void initialize(Context aContext) {
- if (this.context != null) {
- return;
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
+ if (key == null || PreferencesUtils.getKey(context, R.string.metric_units_key).equals(key)) {
+ metricUnits = PreferencesUtils.getBoolean(
+ context, R.string.metric_units_key, PreferencesUtils.METRIC_UNITS_DEFAULT);
+ }
+ if (key == null || PreferencesUtils.getKey(context, R.string.report_speed_key).equals(key)) {
+ reportSpeed = PreferencesUtils.getBoolean(
+ context, R.string.report_speed_key, PreferencesUtils.REPORT_SPEED_DEFAULT);
+ }
+ if (key == null
+ || PreferencesUtils.getKey(context, R.string.stats_use_total_time_key).equals(key)) {
+ useTotalTime = PreferencesUtils.getBoolean(context, R.string.stats_use_total_time_key,
+ PreferencesUtils.STATS_USE_TOTAL_TIME_DEFAULT);
+ }
+ if (key == null
+ || PreferencesUtils.getKey(context, R.string.selected_track_id_key).equals(key)) {
+ selectedTrackId = PreferencesUtils.getLong(context, R.string.selected_track_id_key);
+ }
+ if (key != null) {
+ updateTrack(null);
}
- this.context = aContext;
- trackObserver = new TrackObserver();
- providerUtils = MyTracksProviderUtils.Factory.get(context);
- unknown = context.getString(R.string.value_unknown);
-
- sharedPreferences = context.getSharedPreferences(SETTINGS_NAME, Context.MODE_PRIVATE);
- sharedPreferences.registerOnSharedPreferenceChangeListener(this);
- onSharedPreferenceChanged(sharedPreferences, null);
-
- context.getContentResolver().registerContentObserver(
- TracksColumns.CONTENT_URI, true, trackObserver);
- TRACK_STARTED_ACTION = context.getString(R.string.track_started_broadcast_action);
- TRACK_STOPPED_ACTION = context.getString(R.string.track_stopped_broadcast_action);
}
@Override
@@ -111,43 +121,62 @@ public class TrackWidgetProvider
selectedTrackId = intent.getLongExtra(
context.getString(R.string.track_id_broadcast_extra), selectedTrackId);
String action = intent.getAction();
- Log.d(TAG,
- "TrackWidgetProvider.onReceive: trackId=" + selectedTrackId + ", action=" + action);
if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)
- || TRACK_STARTED_ACTION.equals(action)
- || TRACK_STOPPED_ACTION.equals(action)) {
+ || trackStartedBroadcastAction.equals(action)
+ || trackStoppedBroadcastAction.equals(action)) {
updateTrack(action);
}
}
@Override
public void onDisabled(Context aContext) {
- if (trackObserver != null) {
- aContext.getContentResolver().unregisterContentObserver(trackObserver);
- }
if (sharedPreferences != null) {
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
}
+ if (trackObserver != null) {
+ aContext.getContentResolver().unregisterContentObserver(trackObserver);
+ }
}
- private void updateTrack(String action) {
- Track track = null;
- if (selectedTrackId != PreferencesUtils.SELECTED_TRACK_ID_DEFAULT) {
- Log.d(TAG, "TrackWidgetProvider.updateTrack: Retrieving specified track.");
- track = providerUtils.getTrack(selectedTrackId);
- } else {
- Log.d(TAG, "TrackWidgetProvider.updateTrack: Attempting to retrieve previous track.");
- // TODO we should really read the pref.
- track = providerUtils.getLastTrack();
+ /**
+ * Initializes the widget.
+ *
+ * @param aContext a context
+ */
+ private void initialize(Context aContext) {
+ if (context != null) {
+ // Already initialized
+ return;
}
+ context = aContext;
+ trackObserver = new TrackObserver();
+ myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
+
+ unknown = context.getString(R.string.value_unknown);
+ trackStartedBroadcastAction = context.getString(R.string.track_started_broadcast_action);
+ trackStoppedBroadcastAction = context.getString(R.string.track_stopped_broadcast_action);
+
+ sharedPreferences = context.getSharedPreferences(SETTINGS_NAME, Context.MODE_PRIVATE);
+ sharedPreferences.registerOnSharedPreferenceChangeListener(this);
+ onSharedPreferenceChanged(sharedPreferences, null);
+
+ context.getContentResolver()
+ .registerContentObserver(TracksColumns.CONTENT_URI, true, trackObserver);
+ }
- AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
- ComponentName widget = new ComponentName(context, TrackWidgetProvider.class);
- RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.track_widget);
+ /**
+ * Updates the widget.
+ *
+ * @param action the action
+ */
+ private void updateTrack(String action) {
+ Track track = selectedTrackId != PreferencesUtils.SELECTED_TRACK_ID_DEFAULT ? myTracksProviderUtils
+ .getTrack(selectedTrackId)
+ : myTracksProviderUtils.getLastTrack();
+ RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.track_widget);
- // Make all of the stats open the mytracks activity.
Intent intent;
if (track != null) {
intent = IntentUtils.newIntent(context, TrackDetailActivity.class)
@@ -156,92 +185,68 @@ public class TrackWidgetProvider
intent = IntentUtils.newIntent(context, TrackListActivity.class);
}
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
- views.setOnClickPendingIntent(R.id.appwidget_track_statistics, pendingIntent);
+ remoteViews.setOnClickPendingIntent(R.id.track_widget_statistics, pendingIntent);
if (action != null) {
- updateViewButton(views, action);
+ updateButton(remoteViews, action);
}
- updateViewTrackStatistics(views, track);
- int[] appWidgetIds = appWidgetManager.getAppWidgetIds(widget);
+ updateStatistics(remoteViews, track);
+
+ AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+ int[] appWidgetIds = appWidgetManager.getAppWidgetIds(
+ new ComponentName(context, TrackWidgetProvider.class));
for (int appWidgetId : appWidgetIds) {
- appWidgetManager.updateAppWidget(appWidgetId, views);
+ appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
/**
- * Update the widget's button with the appropriate intent and icon.
- *
- * @param views The RemoteViews containing the button
- * @param action The action broadcast from the track service
+ * Updates button to start/stop recording.
+ *
+ * @param remoteViews the remote views
+ * @param action the action
*/
- private void updateViewButton(RemoteViews views, String action) {
- if (TRACK_STARTED_ACTION.equals(action)) {
- // If a new track is started by this appwidget or elsewhere,
- // toggle the button to active and have it disable the track if pressed.
- setButtonIntent(views, R.string.track_action_end, R.drawable.app_widget_button_enabled);
+ private void updateButton(RemoteViews remoteViews, String action) {
+ int trackAction = trackStartedBroadcastAction.equals(action) ? R.string.track_action_end
+ : R.string.track_action_start;
+ int icon = trackStartedBroadcastAction.equals(action) ? R.drawable.app_widget_button_enabled
+ : R.drawable.app_widget_button_disabled;
+ Intent intent = new Intent(context, ControlRecordingService.class).setAction(
+ context.getString(trackAction));
+ PendingIntent pendingIntent = PendingIntent.getService(
+ context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ remoteViews.setOnClickPendingIntent(R.id.track_widget_button, pendingIntent);
+ remoteViews.setImageViewResource(R.id.track_widget_button, icon);
+ }
+
+ /**
+ * Updates statistics.
+ *
+ * @param remoteViews the remote views
+ * @param track the track
+ */
+ private void updateStatistics(RemoteViews remoteViews, Track track) {
+ TripStatistics tripStatistics = track == null ? null : track.getStatistics();
+ String distance = tripStatistics == null ? unknown
+ : StringUtils.formatDistance(context, tripStatistics.getTotalDistance(), metricUnits);
+ int timeLabelId = useTotalTime ? R.string.stats_total_time : R.string.stats_moving_time;
+ String time = tripStatistics == null ? unknown : StringUtils.formatElapsedTime(
+ useTotalTime ? tripStatistics.getTotalTime()
+ : tripStatistics.getMovingTime());
+ int speedLabelId;
+ if (useTotalTime) {
+ speedLabelId = reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace;
} else {
- // If a track is stopped by this appwidget or elsewhere,
- // toggle the button to inactive and have it start a new track if pressed.
- setButtonIntent(views, R.string.track_action_start, R.drawable.app_widget_button_disabled);
- }
- }
-
- /**
- * Set up the main widget button.
- *
- * @param views The widget views
- * @param action The resource id of the action to fire when the button is pressed
- * @param icon The resource id of the icon to show for the button
- */
- private void setButtonIntent(RemoteViews views, int action, int icon) {
- Intent intent = new Intent(context, ControlRecordingService.class)
- .setAction(context.getString(action));
- PendingIntent pendingIntent = PendingIntent.getService(context, 0,
- intent, PendingIntent.FLAG_UPDATE_CURRENT);
- views.setOnClickPendingIntent(R.id.appwidget_button, pendingIntent);
- views.setImageViewResource(R.id.appwidget_button, icon);
- }
-
- /**
- * Update the specified widget's view with the distance, time, and speed of
- * the specified track.
- *
- * @param views The RemoteViews to update with statistics
- * @param track The track to extract statistics from.
- */
- protected void updateViewTrackStatistics(RemoteViews views, Track track) {
- if (track == null) {
- views.setTextViewText(R.id.appwidget_distance_text, unknown);
- views.setTextViewText(R.id.appwidget_time_text, unknown);
- views.setTextViewText(R.id.appwidget_speed_text, unknown);
- return;
- }
-
- TripStatistics stats = track.getStatistics();
- String distance = StringUtils.formatDistance(context, stats.getTotalDistance(), metricUnits);
- String time = StringUtils.formatElapsedTime(stats.getMovingTime());
- String speed = StringUtils.formatSpeed(
- context, stats.getAverageMovingSpeed(), metricUnits, reportSpeed);
-
- views.setTextViewText(R.id.appwidget_distance_text, distance);
- views.setTextViewText(R.id.appwidget_time_text, time);
- views.setTextViewText(R.id.appwidget_speed_text, speed);
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
- if (key == null || PreferencesUtils.getKey(context, R.string.metric_units_key).equals(key)) {
- metricUnits = PreferencesUtils.getBoolean(
- context, R.string.metric_units_key, PreferencesUtils.METRIC_UNITS_DEFAULT);
- }
- if (key == null || PreferencesUtils.getKey(context, R.string.report_speed_key).equals(key)) {
- reportSpeed = PreferencesUtils.getBoolean(
- context, R.string.report_speed_key, PreferencesUtils.REPORT_SPEED_DEFAULT);
- }
- if (key == null
- || PreferencesUtils.getKey(context, R.string.selected_track_id_key).equals(key)) {
- selectedTrackId = PreferencesUtils.getLong(context, R.string.selected_track_id_key);
- Log.d(TAG, "TrackWidgetProvider setting selecting track from preference: " + selectedTrackId);
+ speedLabelId = reportSpeed ? R.string.stats_average_moving_speed
+ : R.string.stats_average_moving_pace;
}
+ String speed = tripStatistics == null ? unknown : StringUtils.formatSpeed(
+ context, useTotalTime ? tripStatistics.getAverageSpeed()
+ : tripStatistics.getAverageMovingSpeed(), metricUnits, reportSpeed);
+ remoteViews.setTextViewText(R.id.track_widget_distance_value, distance);
+ remoteViews.setTextViewText(R.id.track_widget_time_label, context.getString(timeLabelId));
+ remoteViews.setTextViewText(R.id.track_widget_time_value, time);
+ remoteViews.setTextViewText(R.id.track_widget_speed_label, context.getString(speedLabelId));
+ remoteViews.setTextViewText(R.id.track_widget_speed_value, speed);
}
}