merge heads

This commit is contained in:
Jimmy Shih
2011-09-28 19:41:18 -07:00
48 changed files with 1664 additions and 291 deletions
+2
View File
@@ -7,3 +7,5 @@ syntax:glob
MyTracksTest/annotations.log
**/*.pyc
**/*.pyo
syntax: glob
MyTracksTest/hs_err_pid*.log
+24 -13
View File
@@ -1,13 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="lib" path="libs/googleloginclient-helper.jar"/>
<classpathentry kind="lib" path="libs/google-common.jar"/>
<classpathentry kind="lib" path="libs/google-api-client-1.2.2-alpha.jar"/>
<classpathentry kind="lib" path="libs/libGoogleAnalytics.jar"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry exported="true" kind="lib" path="/MyTracksLib/libs/protobuf-java-2.3.0-lite.jar"/>
<classpathentry kind="src" path="MyTracksLib_src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="lib" path="libs/googleloginclient-helper.jar"/>
<classpathentry kind="lib" path="libs/google-common.jar"/>
<classpathentry kind="lib" path="libs/libGoogleAnalytics.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/commons-codec-1.3.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/commons-logging-1.1.1.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/google-api-client-1.5.0-beta.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/google-http-client-1.5.0-beta.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/google-oauth-client-1.5.0-beta.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/gson-1.6.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/guava-r09.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/httpclient-4.0.3.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/httpcore-4.0.1.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/jackson-core-asl-1.6.7.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/jsr305-1.3.9.jar"/>
<classpathentry kind="lib" path="libs/google-api-client/junit-4.8.2.jar"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry exported="true" kind="lib" path="/MyTracksLib/libs/protobuf-java-2.3.0-lite.jar"/>
<classpathentry kind="src" path="MyTracksLib_src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
+41 -41
View File
@@ -1,41 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MyTracks</name>
<comment></comment>
<projects>
<project>MyTracksLib</project>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<linkedResources>
<link>
<name>MyTracksLib_src</name>
<type>2</type>
<locationURI>_android_MyTracksLib_e2802071/src</locationURI>
</link>
</linkedResources>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MyTracks</name>
<comment></comment>
<projects>
<project>MyTracksLib</project>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<linkedResources>
<link>
<name>MyTracksLib_src</name>
<type>2</type>
<locationURI>_android_MyTracksLib_e2802071/src</locationURI>
</link>
</linkedResources>
</projectDescription>
+2 -4
View File
@@ -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
+15 -7
View File
@@ -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/.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+12
View File
@@ -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 <fields>;
}
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
# Needed by Guava
-dontwarn sun.misc.Unsafe
@@ -118,4 +118,16 @@ limitations under the License.
<item>@string/ant_sensor_type</item>
<item>@string/srm_ant_bridge_sensor_type</item>
</string-array>
<string-array name="track_color_mode_options">
<item>@string/track_color_mode_none</item>
<item>@string/track_color_mode_fixed</item>
<item>@string/track_color_mode_dynamic</item>
</string-array>
<string-array name="track_color_mode_values">
<item>@string/none</item>
<item>@string/track_color_mode_fixed</item>
<item>@string/track_color_mode_dynamic</item>
</string-array>
</resources>
+10
View File
@@ -51,4 +51,14 @@ limitations under the License.
<!-- AppWidget colors -->
<color name="appwidget_text">#EDEDED</color>
<color name="appwidget_hr">#99999999</color>
<!-- Colors for dynamic track drawing -->
<!-- Green -->
<color name="slow_path">#F774DF00</color>
<!-- Blue -->
<color name="normal_path">#F75858FA</color>
<!-- Red -->
<color name="fast_path">#F7DF0101</color>
</resources>
+8 -1
View File
@@ -41,7 +41,13 @@ limitations under the License.
<string name="share_url_only_key">shareUrlOnly</string>
<string name="split_frequency_key">splitFrequency</string>
<string name="timestamp_track_name_key">timestampTrackName</string>
<string name="track_color_mode_key">trackColorMode</string>
<string name="track_color_mode_fixed_speed_slow_key">trackColorModeFixedSlow</string>
<string name="track_color_mode_fixed_speed_medium_key">trackColorModeFixedMedium</string>
<string name="track_color_mode_fixed_speed_slow_display_key">trackColorModeFixedSlowDisplay</string>
<string name="track_color_mode_fixed_speed_medium_display_key">trackColorModeFixedMediumDisplay</string>
<string name="track_color_mode_dynamic_speed_variation_key">trackColorModeDynamicVariation</string>
<!-- Preference keys which keep transient state (not user preferences) - DO NOT TRANSLATE -->
<string name="auto_resume_track_current_retry_key">autoResumeTrackCurrentRetry</string>
<string name="recording_track_key">recordingTrack</string>
@@ -54,4 +60,5 @@ limitations under the License.
<string name="sensor_options_key">sensorOptions</string>
<string name="ant_options_key">antOptions</string>
<string name="display_settings_screen_key">displaySettingsScreen</string>
<string name="track_color_mode_fixed_speed_options_key">trackColorModeFixedOptions</string>
</resources>
+19 -1
View File
@@ -268,6 +268,17 @@ limitations under the License.
<string name="bluetooth_sensor_summary">The bluetooth sensor to connect to</string>
<string name="settings_modular_stats_display_title">Modular Stats Display</string>
<string name="settings_track_color_mode">Track Color Mode</string>
<string name="settings_track_color_mode_summary">The way to color the track</string>
<string name="settings_track_color_mode_fixed">Fixed</string>
<string name="settings_track_color_mode_dynamic">Dynamic</string>
<string name="settings_track_color_mode_fixed_speed_slow">Fixed Speed Slow</string>
<string name="settings_track_color_mode_fixed_speed_slow_summary">Slow speed top value</string>
<string name="settings_track_color_mode_fixed_speed_medium">Fixed Speed Medium</string>
<string name="settings_track_color_mode_fixed_speed_medium_summary">Medium speed top value</string>
<string name="settings_track_color_mode_dynamic_speed_variation">Dynamic Speed Variation</string>
<string name="settings_track_color_mode_dynamic_speed_variation_summary">% Margin from average speed to consider medium speed</string>
<!-- Backups -->
<string name="settings_backup">Backup (BETA)</string>
<string name="settings_sd_backup">SD Card Backup</string>
@@ -483,7 +494,10 @@ limitations under the License.
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
<string name="ant_options">ANT options</string>
<string name="sensor_options">Sensor Options</string>
<string name="track_color_mode">Track Color Mode</string>
<string name="fixed_speed_options">Fixed Speed Options</string>
<string name="dynamic_speed_options">Dynamic Speed Options</string>
<!-- Bluetooth Sensor -->
<string name="bluetooth_connected">Connected to %s</string>
<string name="bluetooth_connecting">Bluetooth sensor connecting ...</string>
@@ -517,4 +531,8 @@ limitations under the License.
<string name="polar_bt_sensor_option">Polar Bluetooth</string>
<string name="zephyr_bt_sensor_option">Zephyr Bluetooth</string>
<!-- Track Color Modes -->
<string name="track_color_mode_none">None</string>
<string name="track_color_mode_fixed">Fixed (BETA)</string>
<string name="track_color_mode_dynamic">Dynamic (BETA)</string>
</resources>
+52
View File
@@ -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" />
<ListPreference android:key="@string/track_color_mode_key"
android:title="@string/settings_track_color_mode"
android:summary="@string/settings_track_color_mode_summary"
android:entries="@array/track_color_mode_options"
android:entryValues="@array/track_color_mode_values"
android:defaultValue="@string/none"/>
<PreferenceCategory android:title="@string/fixed_speed_options"
android:key="@string/track_color_mode_fixed_speed_options_key">
<EditTextPreference android:key="@string/track_color_mode_fixed_speed_slow_key"
android:title="@string/settings_track_color_mode_fixed_speed_slow"
android:summary="@string/settings_track_color_mode_fixed_speed_slow_summary"
android:defaultValue="9"
android:inputType="number"
android:maxLength="3">
</EditTextPreference>
<EditTextPreference android:key="@string/track_color_mode_fixed_speed_slow_display_key"
android:title="@string/settings_track_color_mode_fixed_speed_slow"
android:summary="@string/settings_track_color_mode_fixed_speed_slow_summary"
android:defaultValue="9"
android:inputType="number"
android:maxLength="3">
</EditTextPreference>
<EditTextPreference android:key="@string/track_color_mode_fixed_speed_medium_key"
android:title="@string/settings_track_color_mode_fixed_speed_medium"
android:summary="@string/settings_track_color_mode_fixed_speed_medium_summary"
android:defaultValue="15"
android:inputType="number"
android:maxLength="3">
</EditTextPreference>
<EditTextPreference android:key="@string/track_color_mode_fixed_speed_medium_display_key"
android:title="@string/settings_track_color_mode_fixed_speed_medium"
android:summary="@string/settings_track_color_mode_fixed_speed_medium_summary"
android:defaultValue="15"
android:inputType="number"
android:maxLength="3">
</EditTextPreference>
</PreferenceCategory>
<PreferenceCategory android:title="@string/dynamic_speed_options">
<EditTextPreference android:key="@string/track_color_mode_dynamic_speed_variation_key"
android:title="@string/settings_track_color_mode_dynamic_speed_variation"
android:summary="@string/settings_track_color_mode_dynamic_speed_variation_summary"
android:defaultValue="25"
android:inputType="number"
android:maxLength="2">
</EditTextPreference>
</PreferenceCategory>
</PreferenceScreen>
<!-- Recording settings -->
@@ -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;
}
}
@@ -217,4 +217,4 @@ public class ImportAllTracks {
}
return gpxFiles;
}
}
}
@@ -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<Waypoint> 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<CachedLocation> 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);
}
}
}
}
@@ -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;
}
});
}
}
@@ -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("<LineString><coordinates>");
@@ -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<HttpTransport> wrapper = new GDataWrapper<HttpTransport>();
GDataWrapper<HttpRequestFactory> wrapper = new GDataWrapper<HttpRequestFactory>();
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<HttpTransport>() {
wrapper.runQuery(new QueryFunction<HttpRequestFactory>() {
@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());
}
}
});
@@ -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;
}
}
@@ -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<ColoredPath> 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<ColoredPath>();
}
@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<CachedLocation> 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;
}
}
@@ -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;
}
}
@@ -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<CachedLocation> 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;
}
}
@@ -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();
}
@@ -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<CachedLocation> points);
/**
* @return True if the path needs to be updated.
*/
boolean needsRedraw();
/**
* @return The path being used currently.
*/
Path getLastPath();
}
@@ -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);
}
}
}
@@ -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;
}
}
@@ -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() {
@@ -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() {
}
}
@@ -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<List<PointF>> segments = new LinkedList<List<PointF>>();
/** The total number of points in this path. */
public int totalPoints;
private List<PointF> 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<PointF>(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);
@@ -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();
}
}
@@ -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<List<PointF>> segments = new LinkedList<List<PointF>>();
/** The total number of points in this path. */
public int totalPoints;
private List<PointF> 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<PointF>(Arrays.asList(new PointF(x, y))));
totalPoints++;
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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 <T> 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);
}
}
@@ -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);
}
}
@@ -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;
}
}