diff --git a/.hgignore b/.hgignore index 1c3f1f5a7..ffa8823b5 100644 --- a/.hgignore +++ b/.hgignore @@ -7,3 +7,5 @@ syntax:glob MyTracksTest/annotations.log **/*.pyc **/*.pyo +syntax: glob +MyTracksTest/hs_err_pid*.log diff --git a/MyTracks/.classpath b/MyTracks/.classpath index 4a0943047..b65e415b1 100644 --- a/MyTracks/.classpath +++ b/MyTracks/.classpath @@ -1,13 +1,24 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyTracks/.project b/MyTracks/.project index 5a87d6231..4ff12bb43 100644 --- a/MyTracks/.project +++ b/MyTracks/.project @@ -1,41 +1,41 @@ - - - MyTracks - - - MyTracksLib - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - - - MyTracksLib_src - 2 - _android_MyTracksLib_e2802071/src - - - + + + MyTracks + + + MyTracksLib + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + MyTracksLib_src + 2 + _android_MyTracksLib_e2802071/src + + + diff --git a/MyTracks/default.properties b/MyTracks/default.properties index ee3f68e34..75e62f9cb 100644 --- a/MyTracks/default.properties +++ b/MyTracks/default.properties @@ -13,7 +13,5 @@ split.density=false target=Google Inc.:Google APIs:13 android.library.reference.1=../MyTracksLib/ -# ProGuard is turned off while we investigate the removal of code that -# isn't actually dead from Fusion Tables. See issue 303 for an example of -# the result of that removal. -#proguard.config=proguard.cfg +# Enable proguard. +proguard.config=proguard.cfg diff --git a/MyTracks/libs/README.txt b/MyTracks/libs/README.txt index 62e619f85..0df5b07bb 100644 --- a/MyTracks/libs/README.txt +++ b/MyTracks/libs/README.txt @@ -3,12 +3,20 @@ own licenses, which allow their usage for the My Tracks application. Any other applications that wish to use these files should consult the appropriate licenses or the JAR's authors. -References are provided to the libraries: +google-api-client/ +- see http://code.google.com/p/google-api-java-client/. +- contains Google API client library, google-api-client-1.5.0-beta.jar, and its + dependencies. +- google-api-client-1.5.0-beta.jar depends on protobuf-java-2.2.0.jar, however, + MyTracksLib already includes protobuf-java.2.3.0-lite.jar. Thus using the + newer version, protobuf-java.2.3.0-lite.jar. +- google-api-client-1.5.0-beta.jar also depends on xpp3-1.1.4c.jar, however, + some of its classes are already included in the android framework, thus not + including xpp3-1.1.4c.jar. -google-api-client-*.jar (GData client): -http://code.google.com/p/google-api-java-client/ +google-common.jar -google-common.jar, -googleloginclient-helper.jar, -libmymaps.jar (Google My Maps upload library): -Licensed exclusively for use in My Tracks and derived Android applications. +googleloginclient-helper.jar + +libGoogleAnalytics.jar +- see http://code.google.com/mobile/analytics/docs/. diff --git a/MyTracks/libs/google-api-client-1.2.2-alpha.jar b/MyTracks/libs/google-api-client-1.2.2-alpha.jar deleted file mode 100644 index 7194648fd..000000000 Binary files a/MyTracks/libs/google-api-client-1.2.2-alpha.jar and /dev/null differ diff --git a/MyTracks/libs/google-api-client/commons-codec-1.3.jar b/MyTracks/libs/google-api-client/commons-codec-1.3.jar new file mode 100644 index 000000000..957b6752a Binary files /dev/null and b/MyTracks/libs/google-api-client/commons-codec-1.3.jar differ diff --git a/MyTracks/libs/google-api-client/commons-logging-1.1.1.jar b/MyTracks/libs/google-api-client/commons-logging-1.1.1.jar new file mode 100644 index 000000000..1deef144c Binary files /dev/null and b/MyTracks/libs/google-api-client/commons-logging-1.1.1.jar differ diff --git a/MyTracks/libs/google-api-client/google-api-client-1.5.0-beta.jar b/MyTracks/libs/google-api-client/google-api-client-1.5.0-beta.jar new file mode 100644 index 000000000..41f2e578e Binary files /dev/null and b/MyTracks/libs/google-api-client/google-api-client-1.5.0-beta.jar differ diff --git a/MyTracks/libs/google-api-client/google-http-client-1.5.0-beta.jar b/MyTracks/libs/google-api-client/google-http-client-1.5.0-beta.jar new file mode 100644 index 000000000..b5e610ddf Binary files /dev/null and b/MyTracks/libs/google-api-client/google-http-client-1.5.0-beta.jar differ diff --git a/MyTracks/libs/google-api-client/google-oauth-client-1.5.0-beta.jar b/MyTracks/libs/google-api-client/google-oauth-client-1.5.0-beta.jar new file mode 100644 index 000000000..af73e9aa4 Binary files /dev/null and b/MyTracks/libs/google-api-client/google-oauth-client-1.5.0-beta.jar differ diff --git a/MyTracks/libs/google-api-client/gson-1.6.jar b/MyTracks/libs/google-api-client/gson-1.6.jar new file mode 100644 index 000000000..40648939f Binary files /dev/null and b/MyTracks/libs/google-api-client/gson-1.6.jar differ diff --git a/MyTracks/libs/google-api-client/guava-r09.jar b/MyTracks/libs/google-api-client/guava-r09.jar new file mode 100644 index 000000000..30dbc5692 Binary files /dev/null and b/MyTracks/libs/google-api-client/guava-r09.jar differ diff --git a/MyTracks/libs/google-api-client/httpclient-4.0.3.jar b/MyTracks/libs/google-api-client/httpclient-4.0.3.jar new file mode 100644 index 000000000..16e349a48 Binary files /dev/null and b/MyTracks/libs/google-api-client/httpclient-4.0.3.jar differ diff --git a/MyTracks/libs/google-api-client/httpcore-4.0.1.jar b/MyTracks/libs/google-api-client/httpcore-4.0.1.jar new file mode 100644 index 000000000..4aef35e2f Binary files /dev/null and b/MyTracks/libs/google-api-client/httpcore-4.0.1.jar differ diff --git a/MyTracks/libs/google-api-client/jackson-core-asl-1.6.7.jar b/MyTracks/libs/google-api-client/jackson-core-asl-1.6.7.jar new file mode 100644 index 000000000..7c1207210 Binary files /dev/null and b/MyTracks/libs/google-api-client/jackson-core-asl-1.6.7.jar differ diff --git a/MyTracks/libs/google-api-client/jsr305-1.3.9.jar b/MyTracks/libs/google-api-client/jsr305-1.3.9.jar new file mode 100644 index 000000000..a9afc6619 Binary files /dev/null and b/MyTracks/libs/google-api-client/jsr305-1.3.9.jar differ diff --git a/MyTracks/libs/google-api-client/junit-4.8.2.jar b/MyTracks/libs/google-api-client/junit-4.8.2.jar new file mode 100644 index 000000000..5b4bb849a Binary files /dev/null and b/MyTracks/libs/google-api-client/junit-4.8.2.jar differ diff --git a/MyTracks/proguard.cfg b/MyTracks/proguard.cfg index 8a6087a72..8b178c6b8 100644 --- a/MyTracks/proguard.cfg +++ b/MyTracks/proguard.cfg @@ -51,3 +51,15 @@ -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } + +# Needed by google-api-client to keep generic types and @Key annotations accessed via reflection + +-keepclassmembers class * { + @com.google.api.client.util.Key ; +} + +-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault + +# Needed by Guava + +-dontwarn sun.misc.Unsafe diff --git a/MyTracks/res/values/arrays_do_not_translate.xml b/MyTracks/res/values/arrays_do_not_translate.xml index 25f173930..89c48c308 100644 --- a/MyTracks/res/values/arrays_do_not_translate.xml +++ b/MyTracks/res/values/arrays_do_not_translate.xml @@ -118,4 +118,16 @@ limitations under the License. @string/ant_sensor_type @string/srm_ant_bridge_sensor_type + + + @string/track_color_mode_none + @string/track_color_mode_fixed + @string/track_color_mode_dynamic + + + + @string/none + @string/track_color_mode_fixed + @string/track_color_mode_dynamic + diff --git a/MyTracks/res/values/colors.xml b/MyTracks/res/values/colors.xml index 803446580..eca05f9d7 100644 --- a/MyTracks/res/values/colors.xml +++ b/MyTracks/res/values/colors.xml @@ -51,4 +51,14 @@ limitations under the License. #EDEDED #99999999 + + + + #F774DF00 + + + #F75858FA + + + #F7DF0101 diff --git a/MyTracks/res/values/keys.xml b/MyTracks/res/values/keys.xml index 24794476e..add11edba 100644 --- a/MyTracks/res/values/keys.xml +++ b/MyTracks/res/values/keys.xml @@ -41,7 +41,13 @@ limitations under the License. shareUrlOnly splitFrequency timestampTrackName - + trackColorMode + trackColorModeFixedSlow + trackColorModeFixedMedium + trackColorModeFixedSlowDisplay + trackColorModeFixedMediumDisplay + trackColorModeDynamicVariation + autoResumeTrackCurrentRetry recordingTrack @@ -54,4 +60,5 @@ limitations under the License. sensorOptions antOptions displaySettingsScreen + trackColorModeFixedOptions diff --git a/MyTracks/res/values/strings.xml b/MyTracks/res/values/strings.xml index 0f78c57a2..2ab353a40 100644 --- a/MyTracks/res/values/strings.xml +++ b/MyTracks/res/values/strings.xml @@ -268,6 +268,17 @@ limitations under the License. The bluetooth sensor to connect to Modular Stats Display + Track Color Mode + The way to color the track + Fixed + Dynamic + Fixed Speed Slow + Slow speed top value + Fixed Speed Medium + Medium speed top value + Dynamic Speed Variation + % Margin from average speed to consider medium speed + Backup (BETA) SD Card Backup @@ -483,7 +494,10 @@ limitations under the License. bluetoothSensorsEnabled ANT options Sensor Options - + Track Color Mode + Fixed Speed Options + Dynamic Speed Options + Connected to %s Bluetooth sensor connecting ... @@ -517,4 +531,8 @@ limitations under the License. Polar Bluetooth Zephyr Bluetooth + + None + Fixed (BETA) + Dynamic (BETA) diff --git a/MyTracks/res/xml/preferences.xml b/MyTracks/res/xml/preferences.xml index b1dfb8ee9..f4cb8d523 100644 --- a/MyTracks/res/xml/preferences.xml +++ b/MyTracks/res/xml/preferences.xml @@ -33,6 +33,58 @@ limitations under the License. android:summaryOn="@string/settings_report_speed_or_pace_summary_on" android:summaryOff="@string/settings_report_speed_or_pace_summary_off" android:defaultValue="true" /> + + + + + + + + + + + + + + + + + + + + + diff --git a/MyTracks/src/com/google/android/apps/mytracks/ColoredPath.java b/MyTracks/src/com/google/android/apps/mytracks/ColoredPath.java new file mode 100644 index 000000000..be34ced2a --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/ColoredPath.java @@ -0,0 +1,62 @@ +/* + * Copyright 2011 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 android.graphics.Paint; +import android.graphics.Path; + +/** + * Represents a colored {@code Path} to save its relative color for drawing. + * @author Vangelis S. + */ +public class ColoredPath { + private final Path path; + private final Paint pathPaint; + + /** + * Constructor for a ColoredPath by color. + */ + public ColoredPath(int color) { + path = new Path(); + pathPaint = new Paint(); + pathPaint.setColor(color); + pathPaint.setStrokeWidth(3); + pathPaint.setStyle(Paint.Style.STROKE); + pathPaint.setAntiAlias(true); + } + + /** + * Constructor for a ColoredPath by Paint. + */ + public ColoredPath(Paint paint) { + path = new Path(); + pathPaint = paint; + } + + /** + * @return the path + */ + public Path getPath() { + return path; + } + + /** + * @return the pathPaint + */ + public Paint getPathPaint() { + return pathPaint; + } +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java b/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java index e36c76197..dfea7d5d5 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java +++ b/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java @@ -217,4 +217,4 @@ public class ImportAllTracks { } return gpxFiles; } -} +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/MapOverlay.java b/MyTracks/src/com/google/android/apps/mytracks/MapOverlay.java index 0203d8d6b..b26d4a0b0 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MapOverlay.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MapOverlay.java @@ -18,6 +18,9 @@ package com.google.android.apps.mytracks; import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.content.Waypoint; +import com.google.android.apps.mytracks.maps.TrackPathPainter; +import com.google.android.apps.mytracks.maps.TrackPathPainterFactory; +import com.google.android.apps.mytracks.maps.TrackPathUtilities; import com.google.android.apps.mytracks.util.LocationUtils; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapView; @@ -27,6 +30,8 @@ import com.google.android.maps.mytracks.R; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Paint; @@ -48,7 +53,7 @@ import java.util.concurrent.BlockingQueue; * * @author Leif Hendrik Wilden */ -public class MapOverlay extends Overlay { +public class MapOverlay extends Overlay implements OnSharedPreferenceChangeListener { private final Drawable[] arrows; private final int arrowWidth, arrowHeight; @@ -57,7 +62,6 @@ public class MapOverlay extends Overlay { private final Drawable startMarker; private final Drawable endMarker; private final int markerWidth, markerHeight; - private final Paint selectedTrackPaint; private final Paint errorCirclePaint; private final Context context; private final List waypoints; @@ -73,22 +77,26 @@ public class MapOverlay extends Overlay { private GeoPoint lastReferencePoint; private Rect lastViewRect; - private Path lastPath; + private boolean lastPathExists; + private Location lastLocation; + private TrackPathPainter trackPathPainter; /** * Represents a pre-processed {@code Location} to speed up drawing. * This class is more like a data object and doesn't provide accessors. */ - private static class CachedLocation { + public static class CachedLocation { public final boolean valid; public final GeoPoint geoPoint; - + public final int speed; + /** * Constructor for an invalid cached location. */ public CachedLocation() { this.valid = false; this.geoPoint = null; + this.speed = -1; } /** @@ -97,6 +105,7 @@ public class MapOverlay extends Overlay { public CachedLocation(Location location) { this.valid = LocationUtils.isValidLocation(location); this.geoPoint = valid ? LocationUtils.getGeoPoint(location) : null; + this.speed = (int) Math.floor(location.getSpeed() * 3.6); } }; @@ -151,18 +160,13 @@ public class MapOverlay extends Overlay { waypointMarker = resources.getDrawable(R.drawable.blue_pushpin); waypointMarker.setBounds(0, 0, markerWidth, markerHeight); - selectedTrackPaint = new Paint(); - selectedTrackPaint.setColor(resources.getColor(R.color.red)); - selectedTrackPaint.setStrokeWidth(3); - selectedTrackPaint.setStyle(Paint.Style.STROKE); - selectedTrackPaint.setAntiAlias(true); - - errorCirclePaint = new Paint(); - errorCirclePaint.setColor(resources.getColor(R.color.blue)); - errorCirclePaint.setStyle(Paint.Style.STROKE); - errorCirclePaint.setStrokeWidth(3); + errorCirclePaint = TrackPathUtilities.getPaint(R.color.blue, context); errorCirclePaint.setAlpha(127); - errorCirclePaint.setAntiAlias(true); + + trackPathPainter = TrackPathPainterFactory.getTrackPathPainter(context); + + context.getSharedPreferences(Constants.SETTINGS_NAME, 0) + .registerOnSharedPreferenceChangeListener(this); } /** @@ -205,18 +209,19 @@ public class MapOverlay extends Overlay { } // Visible for testing. - int getNumWaypoints() { + public int getNumWaypoints() { synchronized (waypoints) { return waypoints.size(); } } public void clearPoints() { - synchronized (points) { - points.clear(); + synchronized (getPoints()) { + getPoints().clear(); pendingPoints.clear(); - lastPath = null; + lastPathExists = false; lastViewRect = null; + trackPathPainter.clear(); } } @@ -254,6 +259,9 @@ public class MapOverlay extends Overlay { // Draw the selected track: drawTrack(canvas, projection, viewRect); + // Draw the "Start" and "End" markers: + drawMarkers(canvas, projection); + // Draw the waypoints: drawWaypoints(canvas, projection); } @@ -262,6 +270,28 @@ public class MapOverlay extends Overlay { drawMyLocation(canvas, projection); } + private void drawMarkers(Canvas canvas, Projection projection) { + // Draw the "End" marker. + if (showEndMarker) { + for (int i = getPoints().size() - 1; i >= 0; --i) { + if (getPoints().get(i).valid) { + drawElement(canvas, projection, getPoints().get(i).geoPoint, endMarker, + -markerWidth / 2, -markerHeight); + break; + } + } + } + + // Draw the "Start" marker. + for (int i = 0; i < getPoints().size(); ++i) { + if (getPoints().get(i).valid) { + drawElement(canvas, projection, getPoints().get(i).geoPoint, startMarker, + -markerWidth / 2, -markerHeight); + break; + } + } + } + // Visible for testing. Projection getMapProjection(MapView mapView) { return mapView.getProjection(); @@ -282,10 +312,10 @@ public class MapOverlay extends Overlay { } // Visible for testing. - Path getLastPath() { - return lastPath; + public Path getLastPath() { + return trackPathPainter.getLastPath(); } - + private void drawWaypoints(Canvas canvas, Projection projection) { synchronized (waypoints) {; for (Waypoint wpt : waypoints) { @@ -311,96 +341,39 @@ public class MapOverlay extends Overlay { canvas.drawCircle(pt.x, pt.y, radius, errorCirclePaint); } - private void drawTrack(Canvas canvas, Projection projection, Rect viewRect) { - Path path; + private void drawTrack(Canvas canvas, Projection projection, Rect viewRect) + { + boolean draw; + synchronized (points) { // Merge the pending points with the list of cached locations. final GeoPoint referencePoint = projection.fromPixels(0, 0); - int newPoints = pendingPoints.drainTo(points); + int newPoints = pendingPoints.drainTo(points); boolean newProjection = !viewRect.equals(lastViewRect) || - !referencePoint.equals(lastReferencePoint); - if (newPoints == 0 && lastPath != null && !newProjection) { + !referencePoint.equals(lastReferencePoint); + if (newPoints == 0 && lastPathExists && !newProjection) { // No need to recreate path (same points and viewing area). - path = lastPath; + draw = true; } else { int numPoints = points.size(); if (numPoints < 2) { // Not enough points to draw a path. - path = null; - } else if (lastPath != null && !newProjection) { + draw = false; + } else if (!trackPathPainter.needsRedraw() && lastPathExists && !newProjection) { // Incremental update of the path, without repositioning the view. - path = lastPath; - updatePath(projection, viewRect, path, numPoints - newPoints); + draw = true; + trackPathPainter.updatePath(projection, viewRect, numPoints - newPoints, alwaysVisible, points); } else { // The view has changed so we have to start from scratch. - path = newPath(); - path.incReserve(numPoints); - updatePath(projection, viewRect, path, 0); + draw = true; + trackPathPainter.updatePath(projection, viewRect, 0, alwaysVisible, points); } - lastPath = path; } lastReferencePoint = referencePoint; lastViewRect = viewRect; } - if (path != null) { - canvas.drawPath(path, selectedTrackPaint); - } - - // Draw the "End" marker. - if (showEndMarker) { - for (int i = points.size() - 1; i >= 0; --i) { - if (points.get(i).valid) { - drawElement(canvas, projection, points.get(i).geoPoint, endMarker, - -markerWidth / 2, -markerHeight); - break; - } - } - } - - // Draw the "Start" marker. - for (int i = 0; i < points.size(); ++i) { - if (points.get(i).valid) { - drawElement(canvas, projection, points.get(i).geoPoint, startMarker, - -markerWidth / 2, -markerHeight); - break; - } - } - } - - private void updatePath(Projection projection, Rect viewRect, Path path, - int startLocationIdx) { - // Whether to start a new segment on new valid and visible point. - boolean newSegment = - startLocationIdx > 0 ? !points.get(startLocationIdx - 1).valid : true; - boolean lastVisible = !newSegment; - final Point pt = new Point(); - // Loop over track points. - for (int i = startLocationIdx; i < points.size(); ++i) { - CachedLocation loc = points.get(i); - // Check if valid, if not then indicate a new segment. - if (!loc.valid) { - newSegment = true; - continue; - } - - final GeoPoint geoPoint = loc.geoPoint; - // Check if this breaks the existing segment. - boolean visible = alwaysVisible || viewRect.contains( - geoPoint.getLongitudeE6(), geoPoint.getLatitudeE6()); - if (!visible && !lastVisible) { - // This is a point outside view not connected to a visible one. - newSegment = true; - } - lastVisible = visible; - - // Either move to beginning of a new segment or continue the old one. - projection.toPixels(geoPoint, pt); - if (newSegment) { - path.moveTo(pt.x, pt.y); - newSegment = false; - } else { - path.lineTo(pt.x, pt.y); - } + if (draw) { + trackPathPainter.drawTrack(canvas); } } @@ -479,4 +452,21 @@ public class MapOverlay extends Overlay { } return super.onTap(p, mapView); } + + /** + * @return the points + */ + public List getPoints() { + return points; + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + Log.d(TAG, "MapOverlay: onSharedPreferences changed " + key); + if (key != null) { + if (key.equals(context.getString(R.string.track_color_mode_key))) { + trackPathPainter = TrackPathPainterFactory.getTrackPathPainter(context); + } + } + } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/SettingsActivity.java b/MyTracks/src/com/google/android/apps/mytracks/SettingsActivity.java index 960deb69b..559d9af31 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/SettingsActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/SettingsActivity.java @@ -23,6 +23,7 @@ import com.google.android.apps.mytracks.services.sensors.ant.AntUtils; import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory; import com.google.android.apps.mytracks.util.ApiFeatures; import com.google.android.apps.mytracks.util.BluetoothDeviceUtils; +import com.google.android.apps.mytracks.util.UnitConversions; import com.google.android.maps.mytracks.R; import android.app.AlertDialog; @@ -32,11 +33,13 @@ import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.CheckBoxPreference; +import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceActivity; +import android.preference.PreferenceCategory; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.provider.Settings; @@ -128,7 +131,8 @@ public class SettingsActivity extends PreferenceActivity { updatePreferenceUnits(metricUnitsPreference.isChecked()); customizeSensorOptionsPreferences(); - + customizeTrackColorModePreferences(); + // Hook up action for resetting all settings Preference resetPreference = findPreference(getString(R.string.reset_key)); resetPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() { @@ -203,6 +207,29 @@ public class SettingsActivity extends PreferenceActivity { sensorOptionsScreen.removePreference(findPreference(getString(R.string.ant_options_key))); } } + + private void customizeTrackColorModePreferences() { + ListPreference trackColorModePreference = + (ListPreference) findPreference(getString(R.string.track_color_mode_key)); + trackColorModePreference.setOnPreferenceChangeListener( + new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, + Object newValue) { + updateTrackColorModeSettings((String) newValue); + return true; + } + }); + updateTrackColorModeSettings(trackColorModePreference.getValue()); + + setTrackColorModePreferenceListeners(); + + PreferenceCategory speedOptionsCategory = + (PreferenceCategory) findPreference(getString(R.string.track_color_mode_fixed_speed_options_key)); + + speedOptionsCategory.removePreference(findPreference(getString(R.string.track_color_mode_fixed_speed_slow_key))); + speedOptionsCategory.removePreference(findPreference(getString(R.string.track_color_mode_fixed_speed_medium_key))); + } @Override protected void onResume() { @@ -288,6 +315,18 @@ public class SettingsActivity extends PreferenceActivity { } } + private void updateTrackColorModeSettings(String trackColorMode) { + boolean usesFixedSpeed = trackColorMode.equals(getString(R.string.track_color_mode_fixed)); + boolean usesDynamicSpeed = trackColorMode.equals(getString(R.string.track_color_mode_dynamic)); + + findPreference( + getString(R.string.track_color_mode_fixed_speed_slow_display_key)).setEnabled(usesFixedSpeed); + findPreference( + getString(R.string.track_color_mode_fixed_speed_medium_display_key)).setEnabled(usesFixedSpeed); + findPreference( + getString(R.string.track_color_mode_dynamic_speed_variation_key)).setEnabled(usesDynamicSpeed); + } + /** * Updates all the preferences which give options with distance units to use * the proper unit the user has selected. @@ -416,4 +455,84 @@ public class SettingsActivity extends PreferenceActivity { } }.start(); } + + /** + * Set the given edit text preference text. + * If the units are not metric convert the value before displaying. + */ + private void viewTrackColorModeSettings(EditTextPreference preference, int id) { + CheckBoxPreference metricUnitsPreference = (CheckBoxPreference) findPreference( + getString(R.string.metric_units_key)); + if(metricUnitsPreference.isChecked()) { + return; + } + // Convert miles/h to km/h + SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); + String metricspeed = prefs.getString(getString(id), null); + int englishspeed; + try { + englishspeed = (int) (Double.parseDouble(metricspeed) * UnitConversions.KMH_TO_MPH); + } catch (NumberFormatException e) { + englishspeed = 0; + } + preference.getEditText().setText(String.valueOf(englishspeed)); + } + + /** + * Saves the given edit text preference value. + * If the units are not metric convert the value before saving. + */ + private void validateTrackColorModeSettings(EditTextPreference preference, + String newValue, int id) { + CheckBoxPreference metricUnitsPreference = (CheckBoxPreference) findPreference( + getString(R.string.metric_units_key)); + String metricspeed; + if(!metricUnitsPreference.isChecked()) { + // Convert miles/h to km/h + try { + metricspeed = String.valueOf((int) (Double.parseDouble(newValue) * UnitConversions.MPH_TO_KMH) + 1); + } catch (NumberFormatException e) { + metricspeed = "0"; + } + } else { + metricspeed = newValue; + } + SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); + prefs.edit().putString(getString(id), metricspeed).commit(); + } + + /** + * Sets the TrackColorMode preference listeners. + */ + private void setTrackColorModePreferenceListeners() { + setTrackColorModePreferenceListener(R.string.track_color_mode_fixed_speed_slow_display_key, + R.string.track_color_mode_fixed_speed_slow_key); + setTrackColorModePreferenceListener(R.string.track_color_mode_fixed_speed_medium_display_key, + R.string.track_color_mode_fixed_speed_medium_key); + } + + /** + * Sets a TrackColorMode preference listener. + */ + private void setTrackColorModePreferenceListener(int displayKey, final int metricKey) { + EditTextPreference trackColorModePreference = + (EditTextPreference) findPreference(getString(displayKey)); + trackColorModePreference.setOnPreferenceChangeListener( + new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, + Object newValue) { + validateTrackColorModeSettings((EditTextPreference) preference, (String) newValue, metricKey); + return true; + } + }); + trackColorModePreference.setOnPreferenceClickListener( + new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + viewTrackColorModeSettings((EditTextPreference) preference, metricKey); + return true; + } + }); + } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java b/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java index f830abe6d..f8b7e1f69 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java @@ -26,20 +26,23 @@ import com.google.android.apps.mytracks.io.gdata.GDataWrapper; import com.google.android.apps.mytracks.io.gdata.GDataWrapper.QueryFunction; import com.google.android.apps.mytracks.stats.DoubleBuffer; import com.google.android.apps.mytracks.stats.TripStatistics; +import com.google.android.apps.mytracks.util.ApiFeatures; import com.google.android.apps.mytracks.util.LocationUtils; import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.apps.mytracks.util.SystemUtils; import com.google.android.apps.mytracks.util.UnitConversions; import com.google.android.maps.mytracks.R; import com.google.api.client.googleapis.GoogleHeaders; -import com.google.api.client.googleapis.MethodOverrideIntercepter; +import com.google.api.client.googleapis.MethodOverride; import com.google.api.client.http.GenericUrl; import com.google.api.client.http.HttpRequest; +import com.google.api.client.http.HttpRequestFactory; import com.google.api.client.http.HttpResponse; import com.google.api.client.http.HttpResponseException; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.InputStreamContent; -import com.google.api.client.javanet.NetHttpTransport; +import com.google.api.client.http.apache.ApacheHttpTransport; +import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.util.Strings; import android.app.Activity; @@ -64,6 +67,8 @@ import java.util.Vector; */ public class SendToFusionTables implements Runnable { + private static final String CONTENT_TYPE = "application/x-www-form-urlencoded"; + /** * Listener invoked when sending to fusion tables completes. */ @@ -118,22 +123,15 @@ public class SendToFusionTables implements Runnable { private int totalLocations; private int totalSegmentsUploaded; - private HttpTransport transport; + private HttpRequestFactory httpRequestFactory; private String tableId; private static String MARKER_TYPE_START = "large_green"; private static String MARKER_TYPE_END = "large_red"; private static String MARKER_TYPE_WAYPOINT = "large_yellow"; - static { - // We manually assign the transport to avoid having HttpTransport try to - // load it via reflection (which breaks due to ProGuard). - HttpTransport.setLowLevelHttpTransport(new NetHttpTransport()); - } - - public SendToFusionTables(Activity context, AuthManager auth, - long trackId, ProgressIndicator progressIndicator, - OnSendCompletedListener onCompletion) { + public SendToFusionTables(Activity context, AuthManager auth, long trackId, + ProgressIndicator progressIndicator, OnSendCompletedListener onCompletion) { this.context = context; this.auth = auth; this.trackId = trackId; @@ -142,13 +140,9 @@ public class SendToFusionTables implements Runnable { this.stringUtils = new StringUtils(context); this.providerUtils = MyTracksProviderUtils.Factory.get(context); - GoogleHeaders headers = new GoogleHeaders(); - headers.setApplicationName("Google-MyTracks-" + SystemUtils.getMyTracksVersion(context)); - headers.gdataVersion = GDATA_VERSION; - - transport = new HttpTransport(); - MethodOverrideIntercepter.setAsFirstFor(transport); - transport.defaultHeaders = headers; + HttpTransport transport = ApiFeatures.getInstance().useNetHttpTransport() + ? new NetHttpTransport() : new ApacheHttpTransport(); + httpRequestFactory = transport.createRequestFactory(new MethodOverride()); } @Override @@ -177,7 +171,6 @@ public class SendToFusionTables implements Runnable { } private void doUpload() { - ((GoogleHeaders) transport.defaultHeaders).setGoogleLogin(auth.getAuthToken()); int statusMessageId = R.string.error_sending_to_fusiontables; boolean success = true; try { @@ -280,7 +273,7 @@ public class SendToFusionTables implements Runnable { * * @param name the marker name * @param description the marker description - * @param the marker location + * @param location the marker location * @return true in case of success. */ private boolean createNewPoint(String name, String description, Location location, @@ -306,7 +299,6 @@ public class SendToFusionTables implements Runnable { } private boolean uploadAllTrackPoints(final Track track, String originalDescription) { - SharedPreferences preferences = context.getSharedPreferences(Constants.SETTINGS_NAME, 0); boolean metricUnits = true; if (preferences != null) { @@ -440,10 +432,10 @@ public class SendToFusionTables implements Runnable { } /** - * Returns a KML Point tag for the given location. + * Returns a KML LineString. * - * @param location The location. - * @return the kml. + * @param track the track. + * @return the KML LineString. */ private String getKmlLineString(Track track) { StringBuilder builder = new StringBuilder(""); @@ -500,7 +492,7 @@ public class SendToFusionTables implements Runnable { * Prepares a buffer of locations for transmission to google fusion tables. * * @param track the original track with meta data - * @param buffer a buffer of locations on the track + * @param locations locations on the track * @return an array of tracks each with a sub section of the points in the * original buffer */ @@ -665,33 +657,40 @@ public class SendToFusionTables implements Runnable { * @return true in case of success */ private boolean runUpdate(final String query) { - GDataWrapper wrapper = new GDataWrapper(); + GDataWrapper wrapper = new GDataWrapper(); wrapper.setAuthManager(auth); wrapper.setRetryOnAuthFailure(true); - wrapper.setClient(transport); + wrapper.setClient(httpRequestFactory); Log.d(Constants.TAG, "GData connection prepared: " + this.auth); - wrapper.runQuery(new QueryFunction() { + wrapper.runQuery(new QueryFunction() { @Override - public void query(HttpTransport client) + public void query(HttpRequestFactory factory) throws IOException, GDataWrapper.ParseException, GDataWrapper.HttpException, GDataWrapper.AuthenticationException { - HttpRequest request = transport.buildPostRequest(); - request.headers.contentType = "application/x-www-form-urlencoded"; GenericUrl url = new GenericUrl(FUSIONTABLES_BASE_FEED_URL); - request.url = url; - InputStreamContent isc = new InputStreamContent(); - String sql = "sql=" + URLEncoder.encode(query, "UTF-8"); - isc.inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql)); - request.content = isc; + String sql = "sql=" + URLEncoder.encode(query, "UTF-8"); + ByteArrayInputStream inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql)); + InputStreamContent isc = new InputStreamContent(null, inputStream ); + + HttpRequest request = factory.buildPostRequest(url, isc); + + GoogleHeaders headers = new GoogleHeaders(); + headers.setApplicationName("Google-MyTracks-" + SystemUtils.getMyTracksVersion(context)); + headers.gdataVersion = GDATA_VERSION; + headers.setGoogleLogin(auth.getAuthToken()); + headers.setContentType(CONTENT_TYPE); + request.setHeaders(headers); + Log.d(Constants.TAG, "Running update query " + url.toString() + ": " + sql); HttpResponse response; try { response = request.execute(); } catch (HttpResponseException e) { - throw new GDataWrapper.HttpException(e.response.statusCode, e.response.statusMessage); + throw new GDataWrapper.HttpException(e.getResponse().getStatusCode(), + e.getResponse().getStatusMessage()); } - boolean success = response.isSuccessStatusCode; + boolean success = response.isSuccessStatusCode(); if (success) { byte[] result = new byte[1024]; int read = response.getContent().read(result); @@ -704,9 +703,11 @@ public class SendToFusionTables implements Runnable { Log.w(Constants.TAG, "Unrecognized response: " + lines[0]); } } else { - Log.d(Constants.TAG, "Query failed: " + response.statusMessage + " (" + - response.statusCode + ")"); - throw new GDataWrapper.HttpException(response.statusCode, response.statusMessage); + Log.d(Constants.TAG, + "Query failed: " + response.getStatusMessage() + " (" + + response.getStatusCode() + ")"); + throw new GDataWrapper.HttpException( + response.getStatusCode(), response.getStatusMessage()); } } }); diff --git a/MyTracks/src/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathDescriptor.java b/MyTracks/src/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathDescriptor.java new file mode 100644 index 000000000..f6fc968d5 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathDescriptor.java @@ -0,0 +1,129 @@ +/* + * Copyright 2011 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.maps; + +import static com.google.android.apps.mytracks.Constants.TAG; + +import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.stats.TripStatistics; +import com.google.android.maps.mytracks.R; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.util.Log; + + +/** + * A dynamic speed path descriptor. + * + * @author Vangelis S. + */ +public class DynamicSpeedTrackPathDescriptor + implements TrackPathDescriptor, OnSharedPreferenceChangeListener { + private int slowSpeed; + private int normalSpeed; + private int speedMargin; + private double averageMovingSpeed; + private final Context context; + + public DynamicSpeedTrackPathDescriptor(Context context){ + this.context = context; + SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0); + + if (prefs == null) { + speedMargin = 25; + return; + } + prefs.registerOnSharedPreferenceChangeListener(this); + + speedMargin = Integer.parseInt(prefs.getString( + context.getString(R.string.track_color_mode_dynamic_speed_variation_key), "25")); + } + + /** + * Get the slow speed calculated based on the % below the average speed. + * @return The speed limit considered as slow. + */ + public int getSlowSpeed() + { + slowSpeed = (int) (averageMovingSpeed - (averageMovingSpeed * speedMargin / 100)); + return slowSpeed; + } + + /** + * Get the medium speed calculated based on the % above the average speed. + * @return The speed limit considered as normal. + */ + public int getNormalSpeed() + { + normalSpeed = (int) (averageMovingSpeed + (averageMovingSpeed * speedMargin / 100)); + return normalSpeed; + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + Log.d(TAG, "DynamicSpeedTrackPathDescriptor: onSharedPreferences changed " + key); + if (key == null + || !key.equals(context.getString(R.string.track_color_mode_dynamic_speed_variation_key))) { + return; + } + SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0); + + if (prefs == null) { + speedMargin = 25; + return; + } + + speedMargin = + Integer.parseInt( + prefs.getString( + context.getString(R.string.track_color_mode_dynamic_speed_variation_key), "25")); + } + + @Override + public boolean needsRedraw() { + SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0); + long currentTrackId = prefs.getLong(context.getString(R.string.selected_track_key), -1); + if(currentTrackId == -1) { + // Could not find track. + return false; + } + Track track = MyTracksProviderUtils.Factory.get(context).getTrack(currentTrackId); + TripStatistics stats = track.getStatistics(); + double newaverageSpeed = (int) Math.floor(stats.getAverageMovingSpeed() * 3.6); + + if(averageMovingSpeed == 0) { + averageMovingSpeed = newaverageSpeed; + return true; + } + + double difference = Math.max(averageMovingSpeed, newaverageSpeed); + + if (difference == 0.0) { + difference = 0.0; + } else { + difference = Math.abs(averageMovingSpeed - newaverageSpeed) / difference * 100; + } + if(difference >= 20) { + averageMovingSpeed = newaverageSpeed; + return true; + } + return false; + } +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathPainter.java b/MyTracks/src/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathPainter.java new file mode 100644 index 000000000..2234f8b8f --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathPainter.java @@ -0,0 +1,141 @@ +/* + * Copyright 2011 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.maps; + +import com.google.android.apps.mytracks.ColoredPath; +import com.google.android.apps.mytracks.MapOverlay.CachedLocation; +import com.google.android.maps.GeoPoint; +import com.google.android.maps.Projection; +import com.google.android.maps.mytracks.R; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Point; +import android.graphics.Rect; + +import java.util.ArrayList; +import java.util.List; + +/** + * A path painter that varies the path colors based on fixed speeds or average speed margin + * depending of the TrackPathDescriptor passed to its constructor. + * + * @author Vangelis S. + */ +public class DynamicSpeedTrackPathPainter implements TrackPathPainter { + private final Paint selectedTrackPaintSlow; + private final Paint selectedTrackPaintMedium; + private final Paint selectedTrackPaintFast; + private final List coloredPaths; + private final TrackPathDescriptor trackPathDescriptor; + private int slowSpeed; + private int normalSpeed; + + public DynamicSpeedTrackPathPainter (Context context, TrackPathDescriptor trackPathDescriptor) { + this.trackPathDescriptor = trackPathDescriptor; + + selectedTrackPaintSlow = TrackPathUtilities.getPaint(R.color.slow_path, context); + selectedTrackPaintMedium = TrackPathUtilities.getPaint(R.color.normal_path, context); + selectedTrackPaintFast = TrackPathUtilities.getPaint(R.color.fast_path, context); + + this.coloredPaths = new ArrayList(); + } + + @Override + public void drawTrack(Canvas canvas) { + for(int i = 0; i < coloredPaths.size(); ++i) { + ColoredPath coloredPath = coloredPaths.get(i); + canvas.drawPath(coloredPath.getPath(), coloredPath.getPathPaint()); + } + } + + @Override + public void updatePath(Projection projection, Rect viewRect, int startLocationIdx, + Boolean alwaysVisible, List points) { + // Whether to start a new segment on new valid and visible point. + boolean newSegment = startLocationIdx <= 0 || !points.get(startLocationIdx - 1).valid; + boolean lastVisible = !newSegment; + final Point pt = new Point(); + + clear(); + + slowSpeed = trackPathDescriptor.getSlowSpeed(); + normalSpeed = trackPathDescriptor.getNormalSpeed(); + + // Loop over track points. + for (int i = startLocationIdx; i < points.size(); ++i) { + CachedLocation loc = points.get(i); + + // Check if valid, if not then indicate a new segment. + if (!loc.valid) { + newSegment = true; + continue; + } + + final GeoPoint geoPoint = loc.geoPoint; + // Check if this breaks the existing segment. + boolean visible = alwaysVisible || viewRect.contains( + geoPoint.getLongitudeE6(), geoPoint.getLatitudeE6()); + if (!visible && !lastVisible) { + // This is a point outside view not connected to a visible one. + newSegment = true; + } + lastVisible = visible; + + // Either move to beginning of a new segment or continue the old one. + if (newSegment) { + projection.toPixels(geoPoint, pt); + newSegment = false; + } else { + ColoredPath coloredPath; + if(loc.speed <= slowSpeed) { + coloredPath = new ColoredPath(selectedTrackPaintSlow); + } + else if(loc.speed <= normalSpeed) { + coloredPath = new ColoredPath(selectedTrackPaintMedium); + } else { + coloredPath = new ColoredPath(selectedTrackPaintFast); + } + coloredPath.getPath().moveTo(pt.x, pt.y); + projection.toPixels(geoPoint, pt); + coloredPath.getPath().lineTo(pt.x, pt.y); + coloredPaths.add(coloredPath); + } + } + } + + @Override + public void clear() + { + coloredPaths.clear(); + } + + @Override + public boolean needsRedraw() { + return trackPathDescriptor.needsRedraw(); + } + + @Override + public Path getLastPath() { + Path path = new Path(); + for(int i = 0; i < coloredPaths.size(); ++i) { + path.addPath(coloredPaths.get(i).getPath()); + } + return path; + } +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/maps/FixedSpeedTrackPathDescriptor.java b/MyTracks/src/com/google/android/apps/mytracks/maps/FixedSpeedTrackPathDescriptor.java new file mode 100644 index 000000000..e69b4a6a5 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/maps/FixedSpeedTrackPathDescriptor.java @@ -0,0 +1,115 @@ +/* + * Copyright 2011 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.maps; + +import static com.google.android.apps.mytracks.Constants.TAG; + +import com.google.android.apps.mytracks.Constants; +import com.google.android.maps.mytracks.R; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.util.Log; + + +/** + * A fixed speed path descriptor. + * + * @author Vangelis S. + */ +public class FixedSpeedTrackPathDescriptor implements TrackPathDescriptor, OnSharedPreferenceChangeListener { + private int slowSpeed; + private int normalSpeed; + private final Context context; + + public FixedSpeedTrackPathDescriptor(Context context) { + + this.context = context; + context.getSharedPreferences(Constants.SETTINGS_NAME, 0) + .registerOnSharedPreferenceChangeListener(this); + + SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0); + if (prefs == null) { + slowSpeed = 9; + normalSpeed = 17; + return; + } + try { + slowSpeed = Integer.parseInt(prefs.getString(context.getString( + R.string.track_color_mode_fixed_speed_slow_key), "9")); + } catch (NumberFormatException e) { + slowSpeed = 9; + } + + try { + normalSpeed = Integer.parseInt(prefs.getString(context.getString( + R.string.track_color_mode_fixed_speed_medium_key), "17")); + } catch (NumberFormatException e) { + normalSpeed = 17; + } + } + + /** + * Gets the slow speed for reference. + * @return The speed limit considered as slow. + */ + public int getSlowSpeed() { + return slowSpeed; + } + + /** + * Gets the normal speed for reference. + * @return The speed limit considered as normal. + */ + public int getNormalSpeed() { + return normalSpeed; + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + Log.d(TAG, "FixedSpeedTrackPathDescriptor: onSharedPreferences changed " + key); + if (key == null + || (!key.equals(context.getString(R.string.track_color_mode_fixed_speed_slow_key)) + && !key.equals(context.getString(R.string.track_color_mode_fixed_speed_medium_key)))) { + return; + } + SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0); + if (prefs == null) { + slowSpeed = 9; + normalSpeed = 17; + return; + } + + try { + slowSpeed = Integer.parseInt(prefs.getString(context.getString( + R.string.track_color_mode_fixed_speed_slow_key), "9")); + } catch (NumberFormatException e) { + slowSpeed = 9; + } + try { + normalSpeed = Integer.parseInt(prefs.getString(context.getString( + R.string.track_color_mode_fixed_speed_medium_key), "17")); + } catch (NumberFormatException e) { + normalSpeed = 17; + } + } + + @Override + public boolean needsRedraw() { + return false; + } +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/maps/SingleColorTrackPathPainter.java b/MyTracks/src/com/google/android/apps/mytracks/maps/SingleColorTrackPathPainter.java new file mode 100644 index 000000000..b12ae2370 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/maps/SingleColorTrackPathPainter.java @@ -0,0 +1,107 @@ +/* + * Copyright 2011 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.maps; + +import com.google.android.apps.mytracks.MapOverlay.CachedLocation; +import com.google.android.maps.GeoPoint; +import com.google.android.maps.Projection; +import com.google.android.maps.mytracks.R; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Point; +import android.graphics.Rect; + +import java.util.List; + + +/** + * A path painter that not variates the path colors. + * + * @author Vangelis S. + */ +public class SingleColorTrackPathPainter implements TrackPathPainter { + private final Paint selectedTrackPaint; + private Path path; + + public SingleColorTrackPathPainter(Context context) { + selectedTrackPaint = TrackPathUtilities.getPaint(R.color.red, context); + } + + @Override + public void drawTrack(Canvas canvas) { + canvas.drawPath(path, selectedTrackPaint); + } + + @Override + public void updatePath(Projection projection, Rect viewRect, int startLocationIdx, + Boolean alwaysVisible, List points) { + // Whether to start a new segment on new valid and visible point. + boolean newSegment = startLocationIdx <= 0 || !points.get(startLocationIdx - 1).valid; + boolean lastVisible = !newSegment; + final Point pt = new Point(); + // Loop over track points. + int numPoints = points.size(); + path = new Path(); + path.incReserve(numPoints); + + for (int i = startLocationIdx; i < numPoints ; ++i) { + CachedLocation loc = points.get(i); + + // Check if valid, if not then indicate a new segment. + if (!loc.valid) { + newSegment = true; + continue; + } + + final GeoPoint geoPoint = loc.geoPoint; + // Check if this breaks the existing segment. + boolean visible = alwaysVisible + || viewRect.contains(geoPoint.getLongitudeE6(), geoPoint.getLatitudeE6()); + if (!visible && !lastVisible) { + // This is a point outside view not connected to a visible one. + newSegment = true; + } + lastVisible = visible; + + // Either move to beginning of a new segment or continue the old one. + projection.toPixels(geoPoint, pt); + if (newSegment) { + path.moveTo(pt.x, pt.y); + newSegment = false; + } else { + path.lineTo(pt.x, pt.y); + } + } + } + + @Override + public void clear() { + path = null; + } + + @Override + public boolean needsRedraw() { + return false; + } + + @Override + public Path getLastPath() { + return path; + } +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathDescriptor.java b/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathDescriptor.java new file mode 100644 index 000000000..389994e6b --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathDescriptor.java @@ -0,0 +1,38 @@ +/* + * Copyright 2011 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.maps; + +/** + * An interface for classes which describe how to draw a track path. + * + * @author Vangelis S. + */ +public interface TrackPathDescriptor { + /** + * @return The maximum speed which is considered slow. + */ + int getSlowSpeed(); + + /** + * @return The maximum speed which is considered normal. + */ + int getNormalSpeed(); + + /** + * @return True if the path needs to be updated. + */ + boolean needsRedraw(); +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathPainter.java b/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathPainter.java new file mode 100644 index 000000000..1f1d8e31d --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathPainter.java @@ -0,0 +1,68 @@ +/* + * Copyright 2011 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.maps; + +import com.google.android.apps.mytracks.MapOverlay.CachedLocation; +import com.google.android.maps.Projection; + +import android.graphics.Canvas; +import android.graphics.Path; +import android.graphics.Rect; + +import java.util.List; + +/** + * An interface for classes which paint the track path. + * + * @author Vangelis S. + */ +public interface TrackPathPainter { + + /** + * Clears the related data. + */ + void clear(); + + /** + * Draws the path to the canvas. + * @param canvas The Canvas to draw upon + */ + void drawTrack(Canvas canvas); + + /** + * Updates the path. + * @param projection The Canvas to draw upon. + * @param viewRect The Path to be drawn. + * @param startLocationIdx The start point from where update the path. + * @param alwaysVisible Flag for alwaysvisible. + * @param points The list of points used to update the path. + */ + void updatePath(Projection projection, Rect viewRect, int startLocationIdx, + Boolean alwaysVisible, List points); + + /** + * @return True if the path needs to be updated. + */ + boolean needsRedraw(); + + /** + * @return The path being used currently. + */ + Path getLastPath(); +} + + + diff --git a/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathPainterFactory.java b/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathPainterFactory.java new file mode 100644 index 000000000..14f8f29cd --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathPainterFactory.java @@ -0,0 +1,65 @@ +/* + * Copyright 2011 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.maps; + +import static com.google.android.apps.mytracks.Constants.TAG; + +import com.google.android.apps.mytracks.Constants; +import com.google.android.maps.mytracks.R; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; + +/** + * A factory for TrackPathPainters. + * + * @author Vangelis S. + */ +public class TrackPathPainterFactory { + + private TrackPathPainterFactory() { + } + + /** + * Get a new TrackPathPainter. + * @param context Context to fetch system preferences. + * @return The TrackPathPainter that corresponds to the track color mode setting. + */ + public static TrackPathPainter getTrackPathPainter(Context context) { + SharedPreferences prefs = + context.getSharedPreferences(Constants.SETTINGS_NAME, 0); + if (prefs == null) { + return new SingleColorTrackPathPainter(context); + } + + String colorMode = prefs.getString(context.getString(R.string.track_color_mode_key), null); + Log.i(TAG, "Creating track path painter of type: " + colorMode); + + if (colorMode == null || colorMode.equals(context.getString(R.string.track_color_mode_none))) { + return new SingleColorTrackPathPainter(context); + } else if (colorMode.equals(context.getString(R.string.track_color_mode_fixed))) { + return new DynamicSpeedTrackPathPainter(context, + new FixedSpeedTrackPathDescriptor(context)); + } else if (colorMode.equals(context.getString(R.string.track_color_mode_dynamic))) { + return new DynamicSpeedTrackPathPainter(context, + new DynamicSpeedTrackPathDescriptor(context)); + } else { + Log.w(TAG, "Using default track path painter. Unrecognized painter: " + colorMode); + return new SingleColorTrackPathPainter(context); + } + } +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathUtilities.java b/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathUtilities.java new file mode 100644 index 000000000..956d2c8eb --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/maps/TrackPathUtilities.java @@ -0,0 +1,36 @@ +/* + * Copyright 2011 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.maps; + +import android.content.Context; +import android.graphics.Paint; + +/** + * Various utility functions for TrackPath painting. + * + * @author Vangelis S. + */ +public class TrackPathUtilities { + + public static Paint getPaint(int id, Context context) { + Paint paint = new Paint(); + paint.setColor(context.getResources().getColor(id)); + paint.setStrokeWidth(3); + paint.setStyle(Paint.Style.STROKE); + paint.setAntiAlias(true); + return paint; + } +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java b/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java index 04e88baa4..821e05c80 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java @@ -16,6 +16,7 @@ package com.google.android.apps.mytracks.util; import com.google.android.apps.mytracks.Constants; +import com.google.api.client.http.HttpTransport; import android.os.Build; import android.util.Log; @@ -123,6 +124,15 @@ public class ApiFeatures { public boolean canReuseSQLiteQueryBuilder() { return getApiLevel() > 4; } + + /** + * Returns true if com.google.api.client.javanet.NetHttpTransport should be + * used rather than com.google.api.client.apache.ApacheHttpTransport. See + * {@link HttpTransport} for more info. + */ + public boolean useNetHttpTransport() { + return getApiLevel() >= 9; + } // Visible for testing. protected int getApiLevel() { diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/UnitConversions.java b/MyTracks/src/com/google/android/apps/mytracks/util/UnitConversions.java index c524ca917..609a7a9cf 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/UnitConversions.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/UnitConversions.java @@ -28,7 +28,8 @@ public abstract class UnitConversions { public static final double MI_TO_FEET = 5280.0; public static final double KMH_TO_MPH = 1000 * M_TO_FT / MI_TO_FEET; public static final double TO_RADIANS = Math.PI / 180.0; - + public static final double MPH_TO_KMH = 1.609344; + protected UnitConversions() { } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/MapOverlayTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/MapOverlayTest.java index 3ea8d4a11..49a91b49b 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/MapOverlayTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/MapOverlayTest.java @@ -16,103 +16,23 @@ package com.google.android.apps.mytracks; import com.google.android.apps.mytracks.content.Waypoint; -import com.google.android.maps.GeoPoint; import com.google.android.maps.MapView; -import com.google.android.maps.Projection; -import android.content.Context; import android.graphics.Canvas; -import android.graphics.Path; -import android.graphics.Point; -import android.graphics.PointF; -import android.graphics.Rect; import android.location.Location; import android.test.AndroidTestCase; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; - /** * Tests for the MyTracks map overlay. * * @author Bartlomiej Niechwiej + * @author Vangelis S. */ public class MapOverlayTest extends AndroidTestCase { private Canvas canvas; private MockMyTracksOverlay myTracksOverlay; private MapView mockView; - private Projection mockProjection; - - /** - * A mock version of {@code MapOverlay} that does not use - * {@class MapView}. - */ - private class MockMyTracksOverlay extends MapOverlay { - public MockMyTracksOverlay(Context context) { - super(context); - } - @Override - Projection getMapProjection(MapView mapView) { - return mockProjection; - } - @Override - Rect getMapViewRect(MapView mapView) { - return new Rect(0, 0, 100, 100); - } - @Override - Path newPath() { - return new MockPath(); - } - } - - /** - * A mock class that intercepts {@code Path}'s and records calls to - * {@code #moveTo()} and {@code #lineTo()}. - */ - private static class MockPath extends Path { - /** A list of disjoined path segments. */ - public final List> segments = new LinkedList>(); - /** The total number of points in this path. */ - public int totalPoints; - - private List currentSegment; - @Override - public void lineTo(float x, float y) { - super.lineTo(x, y); - assertNotNull(currentSegment); - currentSegment.add(new PointF(x, y)); - totalPoints++; - } - @Override - public void moveTo(float x, float y) { - super.moveTo(x, y); - segments.add(currentSegment = - new ArrayList(Arrays.asList(new PointF(x, y)))); - totalPoints++; - } - } - - /** - * A mock {@code Projection} that acts as the identity matrix. - */ - private static class MockProjection implements Projection { - @Override - public Point toPixels(GeoPoint in, Point out) { - return out; - } - @Override - public float metersToEquatorPixels(float meters) { - return meters; - } - @Override - public GeoPoint fromPixels(int x, int y) { - return new GeoPoint(y, x); - } - } - @Override protected void setUp() throws Exception { super.setUp(); @@ -121,9 +41,8 @@ public class MapOverlayTest extends AndroidTestCase { // Enable drawing. myTracksOverlay.setTrackDrawingEnabled(true); mockView = null; - mockProjection = new MockProjection(); } - + public void testAddLocation() throws Exception { Location location = new Location("gps"); location.setLatitude(10); diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/MockMyTracksOverlay.java b/MyTracksTest/src/com/google/android/apps/mytracks/MockMyTracksOverlay.java new file mode 100644 index 000000000..9c2355758 --- /dev/null +++ b/MyTracksTest/src/com/google/android/apps/mytracks/MockMyTracksOverlay.java @@ -0,0 +1,57 @@ +/* + * Copyright 2011 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.maps.MapView; +import com.google.android.maps.Projection; + +import android.content.Context; +import android.graphics.Path; +import android.graphics.Rect; + +/** + * Elements for Tests for the MyTracks map overlay. + * + * @author Bartlomiej Niechwiej + * @author Vangelis S. + * + * A mock version of {@code MapOverlay} that does not use + * {@class MapView}. + */ +public class MockMyTracksOverlay extends MapOverlay { + + private Projection mockProjection; + + public MockMyTracksOverlay(Context context) { + super(context); + mockProjection = new MockProjection(); + } + + @Override + public Projection getMapProjection(MapView mapView) { + return mockProjection; + } + + @Override + public Rect getMapViewRect(MapView mapView) { + return new Rect(0, 0, 100, 100); + } + + @Override + public Path newPath() { + return new MockPath(); + } +} \ No newline at end of file diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/MockPath.java b/MyTracksTest/src/com/google/android/apps/mytracks/MockPath.java new file mode 100644 index 000000000..ba9592c08 --- /dev/null +++ b/MyTracksTest/src/com/google/android/apps/mytracks/MockPath.java @@ -0,0 +1,60 @@ +/* + * Copyright 2011 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 android.graphics.Path; +import android.graphics.PointF; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import junit.framework.Assert; + +/** + * Elements for Tests for the MyTracks map overlay. + * + * @author Bartlomiej Niechwiej + * @author Vangelis S. + * + * A mock class that intercepts {@code Path}'s and records calls to + * {@code #moveTo()} and {@code #lineTo()}. + */ +public class MockPath extends Path { + + /** A list of disjoined path segments. */ + public final List> segments = new LinkedList>(); + /** The total number of points in this path. */ + public int totalPoints; + private List currentSegment; + + @Override + public void lineTo(float x, float y) { + super.lineTo(x, y); + Assert.assertNotNull(currentSegment); + currentSegment.add(new PointF(x, y)); + totalPoints++; + } + + @Override + public void moveTo(float x, float y) { + super.moveTo(x, y); + segments.add(currentSegment = + new ArrayList(Arrays.asList(new PointF(x, y)))); + totalPoints++; + } +} \ No newline at end of file diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/MockProjection.java b/MyTracksTest/src/com/google/android/apps/mytracks/MockProjection.java new file mode 100644 index 000000000..a1f36d90b --- /dev/null +++ b/MyTracksTest/src/com/google/android/apps/mytracks/MockProjection.java @@ -0,0 +1,47 @@ +/* + * Copyright 2011 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.maps.GeoPoint; +import com.google.android.maps.Projection; + +import android.graphics.Point; + +/** + * Elements for Tests for the MyTracks map overlay. + * + * @author Bartlomiej Niechwiej + * @author Vangelis S. + * + * A mock {@code Projection} that acts as the identity matrix. + */ +public class MockProjection implements Projection { + + @Override + public Point toPixels(GeoPoint in, Point out) { + return out; + } + + @Override + public float metersToEquatorPixels(float meters) { + return meters; + } + + @Override + public GeoPoint fromPixels(int x, int y) { + return new GeoPoint(y, x); + } +} \ No newline at end of file diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorDynamicSpeedTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorDynamicSpeedTest.java new file mode 100644 index 000000000..63eec1182 --- /dev/null +++ b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorDynamicSpeedTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2011 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.maps; + +import com.google.android.apps.mytracks.MockPath; + +import android.location.Location; + +/** + * Tests for the MyTracks track path descriptors and painters. + * + * @author Vangelis S. + */ +public class TrackPathDescriptorDynamicSpeedTest extends TrackPathPainterTestCase { + + public void testDynamicSpeedTrackPathDescriptor() throws Exception { + Location location = new Location("gps"); + location.setLatitude(10); + + for (int i = 0; i < 100; ++i) { + location = new Location("gps"); + location.setLatitude(20 + i / 2); + location.setLongitude(150 - i); + myTracksOverlay.addLocation(location); + } + + TrackPathPainter painter = new DynamicSpeedTrackPathPainter(getContext(), new DynamicSpeedTrackPathDescriptor(getContext())); + int startLocationIdx = 0; + Boolean alwaysVisible = true; + + assertNotNull(painter); + painter.updatePath(myTracksOverlay.getMapProjection(mockView), + myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible, + myTracksOverlay.getPoints()); + assertNotNull(myTracksOverlay.getLastPath()); + assertTrue(myTracksOverlay.getLastPath() instanceof MockPath); + painter.drawTrack(canvas); + + } +} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorFixedSpeedTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorFixedSpeedTest.java new file mode 100644 index 000000000..d78c02fcb --- /dev/null +++ b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorFixedSpeedTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2011 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.maps; + +import com.google.android.apps.mytracks.MockPath; + +import android.location.Location; + +/** + * Tests for the MyTracks track path descriptors and painters. + * + * @author Vangelis S. + */ +public class TrackPathDescriptorFixedSpeedTest extends TrackPathPainterTestCase { + + public void testFixedSpeedTrackPathDescriptor() throws Exception { + Location location = new Location("gps"); + location.setLatitude(10); + + for (int i = 0; i < 100; ++i) { + location = new Location("gps"); + location.setLatitude(20 + i / 2); + location.setLongitude(150 - i); + myTracksOverlay.addLocation(location); + } + + TrackPathPainter painter = new DynamicSpeedTrackPathPainter(getContext(), new FixedSpeedTrackPathDescriptor(getContext())); + int startLocationIdx = 0; + Boolean alwaysVisible = true; + + assertNotNull(painter); + painter.updatePath(myTracksOverlay.getMapProjection(mockView), + myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible, + myTracksOverlay.getPoints()); + assertNotNull(myTracksOverlay.getLastPath()); + assertTrue(myTracksOverlay.getLastPath() instanceof MockPath); + painter.drawTrack(canvas); + } +} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterFactoryTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterFactoryTest.java new file mode 100644 index 000000000..83482b26b --- /dev/null +++ b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterFactoryTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2011 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.maps; + +import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.MockPath; +import com.google.android.maps.mytracks.R; + +import android.content.Context; +import android.content.SharedPreferences; +import android.location.Location; + +/** + * Tests for the MyTracks track path painter factory. + * + * @author Vangelis S. + */ +public class TrackPathPainterFactoryTest extends TrackPathPainterTestCase { + + public void testTrackPathPainterFactory() throws Exception { + Location location = new Location("gps"); + location.setLatitude(10); + + for (int i = 0; i < 100; ++i) { + location = new Location("gps"); + location.setLatitude(20 + i / 2); + location.setLongitude(150 - i); + myTracksOverlay.addLocation(location); + } + + Context context = getContext(); + SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0); + if (prefs == null) { + return; + } + + testTrackPathPainterFactorySpecific(context, prefs, R.string.track_color_mode_none, + SingleColorTrackPathPainter.class); + testTrackPathPainterFactorySpecific(context, prefs, R.string.track_color_mode_fixed, + DynamicSpeedTrackPathPainter.class); + testTrackPathPainterFactorySpecific(context, prefs, R.string.track_color_mode_dynamic, + DynamicSpeedTrackPathPainter.class); + } + + private void testTrackPathPainterFactorySpecific(Context context, SharedPreferences prefs, + int track_color_mode, Class c) { + prefs.edit().putString(context.getString(track_color_mode), + context.getString(R.string.track_color_mode_key)).commit(); + + int startLocationIdx = 0; + Boolean alwaysVisible = true; + + TrackPathPainter painter = TrackPathPainterFactory.getTrackPathPainter(context); + + assertNotNull(painter); + assertTrue(c.isInstance(painter)); + + painter.updatePath(myTracksOverlay.getMapProjection(mockView), + myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible, + myTracksOverlay.getPoints()); + assertNotNull(myTracksOverlay.getLastPath()); + assertTrue(myTracksOverlay.getLastPath() instanceof MockPath); + painter.drawTrack(canvas); + } +} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterSingleColorTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterSingleColorTest.java new file mode 100644 index 000000000..6c6682e32 --- /dev/null +++ b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterSingleColorTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2011 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.maps; + +import com.google.android.apps.mytracks.MockPath; + +import android.location.Location; + +/** + * Tests for the MyTracks track path descriptors and painters. + * + * @author Vangelis S. + */ +public class TrackPathPainterSingleColorTest extends TrackPathPainterTestCase { + + public void testSimpeColorTrackPathPainter() throws Exception { + Location location = new Location("gps"); + location.setLatitude(10); + + for (int i = 0; i < 100; ++i) { + location = new Location("gps"); + location.setLatitude(20 + i / 2); + location.setLongitude(150 - i); + myTracksOverlay.addLocation(location); + } + + TrackPathPainter painter = new SingleColorTrackPathPainter(getContext()); + int startLocationIdx = 0; + Boolean alwaysVisible = true; + + assertNotNull(painter); + painter.updatePath(myTracksOverlay.getMapProjection(mockView), + myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible, + myTracksOverlay.getPoints()); + assertNotNull(myTracksOverlay.getLastPath()); + assertTrue(myTracksOverlay.getLastPath() instanceof MockPath); + painter.drawTrack(canvas); + } +} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterTestCase.java b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterTestCase.java new file mode 100644 index 000000000..59ceb94fd --- /dev/null +++ b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterTestCase.java @@ -0,0 +1,43 @@ +/* + * Copyright 2011 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.maps; + +import com.google.android.apps.mytracks.MockMyTracksOverlay; +import com.google.android.maps.MapView; + +import android.graphics.Canvas; +import android.test.AndroidTestCase; + +/** + * Tests for the MyTracks track path descriptors and painters. + * + * @author Vangelis S. + */ +public class TrackPathPainterTestCase extends AndroidTestCase { + protected Canvas canvas; + protected MockMyTracksOverlay myTracksOverlay; + protected MapView mockView; + + @Override + protected void setUp() throws Exception { + super.setUp(); + canvas = new Canvas(); + myTracksOverlay = new MockMyTracksOverlay(getContext()); + // Enable drawing. + myTracksOverlay.setTrackDrawingEnabled(true); + mockView = null; + } +}