Merge with head.

This commit is contained in:
Sandor Dornbush
2011-03-24 23:05:02 -07:00
62 changed files with 1582 additions and 436 deletions
+5 -5
View File
@@ -17,8 +17,8 @@ limitations under the License.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.maps.mytracks" package="com.google.android.maps.mytracks"
android:installLocation="auto" android:installLocation="auto"
android:versionCode="26" android:versionCode="27"
android:versionName="1.1.3"> android:versionName="1.1.4">
<application android:icon="@drawable/arrow_icon" <application android:icon="@drawable/arrow_icon"
android:label="@string/app_name" android:label="@string/app_name"
android:backupAgent="com.google.android.apps.mytracks.io.backup.MyTracksBackupAgent"> android:backupAgent="com.google.android.apps.mytracks.io.backup.MyTracksBackupAgent">
@@ -52,7 +52,7 @@ limitations under the License.
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="com.google.android.apps.mytracks.MyTracksMap" <activity android:name="com.google.android.apps.mytracks.MapActivity"
android:label="MyTracks" android:label="MyTracks"
android:exported="false" /> android:exported="false" />
@@ -73,7 +73,7 @@ limitations under the License.
<activity android:name="com.google.android.apps.mytracks.WaypointDetails" <activity android:name="com.google.android.apps.mytracks.WaypointDetails"
android:label="@string/waypointdetails_title" /> android:label="@string/waypointdetails_title" />
<activity android:name="com.google.android.apps.mytracks.MyTracksSettings" <activity android:name="com.google.android.apps.mytracks.SettingsActivity"
android:label="@string/mytracks_settings" /> android:label="@string/mytracks_settings" />
<activity android:name="com.google.android.apps.mytracks.AggregatedStatsActivity" <activity android:name="com.google.android.apps.mytracks.AggregatedStatsActivity"
@@ -101,7 +101,7 @@ limitations under the License.
android:exported="true" android:exported="true"
android:permission="com.google.android.apps.mytracks.WRITE_TRACK_DATA" /> android:permission="com.google.android.apps.mytracks.WRITE_TRACK_DATA" />
<receiver android:name="com.google.android.apps.mytracks.MyTracksReceiver"> <receiver android:name="com.google.android.apps.mytracks.BootReceiver">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter> </intent-filter>
+8 -8
View File
@@ -30,18 +30,18 @@ limitations under the License.
<string name="current_segment">Último segmento</string> <string name="current_segment">Último segmento</string>
<!-- Error messages --> <!-- Error messages -->
<string name="error_no_location_manager">Ningún administrador de ubicación fue hallado en este aparato! </string> <string name="error_no_location_manager">Ningún administrador de ubicación fue hallado en este dispositivo! </string>
<string name="error_no_gps_location_provider">Ningún proveedor GPS de ubicación fue hallado en este aparato.</string> <string name="error_no_gps_location_provider">Ningún proveedor de ubicación GPS fue hallado en este dispositivo.</string>
<string name="error_sending_to_fusiontables">Hubo un error al mandar su recorrido a Google Fusion Tables. Por favor inténtelo de nuevo más tarde.</string> <string name="error_sending_to_fusiontables">Se produjo un error al enviar su recorrido a Google Fusion Tables.</string>
<string name="error_sending_to_docs">Hubo un error al mandar su recorrido a Google Docs. Por favor inténtelo de nuevo más tarde.</string> <string name="error_sending_to_docs">Se produjo un error al enviar su recorrido a Google Docs.</string>
<string name="error_unable_to_start_recording">No pude empezar a grabar. Por favor inténtelo de nuevo. </string> <string name="error_unable_to_start_recording">No se puede iniciar la grabación. Inténtelo de nuevo. </string>
<string name="error_unable_to_stop_recording">No pude dejar de grabar. Por favor inténtelo de nuevo.</string> <string name="error_unable_to_stop_recording">No se puede detener la grabación. Inténtelo de nuevo.</string>
<string name="error_unable_to_read_file">No pude leer del archivo.</string> <string name="error_unable_to_read_file">No pude leer del archivo.</string>
<string name="error_invalid_gpx_format">El archivo no tiene un format GPX válido.</string> <string name="error_invalid_gpx_format">El archivo no tiene un format GPX válido.</string>
<string name="error_generic">Error. Por favor inténtelo de nuevo.</string> <string name="error_generic">A ocurrido un error. Por favor, inténtelo de nuevo.</string>
<string name="error_track_does_not_exist">El recorrido no existe.</string> <string name="error_track_does_not_exist">El recorrido no existe.</string>
<string name="error_out_of_memory">El archivo es demasiado grande (tiene que ser menor a 500 KB). Abortando.</string> <string name="error_out_of_memory">El archivo es demasiado grande (tiene que ser menor a 500 KB). Abortando.</string>
<string name="error_unable_to_insert_marker">No pude insertar la señal. La ubicación no esta disponible.</string> <string name="error_unable_to_insert_marker">No se puede insertar el marcador. La ubicación no esta disponible.</string>
<!-- Status messages --> <!-- Status messages -->
<string name="wait_for_fix">Esperando una ubicación mas exacta del GPS. Asegúrese que el cielo sea visible.</string> <string name="wait_for_fix">Esperando una ubicación mas exacta del GPS. Asegúrese que el cielo sea visible.</string>
@@ -67,7 +67,7 @@ public class AggregatedStatsActivity extends Activity implements
sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET); sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
SharedPreferences preferences = getSharedPreferences( SharedPreferences preferences = getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
if (preferences != null) { if (preferences != null) {
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true); metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
preferences.registerOnSharedPreferenceChangeListener(this); preferences.registerOnSharedPreferenceChangeListener(this);
@@ -41,17 +41,17 @@ import android.util.Log;
* *
* @author Bartlomiej Niechwiej * @author Bartlomiej Niechwiej
*/ */
public class MyTracksReceiver extends BroadcastReceiver { public class BootReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
Log.d(TAG, "MyTracksReceiver.onReceive: " + intent.getAction()); Log.d(TAG, "BootReceiver.onReceive: " + intent.getAction());
if (ACTION_BOOT_COMPLETED.equals(intent.getAction())) { if (ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent startIntent = new Intent(context, TrackRecordingService.class); Intent startIntent = new Intent(context, TrackRecordingService.class);
startIntent.putExtra(RESUME_TRACK_EXTRA_NAME, true); startIntent.putExtra(RESUME_TRACK_EXTRA_NAME, true);
context.startService(startIntent); context.startService(startIntent);
} else { } else {
Log.w(TAG, "MyTracksReceiver: unsupported action"); Log.w(TAG, "BootReceiver: unsupported action");
} }
} }
} }
@@ -78,7 +78,7 @@ class CheckUnits {
private static void accept(Context context, SharedPreferences preferences) { private static void accept(Context context, SharedPreferences preferences) {
recordCheckPerformed(preferences); recordCheckPerformed(preferences);
Intent startIntent = new Intent(context, MyTracksSettings.class); Intent startIntent = new Intent(context, SettingsActivity.class);
context.startActivity(startIntent); context.startActivity(startIntent);
} }
@@ -140,6 +140,12 @@ public abstract class Constants {
*/ */
public static final int MAX_LOADED_TRACK_POINTS = 20000; public static final int MAX_LOADED_TRACK_POINTS = 20000;
/**
* Maximum number of track points ever loaded at once from the provider into
* memory in a single call to read points.
*/
public static final int MAX_LOADED_TRACK_POINTS_PER_BATCH = 1000;
/** /**
* Maximum number of way points displayed by the map overlay. * Maximum number of way points displayed by the map overlay.
*/ */
@@ -216,6 +222,20 @@ public abstract class Constants {
public static final String MAPSHOP_BASE_URL = public static final String MAPSHOP_BASE_URL =
"http://maps.google.com/maps/ms"; "http://maps.google.com/maps/ms";
/*
* Default values - keep in sync with those in preferences.xml.
*/
public static final int DEFAULT_ANNOUNCEMENT_FREQUENCY = -1;
public static final int DEFAULT_AUTO_RESUME_TRACK_TIMEOUT = 10; // In min.
public static final int DEFAULT_MAX_RECORDING_DISTANCE = 200;
public static final int DEFAULT_MIN_RECORDING_DISTANCE = 5;
public static final int DEFAULT_MIN_RECORDING_INTERVAL = 0;
public static final int DEFAULT_MIN_REQUIRED_ACCURACY = 200;
public static final int DEFAULT_SPLIT_FREQUENCY = 0;
public static final String SETTINGS_NAME = "SettingsActivity";
/** /**
* This is an abstract utility class. * This is an abstract utility class.
*/ */
@@ -61,8 +61,9 @@ public class DeleteAllTracks extends Handler {
Log.w(Constants.TAG, "deleting all!"); Log.w(Constants.TAG, "deleting all!");
MyTracksProviderUtils.Factory.get(context).deleteAllTracks(); MyTracksProviderUtils.Factory.get(context).deleteAllTracks();
SharedPreferences prefs = SharedPreferences prefs =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
// TODO: Go through data manager
editor.putLong(context.getString(R.string.selected_track_key), -1); editor.putLong(context.getString(R.string.selected_track_key), -1);
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(editor); ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(editor);
if (done != null) { if (done != null) {
@@ -17,10 +17,10 @@ package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.io.TrackWriter; import com.google.android.apps.mytracks.io.file.TrackWriter;
import com.google.android.apps.mytracks.io.TrackWriterFactory; import com.google.android.apps.mytracks.io.file.TrackWriterFactory;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat; import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Activity; import android.app.Activity;
@@ -113,14 +113,14 @@ public class ExportAllTracks {
*/ */
private void aquireLocksAndExport() { private void aquireLocksAndExport() {
SharedPreferences prefs = SharedPreferences prefs =
activity.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); activity.getSharedPreferences(Constants.SETTINGS_NAME, 0);
long recordingTrackId = -1; long recordingTrackId = -1;
if (prefs != null) { if (prefs != null) {
recordingTrackId = recordingTrackId =
prefs.getLong(activity.getString(R.string.recording_track_key), -1); prefs.getLong(activity.getString(R.string.recording_track_key), -1);
} }
if (recordingTrackId != -1) { if (recordingTrackId != -1) {
wakeLock = MyTracksUtils.acquireWakeLock(activity, wakeLock); wakeLock = SystemUtils.acquireWakeLock(activity, wakeLock);
} }
// Now we can safely export everything. // Now we can safely export everything.
@@ -16,9 +16,9 @@
package com.google.android.apps.mytracks; package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.io.GpxImporter; import com.google.android.apps.mytracks.io.file.GpxImporter;
import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Activity; import android.app.Activity;
@@ -82,13 +82,13 @@ public class ImportAllTracks {
* track. Acquire a wake lock if there is no current track. * track. Acquire a wake lock if there is no current track.
*/ */
private void aquireLocksAndImport() { private void aquireLocksAndImport() {
SharedPreferences prefs = activity.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); SharedPreferences prefs = activity.getSharedPreferences(Constants.SETTINGS_NAME, 0);
long recordingTrackId = -1; long recordingTrackId = -1;
if (prefs != null) { if (prefs != null) {
recordingTrackId = prefs.getLong(activity.getString(R.string.recording_track_key), -1); recordingTrackId = prefs.getLong(activity.getString(R.string.recording_track_key), -1);
} }
if (recordingTrackId != -1) { if (recordingTrackId != -1) {
wakeLock = MyTracksUtils.acquireWakeLock(activity, wakeLock); wakeLock = SystemUtils.acquireWakeLock(activity, wakeLock);
} }
// Now we can safely import everything. // Now we can safely import everything.
@@ -16,7 +16,7 @@
package com.google.android.apps.mytracks; package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.maps.GeoPoint; import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView; import com.google.android.maps.MapView;
import com.google.android.maps.Overlay; import com.google.android.maps.Overlay;
@@ -45,7 +45,7 @@ import java.util.concurrent.BlockingQueue;
* *
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
*/ */
public class MyTracksOverlay extends Overlay { public class MapOverlay extends Overlay {
private final Drawable[] arrows; private final Drawable[] arrows;
private final int arrowWidth, arrowHeight; private final int arrowWidth, arrowHeight;
@@ -80,13 +80,24 @@ public class MyTracksOverlay extends Overlay {
public final boolean valid; public final boolean valid;
public final GeoPoint geoPoint; public final GeoPoint geoPoint;
/**
* Constructor for an invalid cached location.
*/
public CachedLocation() {
this.valid = false;
this.geoPoint = null;
}
/**
* Constructor for a potentially valid cached location.
*/
public CachedLocation(Location location) { public CachedLocation(Location location) {
this.valid = MyTracksUtils.isValidLocation(location); this.valid = LocationUtils.isValidLocation(location);
this.geoPoint = valid ? MyTracksUtils.getGeoPoint(location) : null; this.geoPoint = valid ? LocationUtils.getGeoPoint(location) : null;
} }
}; };
public MyTracksOverlay(Context context) { public MapOverlay(Context context) {
this.context = context; this.context = context;
this.waypoints = new ArrayList<Waypoint>(); this.waypoints = new ArrayList<Waypoint>();
@@ -164,6 +175,13 @@ public class MyTracksOverlay extends Overlay {
pendingPoints.offer(new CachedLocation(l)); pendingPoints.offer(new CachedLocation(l));
} }
/**
* Adds a segment split to the map overlay.
*/
public void addSegmentSplit() {
pendingPoints.offer(new CachedLocation());
}
public void addWaypoint(Waypoint wpt) { public void addWaypoint(Waypoint wpt) {
// Note: We don't cache waypoints, because it's not worth the effort. // Note: We don't cache waypoints, because it's not worth the effort.
if (wpt != null && wpt.getLocation() != null) { if (wpt != null && wpt.getLocation() != null) {
@@ -260,7 +278,7 @@ public class MyTracksOverlay extends Overlay {
synchronized (waypoints) {; synchronized (waypoints) {;
for (Waypoint wpt : waypoints) { for (Waypoint wpt : waypoints) {
Location loc = wpt.getLocation(); Location loc = wpt.getLocation();
drawElement(canvas, projection, MyTracksUtils.getGeoPoint(loc), drawElement(canvas, projection, LocationUtils.getGeoPoint(loc),
wpt.getType() == Waypoint.TYPE_STATISTICS ? statsMarker wpt.getType() == Waypoint.TYPE_STATISTICS ? statsMarker
: waypointMarker, -(markerWidth / 2) + 3, -markerHeight); : waypointMarker, -(markerWidth / 2) + 3, -markerHeight);
} }
@@ -274,7 +292,7 @@ public class MyTracksOverlay extends Overlay {
} }
Point pt = drawElement(canvas, projection, Point pt = drawElement(canvas, projection,
MyTracksUtils.getGeoPoint(myLocation), arrows[lastHeading], LocationUtils.getGeoPoint(myLocation), arrows[lastHeading],
-(arrowWidth / 2) + 3, -(arrowHeight / 2)); -(arrowWidth / 2) + 3, -(arrowHeight / 2));
// Draw the error circle. // Draw the error circle.
float radius = projection.metersToEquatorPixels(myLocation.getAccuracy()); float radius = projection.metersToEquatorPixels(myLocation.getAccuracy());
@@ -423,7 +441,7 @@ public class MyTracksOverlay extends Overlay {
return false; return false;
} }
final Location tapLocation = MyTracksUtils.getLocation(p); final Location tapLocation = LocationUtils.getLocation(p);
double dmin = Double.MAX_VALUE; double dmin = Double.MAX_VALUE;
Waypoint waypoint = null; Waypoint waypoint = null;
synchronized (waypoints) { synchronized (waypoints) {
@@ -78,7 +78,7 @@ class MenuManager {
return startActivity(SensorStateActivity.class); return startActivity(SensorStateActivity.class);
} }
case R.id.menu_settings: { case R.id.menu_settings: {
return startActivity(MyTracksSettings.class); return startActivity(SettingsActivity.class);
} }
case R.id.menu_aggregated_stats: { case R.id.menu_aggregated_stats: {
return startActivity(AggregatedStatsActivity.class); return startActivity(AggregatedStatsActivity.class);
@@ -87,7 +87,7 @@ class MenuManager {
return startActivity(WelcomeActivity.class); return startActivity(WelcomeActivity.class);
} }
case Constants.MENU_CLEAR_MAP: { case Constants.MENU_CLEAR_MAP: {
activity.setSelectedTrackId(-1); activity.clearSelectedTrack();
return true; return true;
} }
} }
@@ -27,15 +27,15 @@ import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.WaypointCreationRequest; import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.io.AuthManager; import com.google.android.apps.mytracks.io.AuthManager;
import com.google.android.apps.mytracks.io.AuthManagerFactory; import com.google.android.apps.mytracks.io.AuthManagerFactory;
import com.google.android.apps.mytracks.io.GpxImporter;
import com.google.android.apps.mytracks.io.SendToDocs; import com.google.android.apps.mytracks.io.SendToDocs;
import com.google.android.apps.mytracks.io.SendToFusionTables; import com.google.android.apps.mytracks.io.SendToFusionTables;
import com.google.android.apps.mytracks.io.SendToFusionTables.OnSendCompletedListener; import com.google.android.apps.mytracks.io.SendToFusionTables.OnSendCompletedListener;
import com.google.android.apps.mytracks.io.SendToMyMaps; import com.google.android.apps.mytracks.io.SendToMyMaps;
import com.google.android.apps.mytracks.io.TempFileCleaner; import com.google.android.apps.mytracks.io.file.GpxImporter;
import com.google.android.apps.mytracks.io.TrackWriter; import com.google.android.apps.mytracks.io.file.TempFileCleaner;
import com.google.android.apps.mytracks.io.TrackWriterFactory; import com.google.android.apps.mytracks.io.file.TrackWriter;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat; import com.google.android.apps.mytracks.io.file.TrackWriterFactory;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade; import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants; import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants;
import com.google.android.apps.mytracks.io.sendtogoogle.ResultDialogFactory; import com.google.android.apps.mytracks.io.sendtogoogle.ResultDialogFactory;
@@ -47,7 +47,7 @@ import com.google.android.apps.mytracks.services.TrackRecordingService;
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory; import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.util.ApiFeatures; import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Activity; import android.app.Activity;
@@ -55,15 +55,11 @@ import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.TabActivity; import android.app.TabActivity;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Resources; import android.content.res.Resources;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@@ -101,12 +97,13 @@ import org.xml.sax.SAXException;
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
*/ */
public class MyTracks extends TabActivity implements OnTouchListener, public class MyTracks extends TabActivity implements OnTouchListener,
OnSharedPreferenceChangeListener, ProgressIndicator { ProgressIndicator {
/** /**
* Singleton instance * Singleton instance
*/ */
private static MyTracks instance; private static MyTracks instance;
private TrackDataHub dataHub;
private ChartActivity chartActivity; private ChartActivity chartActivity;
/* /*
@@ -150,16 +147,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
private ITrackRecordingService trackRecordingService; private ITrackRecordingService trackRecordingService;
/**
* The id of the currently recording track.
*/
private long recordingTrackId = -1;
/**
* The id of the currently selected track.
*/
private long selectedTrackId = -1;
/** /**
* Does the user want to share the current track. * Does the user want to share the current track.
*/ */
@@ -234,7 +221,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
public boolean isRecording() { public boolean isRecording() {
if (trackRecordingService == null) { if (trackRecordingService == null) {
// Fall back to alternative check method. // Fall back to alternative check method.
return isRecordingBasedOnSharedPreferences(); return dataHub.isRecording();
} }
try { try {
return trackRecordingService.isRecording(); return trackRecordingService.isRecording();
@@ -244,16 +231,10 @@ public class MyTracks extends TabActivity implements OnTouchListener,
Log.e(TAG, "MyTracks: Remote exception.", e); Log.e(TAG, "MyTracks: Remote exception.", e);
// Fall back to alternative check method. // Fall back to alternative check method.
return isRecordingBasedOnSharedPreferences(); return dataHub.isRecording();
} }
} }
private boolean isRecordingBasedOnSharedPreferences() {
// TrackRecordingService guarantees that recordingTrackId is set to
// -1 if the track has been stopped.
return recordingTrackId >= 0;
}
/* /*
* Application lifetime events: * Application lifetime events:
* ============================ * ============================
@@ -265,13 +246,14 @@ public class MyTracks extends TabActivity implements OnTouchListener,
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
instance = this; instance = this;
ApiFeatures apiFeatures = ApiFeatures.getInstance(); ApiFeatures apiFeatures = ApiFeatures.getInstance();
if (!MyTracksUtils.isRelease(this)) { if (!SystemUtils.isRelease(this)) {
apiFeatures.getApiPlatformAdapter().enableStrictMode(); apiFeatures.getApiPlatformAdapter().enableStrictMode();
} }
providerUtils = MyTracksProviderUtils.Factory.get(this); providerUtils = MyTracksProviderUtils.Factory.get(this);
dataHub = new TrackDataHub(this, providerUtils);
menuManager = new MenuManager(this); menuManager = new MenuManager(this);
sharedPreferences = getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
dialogManager = new DialogManager(this); dialogManager = new DialogManager(this);
// The volume we want to control is the Text-To-Speech volume // The volume we want to control is the Text-To-Speech volume
@@ -287,7 +269,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
tabHost.addTab(tabHost.newTabSpec("tab1") tabHost.addTab(tabHost.newTabSpec("tab1")
.setIndicator("Map", res.getDrawable( .setIndicator("Map", res.getDrawable(
android.R.drawable.ic_menu_mapmode)) android.R.drawable.ic_menu_mapmode))
.setContent(new Intent(this, MyTracksMap.class))); .setContent(new Intent(this, MapActivity.class)));
tabHost.addTab(tabHost.newTabSpec("tab2") tabHost.addTab(tabHost.newTabSpec("tab2")
.setIndicator("Stats", res.getDrawable(R.drawable.menu_stats)) .setIndicator("Stats", res.getDrawable(R.drawable.menu_stats))
.setContent(new Intent(this, StatsActivity.class))); .setContent(new Intent(this, StatsActivity.class)));
@@ -312,20 +294,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
tabHost.addView(layout); tabHost.addView(layout);
layout.setOnTouchListener(this); layout.setOnTouchListener(this);
if (sharedPreferences != null) {
selectedTrackId =
sharedPreferences.getLong(getString(R.string.selected_track_key), -1);
recordingTrackId = sharedPreferences.getLong(
getString(R.string.recording_track_key), -1);
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
Log.d(TAG, "recordingTrackId: " + recordingTrackId
+ ", selectedTrackId: " + selectedTrackId);
if (recordingTrackId > 0) {
Intent startIntent = new Intent(this, TrackRecordingService.class);
startService(startIntent);
}
}
// This will show the eula until the user accepts or quits the app. // This will show the eula until the user accepts or quits the app.
Eula.showEulaRequireAcceptance(this); Eula.showEulaRequireAcceptance(this);
@@ -353,10 +321,24 @@ public class MyTracks extends TabActivity implements OnTouchListener,
@Override @Override
protected void onDestroy() { protected void onDestroy() {
Log.d(TAG, "MyTracks.onDestroy"); Log.d(TAG, "MyTracks.onDestroy");
dataHub.destroy();
tryUnbindTrackRecordingService(); tryUnbindTrackRecordingService();
super.onDestroy(); super.onDestroy();
} }
@Override
protected void onStop() {
Log.d(TAG, "MyTracks.onStop");
dataHub.stop();
// Clean up any temporary track files.
TempFileCleaner.clean();
super.onStop();
}
@Override @Override
protected void onPause() { protected void onPause() {
// Called when activity is going into the background, but has not (yet) been // Called when activity is going into the background, but has not (yet) been
@@ -376,11 +358,10 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
@Override @Override
protected void onStop() { protected void onStart() {
Log.d(TAG, "MyTracks.onStop"); Log.d(TAG, "MyTracks.onStart");
// Clean up any temporary track files. super.onStart();
TempFileCleaner.clean(); dataHub.start();
super.onStop();
} }
/* /*
@@ -397,7 +378,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) {
menuManager.onPrepareOptionsMenu(menu, providerUtils.getLastTrack() != null, menuManager.onPrepareOptionsMenu(menu, providerUtils.getLastTrack() != null,
isRecording(), selectedTrackId >= 0); isRecording(), dataHub.isATrackSelected());
return super.onPrepareOptionsMenu(menu); return super.onPrepareOptionsMenu(menu);
} }
@@ -455,6 +436,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
public void onActivityResult(int requestCode, int resultCode, public void onActivityResult(int requestCode, int resultCode,
final Intent results) { final Intent results) {
TrackFileFormat exportFormat = null; TrackFileFormat exportFormat = null;
final long trackId = results.getLongExtra("trackid", dataHub.getSelectedTrackId());
switch (requestCode) { switch (requestCode) {
case Constants.GET_LOGIN: { case Constants.GET_LOGIN: {
if (resultCode != RESULT_OK || auth == null || !auth.authResult(resultCode, results)) { if (resultCode != RESULT_OK || auth == null || !auth.authResult(resultCode, results)) {
@@ -464,9 +446,9 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
case Constants.SHOW_TRACK: { case Constants.SHOW_TRACK: {
if (results != null) { if (results != null) {
final long trackId = results.getLongExtra("trackid", -1);
if (trackId >= 0) { if (trackId >= 0) {
setSelectedTrackId(trackId); dataHub.loadTrack(trackId);
// The track list passed the requested action as result code. Hand // The track list passed the requested action as result code. Hand
// it off to the onAcitivtyResult for further processing: // it off to the onAcitivtyResult for further processing:
if (resultCode != Constants.SHOW_TRACK) { if (resultCode != Constants.SHOW_TRACK) {
@@ -480,8 +462,8 @@ public class MyTracks extends TabActivity implements OnTouchListener,
if (results != null) { if (results != null) {
final long waypointId = results.getLongExtra("waypointid", -1); final long waypointId = results.getLongExtra("waypointid", -1);
if (waypointId >= 0) { if (waypointId >= 0) {
MyTracksMap map = MapActivity map =
(MyTracksMap) getLocalActivityManager().getActivity("tab1"); (MapActivity) getLocalActivityManager().getActivity("tab1");
if (map != null) { if (map != null) {
getTabHost().setCurrentTab(0); getTabHost().setCurrentTab(0);
map.showWaypoint(waypointId); map.showWaypoint(waypointId);
@@ -492,14 +474,12 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
case Constants.DELETE_TRACK: { case Constants.DELETE_TRACK: {
if (results != null && resultCode == RESULT_OK) { if (results != null && resultCode == RESULT_OK) {
final long trackId = results.getLongExtra("trackid", selectedTrackId);
deleteTrack(trackId); deleteTrack(trackId);
} }
break; break;
} }
case Constants.EDIT_DETAILS: { case Constants.EDIT_DETAILS: {
if (results != null && resultCode == RESULT_OK) { if (results != null && resultCode == RESULT_OK) {
final long trackId = results.getLongExtra("trackid", selectedTrackId);
Intent intent = new Intent(this, TrackDetails.class); Intent intent = new Intent(this, TrackDetails.class);
intent.putExtra("trackid", trackId); intent.putExtra("trackid", trackId);
startActivity(intent); startActivity(intent);
@@ -514,7 +494,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
case Constants.GET_MAP: { case Constants.GET_MAP: {
// User picked a map to upload to // User picked a map to upload to
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
results.putExtra("trackid", selectedTrackId); results.putExtra("trackid", dataHub.getSelectedTrackId());
if (results.hasExtra("mapid")) { if (results.hasExtra("mapid")) {
sendToMyMapsMapId = results.getStringExtra("mapid"); sendToMyMapsMapId = results.getStringExtra("mapid");
} }
@@ -528,17 +508,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
// Authenticated with Google My Maps // Authenticated with Google My Maps
if (results != null && resultCode == RESULT_OK) { if (results != null && resultCode == RESULT_OK) {
final String mapId; final String mapId;
final long trackId;
if (results.hasExtra("mapid")) { if (results.hasExtra("mapid")) {
mapId = results.getStringExtra("mapid"); mapId = results.getStringExtra("mapid");
} else { } else {
mapId = "new"; mapId = "new";
} }
if (results.hasExtra("trackid")) {
trackId = results.getLongExtra("trackid", -1);
} else {
trackId = selectedTrackId;
}
sendToGoogleMaps(trackId, mapId); sendToGoogleMaps(trackId, mapId);
} else { } else {
@@ -549,13 +523,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
case Constants.AUTHENTICATE_TO_FUSION_TABLES: { case Constants.AUTHENTICATE_TO_FUSION_TABLES: {
// Authenticated with Google Fusion Tables // Authenticated with Google Fusion Tables
if (results != null && resultCode == RESULT_OK) { if (results != null && resultCode == RESULT_OK) {
final long trackId;
if (results.hasExtra("trackid")) {
trackId = results.getLongExtra("trackid", -1);
} else {
trackId = selectedTrackId;
}
sendToFusionTables(trackId); sendToFusionTables(trackId);
} else { } else {
onSendToGoogleDone(); onSendToGoogleDone();
@@ -574,7 +541,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
case Constants.AUTHENTICATE_TO_TRIX: { case Constants.AUTHENTICATE_TO_TRIX: {
// Authenticated with Trix // Authenticated with Trix
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
final long trackId = results.getLongExtra("trackid", selectedTrackId);
sendToGoogleDocs(trackId); sendToGoogleDocs(trackId);
} else { } else {
onSendToGoogleDone(); onSendToGoogleDone();
@@ -594,19 +560,18 @@ public class MyTracks extends TabActivity implements OnTouchListener,
if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; } if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; }
if (results != null && resultCode == Activity.RESULT_OK) { if (results != null && resultCode == Activity.RESULT_OK) {
final long trackId = results.getLongExtra("trackid", selectedTrackId);
if (trackId >= 0) { if (trackId >= 0) {
saveTrack(trackId, exportFormat); saveTrack(trackId, exportFormat);
} }
} }
break; break;
case Constants.SHARE_LINK: { case Constants.SHARE_LINK: {
Track selectedTrack = providerUtils.getTrack(selectedTrackId); Track selectedTrack = providerUtils.getTrack(dataHub.getSelectedTrackId());
if (selectedTrack != null) { if (selectedTrack != null) {
if (!TextUtils.isEmpty(selectedTrack.getMapId())) { if (!TextUtils.isEmpty(selectedTrack.getMapId())) {
shareLinkToMap(MapsFacade.buildMapUrl(selectedTrack.getMapId())); shareLinkToMap(MapsFacade.buildMapUrl(selectedTrack.getMapId()));
} else if (!TextUtils.isEmpty(selectedTrack.getTableId())) { } else if (!TextUtils.isEmpty(selectedTrack.getTableId())) {
shareLinkToMap(getFusionTablesUrl(selectedTrackId)); shareLinkToMap(getFusionTablesUrl(dataHub.getSelectedTrackId()));
} else { } else {
shareRequested = true; shareRequested = true;
dialogManager.showDialogSafely(DIALOG_SEND_TO_GOOGLE); dialogManager.showDialogSafely(DIALOG_SEND_TO_GOOGLE);
@@ -627,7 +592,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; } if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; }
if (results != null && resultCode == Activity.RESULT_OK) { if (results != null && resultCode == Activity.RESULT_OK) {
final long trackId = results.getLongExtra("trackid", selectedTrackId);
if (trackId >= 0) { if (trackId >= 0) {
sendTrack(trackId, exportFormat); sendTrack(trackId, exportFormat);
} }
@@ -635,7 +599,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
break; break;
} }
case Constants.CLEAR_MAP: { case Constants.CLEAR_MAP: {
setSelectedTrackId(-1); dataHub.unloadCurrentTrack();
break; break;
} }
case Constants.WELCOME: { case Constants.WELCOME: {
@@ -657,19 +621,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
return false; return false;
} }
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key != null && key.equals(getString(R.string.selected_track_key))) {
selectedTrackId = sharedPreferences.getLong(
getString(R.string.selected_track_key), -1);
}
if (key != null && key.equals(getString(R.string.recording_track_key))) {
recordingTrackId = sharedPreferences.getLong(
getString(R.string.recording_track_key), -1);
}
}
/** /**
* Resets status information for sending to MyMaps/Docs. * Resets status information for sending to MyMaps/Docs.
*/ */
@@ -715,7 +666,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
if (trackIdsImported != null && trackIdsImported.length > 0) { if (trackIdsImported != null && trackIdsImported.length > 0) {
// select last track from import file // select last track from import file
setSelectedTrackId(trackIdsImported[trackIdsImported.length - 1]); dataHub.loadTrack(trackIdsImported[trackIdsImported.length - 1]);
} else { } else {
dialogManager.showMessageDialog(message, false/* success */); dialogManager.showMessageDialog(message, false/* success */);
} }
@@ -787,8 +738,8 @@ public class MyTracks extends TabActivity implements OnTouchListener,
public void onClick(DialogInterface dialog, int i) { public void onClick(DialogInterface dialog, int i) {
dialog.dismiss(); dialog.dismiss();
providerUtils.deleteTrack(trackId); providerUtils.deleteTrack(trackId);
if (trackId == selectedTrackId) { if (trackId == dataHub.getSelectedTrackId()) {
setSelectedTrackId(-1); dataHub.unloadCurrentTrack();
} }
}}); }});
builder.setNegativeButton(getString(R.string.no), builder.setNegativeButton(getString(R.string.no),
@@ -801,46 +752,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
dialog.show(); dialog.show();
} }
public Location getCurrentLocation() {
// TODO: Let's look at more advanced algorithms to determine the best
// current location.
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (locationManager == null) {
return null;
}
final long maxAgeMilliSeconds = 1000 * 60 * 1; // 1 minute
final long maxAgeNetworkMilliSeconds = 1000 * 60 * 10; // 10 minutes
final long now = System.currentTimeMillis();
Location loc = locationManager.getLastKnownLocation(
Constants.GPS_PROVIDER);
if (loc == null || loc.getTime() < now - maxAgeMilliSeconds) {
// We don't have a recent GPS fix, just use cell towers if available
loc = locationManager.getLastKnownLocation(
LocationManager.NETWORK_PROVIDER);
if (loc == null || loc.getTime() < now - maxAgeNetworkMilliSeconds) {
// We don't have a recent cell tower location, let the user know:
Toast.makeText(this, getString(R.string.status_no_location),
Toast.LENGTH_LONG).show();
return null;
} else {
// Let the user know we have only an approximate location:
Toast.makeText(this, getString(R.string.status_approximate_location),
Toast.LENGTH_LONG).show();
}
}
return loc;
}
public Location getLastLocation() {
if (providerUtils.getLastLocationId(recordingTrackId) < 0) {
return null;
}
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
return locationManager.getLastKnownLocation(Constants.GPS_PROVIDER);
}
/** /**
* Inserts a waypoint marker. * Inserts a waypoint marker.
* *
@@ -917,9 +828,9 @@ public class MyTracks extends TabActivity implements OnTouchListener,
private void startRecordingNewTrack( private void startRecordingNewTrack(
ITrackRecordingService trackRecordingService) { ITrackRecordingService trackRecordingService) {
try { try {
recordingTrackId = trackRecordingService.startNewTrack(); long recordingTrackId = trackRecordingService.startNewTrack();
// Select the recording track. // Select the recording track.
setSelectedTrackId(recordingTrackId); dataHub.loadTrack(recordingTrackId);
Toast.makeText(this, getString(R.string.status_now_recording), Toast.makeText(this, getString(R.string.status_now_recording),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
// TODO: We catch Exception, because after eliminating the service process // TODO: We catch Exception, because after eliminating the service process
@@ -954,7 +865,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
public void stopRecording() { public void stopRecording() {
if (trackRecordingService != null) { if (trackRecordingService != null) {
// Save the track id as the shared preference will overwrite the recording track id. // Save the track id as the shared preference will overwrite the recording track id.
long currentTrackId = recordingTrackId; long currentTrackId = sharedPreferences.getLong(getString(R.string.recording_track_key), -1);
try { try {
trackRecordingService.endCurrentTrack(); trackRecordingService.endCurrentTrack();
// TODO: We catch Exception, because after eliminating the service process // TODO: We catch Exception, because after eliminating the service process
@@ -962,10 +873,13 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Unable to stop recording.", e); Log.e(TAG, "Unable to stop recording.", e);
} }
Intent intent = new Intent(MyTracks.this, TrackDetails.class);
intent.putExtra("trackid", currentTrackId); if (currentTrackId > 0) {
intent.putExtra("hasCancelButton", false); Intent intent = new Intent(MyTracks.this, TrackDetails.class);
startActivity(intent); intent.putExtra("trackid", currentTrackId);
intent.putExtra("hasCancelButton", false);
startActivity(intent);
}
} }
tryUnbindTrackRecordingService(); tryUnbindTrackRecordingService();
try { try {
@@ -1259,44 +1173,12 @@ public class MyTracks extends TabActivity implements OnTouchListener,
return results; return results;
} }
String getSendToGoogleResultMessage() { void clearSelectedTrack() {
StringBuilder message = new StringBuilder(); dataHub.unloadCurrentTrack();
SendDialog sendToGoogleDialog =
dialogManager.getSendToGoogleDialog();
if (sendToGoogleDialog.getSendToMyMaps()) {
message.append(sendToMyMapsMessage);
}
if (sendToGoogleDialog.getSendToFusionTables()) {
message.append(sendToFusionTablesMessage);
}
if (sendToGoogleDialog.getSendToDocs()) {
if (message.length() > 0) {
message.append(' ');
}
message.append(sendToDocsMessage);
}
if (sendToMyMapsSuccess && sendToFusionTablesSuccess && sendToDocsSuccess) {
message.append(' ');
message.append(getString(R.string.status_mymap_info));
}
return message.toString();
}
/**
* Writes the selected track id to the shared preferences.
* Executed on the UI thread.
*
* @param trackId the id of the track
*/
public void setSelectedTrackId(final long trackId) {
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(
sharedPreferences
.edit()
.putLong(getString(R.string.selected_track_key), trackId));
} }
long getSelectedTrackId() { long getSelectedTrackId() {
return selectedTrackId; return dataHub.getSelectedTrackId();
} }
/** /**
@@ -1419,7 +1301,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
// @VisibleForTesting // @VisibleForTesting
long getRecordingTrackId() { long getRecordingTrackId() {
return recordingTrackId; return sharedPreferences.getLong(getString(R.string.recording_track_key), -1);
} }
// @VisibleForTesting // @VisibleForTesting
@@ -1436,4 +1318,8 @@ public class MyTracks extends TabActivity implements OnTouchListener,
ITrackRecordingService getTrackRecordingService() { ITrackRecordingService getTrackRecordingService() {
return trackRecordingService; return trackRecordingService;
} }
public TrackDataHub getDataHub() {
return dataHub;
}
} }
@@ -54,28 +54,14 @@ import java.util.Set;
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
* @author Rodrigo Damazio * @author Rodrigo Damazio
*/ */
public class MyTracksSettings extends PreferenceActivity { public class SettingsActivity extends PreferenceActivity {
public static final String SETTINGS_NAME = "MyTracksSettings";
/*
* Default values - keep in sync with those in preferences.xml.
*/
public static final int DEFAULT_AUTO_RESUME_TRACK_TIMEOUT = 10; // In min.
public static final int DEFAULT_ANNOUNCEMENT_FREQUENCY = -1;
public static final int DEFAULT_MAX_RECORDING_DISTANCE = 200;
public static final int DEFAULT_MIN_RECORDING_DISTANCE = 5;
public static final int DEFAULT_MIN_RECORDING_INTERVAL = 0;
public static final int DEFAULT_MIN_REQUIRED_ACCURACY = 200;
public static final int DEFAULT_SPLIT_FREQUENCY = 0;
private BackupPreferencesListener backupListener; private BackupPreferencesListener backupListener;
private SharedPreferences preferences; private SharedPreferences preferences;
/** Called when the activity is first created. */ /** Called when the activity is first created. */
@Override @Override
public void onCreate(Bundle icicle) { protected void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
// The volume we want to control is the Text-To-Speech volume // The volume we want to control is the Text-To-Speech volume
@@ -86,7 +72,7 @@ public class MyTracksSettings extends PreferenceActivity {
// Tell it where to read/write preferences // Tell it where to read/write preferences
PreferenceManager preferenceManager = getPreferenceManager(); PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.setSharedPreferencesName(SETTINGS_NAME); preferenceManager.setSharedPreferencesName(Constants.SETTINGS_NAME);
preferenceManager.setSharedPreferencesMode(0); preferenceManager.setSharedPreferencesMode(0);
// Set up automatic preferences backup // Set up automatic preferences backup
@@ -219,7 +205,7 @@ public class MyTracksSettings extends PreferenceActivity {
@Override @Override
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
BackupActivityHelper backupHelper = BackupActivityHelper backupHelper =
new BackupActivityHelper(MyTracksSettings.this); new BackupActivityHelper(SettingsActivity.this);
backupHelper.writeBackup(); backupHelper.writeBackup();
return true; return true;
} }
@@ -229,7 +215,7 @@ public class MyTracksSettings extends PreferenceActivity {
@Override @Override
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
BackupActivityHelper backupHelper = BackupActivityHelper backupHelper =
new BackupActivityHelper(MyTracksSettings.this); new BackupActivityHelper(SettingsActivity.this);
backupHelper.restoreBackup(); backupHelper.restoreBackup();
return true; return true;
} }
@@ -373,7 +359,7 @@ public class MyTracksSettings extends PreferenceActivity {
public void run() { public void run() {
// Give feedback to the user. // Give feedback to the user.
Toast.makeText( Toast.makeText(
MyTracksSettings.this, SettingsActivity.this,
R.string.settings_reset_done, R.string.settings_reset_done,
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,169 @@
/*
* 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.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import android.location.Location;
/**
* Listener for track data, for both initial and incremental loading.
*
* TODO: Allow listening to just part of the data received here.
*
* @author Rodrigo Damazio
*/
public interface TrackDataListener {
/** States for the GPS location provider. */
public enum ProviderState {
DISABLED,
NO_FIX,
BAD_FIX,
GOOD_FIX;
}
/**
* Called when the location provider changes state.
*/
void onProviderStateChange(ProviderState state);
/**
* Called when the current location changes.
* This is meant for immediate location display only - track point data is
* delivered by other methods below, such as {@link #onNewTrackPoint}.
*
* @param loc the last known location
*/
void onCurrentLocationChanged(Location loc);
/**
* Called when the current heading changes.
*
* @param heading the current heading, already accounting magnetic declination
*/
void onCurrentHeadingChanged(double heading);
// This is always followed by calls to onTrackUpdated/onNewTrackPoints/onWaypointsChanged
// The recipient has a chance to unregister here before that happens.
/**
* Called when the currently-selected track changes.
* This will be followed by calls to data methods such as
* {@link #onTrackUpdated}, {@link #clearTrackPoints},
* {@link #onNewTrackPoint(Location)}, etc., even if no track is currently
* selected (in which case you'll only get calls to clear the current data).
*
* @param track the selected track, or null if no track is selected
* @param isRecording whether we're currently recording the selected track
*/
void onSelectedTrackChanged(Track track, boolean isRecording);
// Called when the already-selected track gets updated
/**
* Called when the track and/or its statistics have been updated.
*
* @param track the updated version of the track
*/
void onTrackUpdated(Track track);
// Map, chart - points, waypoints
// Stats - track
// Points are loaded progressively in batches
// Track is always loaded
// Waypoints are always fully loaded (limit to MyTracksConstants.MAX_DISPLAYED_WAYPOINTS_POINTS)
// Initial load - clear + N * onNewTrackPoint + onNewTrackPointsDone
// New points - onNewTrackPoint + onNewTrackPointsDone
// Points passed in are already sampled (but can be invalid to denote a split)
// If needs to resample, repeats initial load
/**
* Called to clear any previously-sent track points.
* This can be called at any time that we decide the data needs to be
* reloaded, such as when it needs to be resampled.
*/
void clearTrackPoints();
/**
* Called when a new interesting track point is read.
* In this case, interesting means that the point has already undergone
* sampling and invalid point filtering.
*
* @param loc the new track point
*/
void onNewTrackPoint(Location loc);
/**
* Called when a uninteresting track point is read.
* Uninteresting points are all points that get sampled out of the track.
*
* @param loc the new track point
*/
void onSampledOutTrackPoint(Location loc);
/**
* Called when an invalid point (representing a segment split) is read.
*/
void onSegmentSplit();
/**
* Called when we're done (for the time being) sending new points.
* This gets called after every batch of calls to {@link #onNewTrackPoint},
* {@link #onSampledOutTrackPoint} and {@link #onSegmentSplit}.
*/
void onNewTrackPointsDone();
/**
* Called to clear any previously-sent waypoints.
* This can be called at any time that we decide the data needs to be
* reloaded.
*/
void clearWaypoints();
/**
* Called when a new waypoint is read.
*
* @param wpt the new waypoint
*/
void onNewWaypoint(Waypoint wpt);
/**
* Called when we're done (for the time being) sending new waypoints.
* This gets called after every batch of calls to {@link #clearWaypoints} and
* {@link #onNewWaypoint}.
*/
void onNewWaypointsDone();
/**
* Called when the display units are changed by the user.
*
* @param metric true if the units are metric, false if imperial
* @return true to reload all the data, false otherwise
*/
boolean onUnitsChanged(boolean metric);
/**
* Called when the speed/pace display unit is changed by the user.
*
* @param reportSpeed true to report speed, false for pace
* @return true to reload all the data, false otherwise
*/
boolean onReportSpeedChanged(boolean reportSpeed);
}
@@ -202,7 +202,7 @@ public class TrackList extends ListActivity
findViewById(R.id.tracklist_btn_import_all).setOnClickListener(this); findViewById(R.id.tracklist_btn_import_all).setOnClickListener(this);
SharedPreferences preferences = SharedPreferences preferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); getSharedPreferences(Constants.SETTINGS_NAME, 0);
preferences.registerOnSharedPreferenceChangeListener(this); preferences.registerOnSharedPreferenceChangeListener(this);
metricUnits = metricUnits =
preferences.getBoolean(getString(R.string.metric_units_key), true); preferences.getBoolean(getString(R.string.metric_units_key), true);
@@ -65,7 +65,7 @@ public class WaypointDetails extends Activity
utils = new StatsUtilities(this); utils = new StatsUtilities(this);
SharedPreferences preferences = SharedPreferences preferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (preferences != null) { if (preferences != null) {
boolean useMetric = boolean useMetric =
preferences.getBoolean(getString(R.string.metric_units_key), true); preferences.getBoolean(getString(R.string.metric_units_key), true);
@@ -59,7 +59,6 @@ public class WaypointsList extends ListActivity
private Button insertWaypointButton = null; private Button insertWaypointButton = null;
private Button insertStatisticsButton = null; private Button insertStatisticsButton = null;
private long recordingTrackId = -1; private long recordingTrackId = -1;
private long selectedTrackId = -1;
private MyTracksProviderUtils providerUtils; private MyTracksProviderUtils providerUtils;
private Cursor waypointsCursor = null; private Cursor waypointsCursor = null;
@@ -139,7 +138,10 @@ public class WaypointsList extends ListActivity
(Button) findViewById(R.id.waypointslist_btn_insert_statistics); (Button) findViewById(R.id.waypointslist_btn_insert_statistics);
insertStatisticsButton.setOnClickListener(this); insertStatisticsButton.setOnClickListener(this);
SharedPreferences preferences = SharedPreferences preferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); getSharedPreferences(Constants.SETTINGS_NAME, 0);
// TODO: Get rid of selected and recording track IDs
long selectedTrackId = -1;
if (preferences != null) { if (preferences != null) {
recordingTrackId = recordingTrackId =
preferences.getLong(getString(R.string.recording_track_key), -1); preferences.getLong(getString(R.string.recording_track_key), -1);
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks; package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Activity; import android.app.Activity;
@@ -82,6 +82,6 @@ public class WelcomeActivity extends Activity {
AlertDialog dialog = builder.create(); AlertDialog dialog = builder.create();
dialog.show(); dialog.show();
((TextView) dialog.findViewById(R.id.about_version_register)). ((TextView) dialog.findViewById(R.id.about_version_register)).
setText(MyTracksUtils.getMyTracksVersion(this)); setText(SystemUtils.getMyTracksVersion(this));
} }
} }
@@ -17,7 +17,6 @@ package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.MyTracks; import com.google.android.apps.mytracks.MyTracks;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.docs.DocsHelper; import com.google.android.apps.mytracks.io.docs.DocsHelper;
@@ -73,7 +72,7 @@ public class SendToDocs {
this.trackId = trackId; this.trackId = trackId;
SharedPreferences preferences = activity.getSharedPreferences( SharedPreferences preferences = activity.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
if (preferences != null) { if (preferences != null) {
metricUnits = metricUnits =
preferences.getBoolean(activity.getString(R.string.metric_units_key), preferences.getBoolean(activity.getString(R.string.metric_units_key),
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.ProgressIndicator; import com.google.android.apps.mytracks.ProgressIndicator;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
@@ -25,8 +24,9 @@ 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.io.gdata.GDataWrapper.QueryFunction;
import com.google.android.apps.mytracks.stats.DoubleBuffer; import com.google.android.apps.mytracks.stats.DoubleBuffer;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.apps.mytracks.util.StringUtils; 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.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import com.google.api.client.googleapis.GoogleHeaders; import com.google.api.client.googleapis.GoogleHeaders;
@@ -141,7 +141,7 @@ public class SendToFusionTables implements Runnable {
this.providerUtils = MyTracksProviderUtils.Factory.get(context); this.providerUtils = MyTracksProviderUtils.Factory.get(context);
GoogleHeaders headers = new GoogleHeaders(); GoogleHeaders headers = new GoogleHeaders();
headers.setApplicationName("Google-MyTracks-" + MyTracksUtils.getMyTracksVersion(context)); headers.setApplicationName("Google-MyTracks-" + SystemUtils.getMyTracksVersion(context));
headers.gdataVersion = GDATA_VERSION; headers.gdataVersion = GDATA_VERSION;
transport = new HttpTransport(); transport = new HttpTransport();
@@ -296,7 +296,7 @@ public class SendToFusionTables implements Runnable {
private boolean uploadAllTrackPoints(final Track track, String originalDescription) { private boolean uploadAllTrackPoints(final Track track, String originalDescription) {
SharedPreferences preferences = context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); SharedPreferences preferences = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
boolean metricUnits = true; boolean metricUnits = true;
if (preferences != null) { if (preferences != null) {
metricUnits = preferences.getBoolean(context.getString(R.string.metric_units_key), true); metricUnits = preferences.getBoolean(context.getString(R.string.metric_units_key), true);
@@ -344,7 +344,7 @@ public class SendToFusionTables implements Runnable {
} }
// Add to the elevation profile. // Add to the elevation profile.
if (loc != null && MyTracksUtils.isValidLocation(loc)) { if (loc != null && LocationUtils.isValidLocation(loc)) {
// All points go into the smoothing buffer... // All points go into the smoothing buffer...
elevationBuffer.setNext(metricUnits ? loc.getAltitude() elevationBuffer.setNext(metricUnits ? loc.getAltitude()
: loc.getAltitude() * UnitConversions.M_TO_FT); : loc.getAltitude() * UnitConversions.M_TO_FT);
@@ -566,12 +566,12 @@ public class SendToFusionTables implements Runnable {
* Decimate to 2 meter precision. Fusion tables doesn't like too many * Decimate to 2 meter precision. Fusion tables doesn't like too many
* points: * points:
*/ */
MyTracksUtils.decimate(segment, 2.0); LocationUtils.decimate(segment, 2.0);
/* If the track still has > 2500 points, split it in pieces: */ /* If the track still has > 2500 points, split it in pieces: */
final int maxPoints = 2500; final int maxPoints = 2500;
if (segment.getLocations().size() > maxPoints) { if (segment.getLocations().size() > maxPoints) {
splitTracks.addAll(MyTracksUtils.split(segment, maxPoints)); splitTracks.addAll(LocationUtils.split(segment, maxPoints));
} else if (segment.getLocations().size() >= 2) { } else if (segment.getLocations().size() >= 2) {
splitTracks.add(segment); splitTracks.add(segment);
} }
@@ -17,7 +17,6 @@ package com.google.android.apps.mytracks.io;
import static com.google.android.apps.mytracks.Constants.TAG; import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.ProgressIndicator; import com.google.android.apps.mytracks.ProgressIndicator;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
@@ -25,7 +24,7 @@ import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade; import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
import com.google.android.apps.mytracks.stats.DoubleBuffer; import com.google.android.apps.mytracks.stats.DoubleBuffer;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.apps.mytracks.util.UnitConversions; import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -117,7 +116,7 @@ public class SendToMyMaps implements Runnable {
boolean isNewMap = mapId.equals(NEW_MAP_ID); boolean isNewMap = mapId.equals(NEW_MAP_ID);
if (isNewMap) { if (isNewMap) {
SharedPreferences preferences = context.getSharedPreferences( SharedPreferences preferences = context.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
boolean mapPublic = true; boolean mapPublic = true;
if (preferences != null) { if (preferences != null) {
mapPublic = preferences.getBoolean( mapPublic = preferences.getBoolean(
@@ -196,7 +195,7 @@ public class SendToMyMaps implements Runnable {
private boolean uploadAllTrackPoints( private boolean uploadAllTrackPoints(
final Track track, String originalDescription) { final Track track, String originalDescription) {
SharedPreferences preferences = context.getSharedPreferences( SharedPreferences preferences = context.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
boolean metricUnits = true; boolean metricUnits = true;
if (preferences != null) { if (preferences != null) {
metricUnits = metricUnits =
@@ -249,7 +248,7 @@ public class SendToMyMaps implements Runnable {
} }
// Add to the elevation profile. // Add to the elevation profile.
if (loc != null && MyTracksUtils.isValidLocation(loc)) { if (loc != null && LocationUtils.isValidLocation(loc)) {
// All points go into the smoothing buffer... // All points go into the smoothing buffer...
elevationBuffer.setNext(metricUnits ? loc.getAltitude() elevationBuffer.setNext(metricUnits ? loc.getAltitude()
: loc.getAltitude() * UnitConversions.M_TO_FT); : loc.getAltitude() * UnitConversions.M_TO_FT);
@@ -431,11 +430,11 @@ public class SendToMyMaps implements Runnable {
* Decimate to 2 meter precision. Mapshop doesn't like too many * Decimate to 2 meter precision. Mapshop doesn't like too many
* points: * points:
*/ */
MyTracksUtils.decimate(segment, 2.0); LocationUtils.decimate(segment, 2.0);
/* It the track still has > 500 points, split it in pieces: */ /* It the track still has > 500 points, split it in pieces: */
if (segment.getLocations().size() > 500) { if (segment.getLocations().size() > 500) {
splitTracks.addAll(MyTracksUtils.split(segment, 500)); splitTracks.addAll(LocationUtils.split(segment, 500));
} else if (segment.getLocations().size() >= 2) { } else if (segment.getLocations().size() >= 2) {
splitTracks.add(segment); splitTracks.add(segment);
} }
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks.io.backup; package com.google.android.apps.mytracks.io.backup;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.content.TrackPointsColumns; import com.google.android.apps.mytracks.content.TrackPointsColumns;
import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.content.WaypointsColumns; import com.google.android.apps.mytracks.content.WaypointsColumns;
@@ -201,7 +200,7 @@ class ExternalFileBackup {
// Dump preferences // Dump preferences
SharedPreferences preferences = SharedPreferences preferences =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
preferencesHelper.exportPreferences(preferences, outWriter); preferencesHelper.exportPreferences(preferences, outWriter);
} catch (IOException e) { } catch (IOException e) {
// We tried to delete the partially created file, but do nothing // We tried to delete the partially created file, but do nothing
@@ -253,7 +252,7 @@ class ExternalFileBackup {
// Restore preferences // Restore preferences
SharedPreferences preferences = SharedPreferences preferences =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
preferencesHelper.importPreferences(reader, preferences); preferencesHelper.importPreferences(reader, preferences);
} finally { } finally {
compressedStream.close(); compressedStream.close();
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks.io.backup; package com.google.android.apps.mytracks.io.backup;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings;
import android.app.backup.BackupAgent; import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput; import android.app.backup.BackupDataInput;
@@ -42,7 +41,7 @@ public class MyTracksBackupAgent extends BackupAgent {
ParcelFileDescriptor newState) throws IOException { ParcelFileDescriptor newState) throws IOException {
Log.i(Constants.TAG, "Performing backup"); Log.i(Constants.TAG, "Performing backup");
SharedPreferences preferences = this.getSharedPreferences( SharedPreferences preferences = this.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
backupPreferences(data, preferences); backupPreferences(data, preferences);
Log.i(Constants.TAG, "Backup complete"); Log.i(Constants.TAG, "Backup complete");
@@ -92,7 +91,7 @@ public class MyTracksBackupAgent extends BackupAgent {
} }
SharedPreferences preferences = this.getSharedPreferences( SharedPreferences preferences = this.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
PreferenceBackupHelper importer = createPreferenceBackupHelper(); PreferenceBackupHelper importer = createPreferenceBackupHelper();
importer.importPreferences(dataBuffer, preferences); importer.importPreferences(dataBuffer, preferences);
} }
@@ -13,11 +13,11 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat; import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import android.location.Location; import android.location.Location;
@@ -13,13 +13,13 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder; import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.apps.mytracks.util.StringUtils;
import android.location.Location; import android.location.Location;
@@ -362,7 +362,7 @@ public class GpxImporter extends DefaultHandler {
* @throws SAXException - thrown if track point is invalid * @throws SAXException - thrown if track point is invalid
*/ */
private void onTrackPointElementEnd() throws SAXException { private void onTrackPointElementEnd() throws SAXException {
if (MyTracksUtils.isValidLocation(location)) { if (LocationUtils.isValidLocation(location)) {
if (statsBuilder == null) { if (statsBuilder == null) {
// first point did not have a time, start stats builder without it // first point did not have a time, start stats builder without it
statsBuilder = new TripStatisticsBuilder(0); statsBuilder = new TripStatisticsBuilder(0);
@@ -13,11 +13,11 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat; import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.apps.mytracks.util.StringUtils;
import android.location.Location; import android.location.Location;
@@ -13,11 +13,11 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat; import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.apps.mytracks.util.StringUtils;
import android.content.Context; import android.content.Context;
@@ -13,15 +13,15 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat; import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.SystemUtils;
import android.content.Context; import android.content.Context;
import android.location.Location; import android.location.Location;
@@ -236,7 +236,7 @@ public class TcxTrackWriter implements TrackFormatWriter {
// it. The TCX schema tightly defined the Version tag, so we can't put it // it. The TCX schema tightly defined the Version tag, so we can't put it
// there. They've similarly constrained the PartNumber tag, so it can't go // there. They've similarly constrained the PartNumber tag, so it can't go
// there either. // there either.
pw.format("<Name>My Tracks %s by Google</Name>\n", MyTracksUtils.getMyTracksVersion(context)); pw.format("<Name>My Tracks %s by Google</Name>\n", SystemUtils.getMyTracksVersion(context));
pw.println("<Build>"); pw.println("<Build>");
@@ -246,11 +246,11 @@ public class TcxTrackWriter implements TrackFormatWriter {
// signify that this build is newer than the one associated with the // signify that this build is newer than the one associated with the
// version code given in VersionMajor. // version code given in VersionMajor.
pw.println("<Version>"); pw.println("<Version>");
pw.format("<VersionMajor>%d</VersionMajor>\n", MyTracksUtils.getMyTracksVersion(context)); pw.format("<VersionMajor>%s</VersionMajor>\n", SystemUtils.getMyTracksVersion(context));
pw.format("<VersionMinor>%d</VersionMinor>\n", MyTracksUtils.isRelease(context) ? 0 : 1); pw.format("<VersionMinor>%d</VersionMinor>\n", SystemUtils.isRelease(context) ? 0 : 1);
pw.println("</Version>"); pw.println("</Version>");
pw.format("<Type>%s</Type>\n", MyTracksUtils.isRelease(context) ? TCX_TYPE_RELEASE pw.format("<Type>%s</Type>\n", SystemUtils.isRelease(context) ? TCX_TYPE_RELEASE
: TCX_TYPE_INTERNAL); : TCX_TYPE_INTERNAL);
pw.println("</Build>"); pw.println("</Build>");
pw.format("<LangID>%s</LangID>\n", Locale.getDefault().getLanguage()); pw.format("<LangID>%s</LangID>\n", Locale.getDefault().getLanguage());
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import android.os.Environment; import android.os.Environment;
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
@@ -22,7 +22,7 @@ import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator; import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Activity; import android.app.Activity;
@@ -302,7 +302,7 @@ public class TrackWriter {
while (it.hasNext()) { while (it.hasNext()) {
Location loc = it.next(); Location loc = it.next();
boolean isValid = MyTracksUtils.isValidLocation(loc); boolean isValid = LocationUtils.isValidLocation(loc);
boolean validSegment = isValid && isLastValid; boolean validSegment = isValid && isLastValid;
if (!wroteFirst && validSegment) { if (!wroteFirst && validSegment) {
// Found the first two consecutive points which are valid // Found the first two consecutive points which are valid
@@ -14,7 +14,7 @@
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
@@ -15,9 +15,9 @@
*/ */
package com.google.android.apps.mytracks.io.sendtogoogle; package com.google.android.apps.mytracks.io.sendtogoogle;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.DialogManager; import com.google.android.apps.mytracks.DialogManager;
import com.google.android.apps.mytracks.MyTracks; import com.google.android.apps.mytracks.MyTracks;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Dialog; import android.app.Dialog;
@@ -107,7 +107,7 @@ public class SendDialog extends Dialog {
R.id.sendtogoogle_send_stats_and_points); R.id.sendtogoogle_send_stats_and_points);
SharedPreferences prefs = SharedPreferences prefs =
getContext().getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); getContext().getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (prefs != null) { if (prefs != null) {
sendToMyMapsCheckBox.setChecked( sendToMyMapsCheckBox.setChecked(
prefs.getBoolean( prefs.getBoolean(
@@ -138,7 +138,7 @@ public class SendDialog extends Dialog {
@Override @Override
protected void onStop() { protected void onStop() {
SharedPreferences prefs = SharedPreferences prefs =
getContext().getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); getContext().getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (prefs != null) { if (prefs != null) {
Editor editor = prefs.edit(); Editor editor = prefs.edit();
if (editor != null) { if (editor != null) {
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.services; package com.google.android.apps.mytracks.services;
import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.apps.mytracks.Constants;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.content.Context; import android.content.Context;
@@ -58,7 +58,7 @@ class DefaultTrackNameFactory {
/** Determines whether the preferences allow a timestamp-based track name */ /** Determines whether the preferences allow a timestamp-based track name */
protected boolean useTimestampTrackName() { protected boolean useTimestampTrackName() {
SharedPreferences prefs = SharedPreferences prefs =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
return prefs.getBoolean( return prefs.getBoolean(
context.getString(R.string.timestamp_track_name_key), true); context.getString(R.string.timestamp_track_name_key), true);
} }
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks.services; package com.google.android.apps.mytracks.services;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@@ -45,7 +44,7 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener {
public PreferenceManager(TrackRecordingService service) { public PreferenceManager(TrackRecordingService service) {
this.service = service; this.service = service;
this.sharedPreferences = service.getSharedPreferences( this.sharedPreferences = service.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
if (sharedPreferences == null) { if (sharedPreferences == null) {
Log.w(Constants.TAG, Log.w(Constants.TAG,
"TrackRecordingService: Couldn't get shared preferences."); "TrackRecordingService: Couldn't get shared preferences.");
@@ -97,7 +96,7 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener {
service.setMinRecordingDistance( service.setMinRecordingDistance(
sharedPreferences.getInt( sharedPreferences.getInt(
minRecordingDistanceKey, minRecordingDistanceKey,
MyTracksSettings.DEFAULT_MIN_RECORDING_DISTANCE)); Constants.DEFAULT_MIN_RECORDING_DISTANCE));
Log.d(Constants.TAG, Log.d(Constants.TAG,
"TrackRecordingService: minRecordingDistance = " "TrackRecordingService: minRecordingDistance = "
+ service.getMinRecordingDistance()); + service.getMinRecordingDistance());
@@ -105,12 +104,12 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener {
if (key == null || key.equals(maxRecordingDistanceKey)) { if (key == null || key.equals(maxRecordingDistanceKey)) {
service.setMaxRecordingDistance(sharedPreferences.getInt( service.setMaxRecordingDistance(sharedPreferences.getInt(
maxRecordingDistanceKey, maxRecordingDistanceKey,
MyTracksSettings.DEFAULT_MAX_RECORDING_DISTANCE)); Constants.DEFAULT_MAX_RECORDING_DISTANCE));
} }
if (key == null || key.equals(minRecordingIntervalKey)) { if (key == null || key.equals(minRecordingIntervalKey)) {
int minRecordingInterval = sharedPreferences.getInt( int minRecordingInterval = sharedPreferences.getInt(
minRecordingIntervalKey, minRecordingIntervalKey,
MyTracksSettings.DEFAULT_MIN_RECORDING_INTERVAL); Constants.DEFAULT_MIN_RECORDING_INTERVAL);
switch (minRecordingInterval) { switch (minRecordingInterval) {
case -2: case -2:
// Battery Miser // Battery Miser
@@ -136,7 +135,7 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener {
if (key == null || key.equals(minRequiredAccuracyKey)) { if (key == null || key.equals(minRequiredAccuracyKey)) {
service.setMinRequiredAccuracy(sharedPreferences.getInt( service.setMinRequiredAccuracy(sharedPreferences.getInt(
minRequiredAccuracyKey, minRequiredAccuracyKey,
MyTracksSettings.DEFAULT_MIN_REQUIRED_ACCURACY)); Constants.DEFAULT_MIN_REQUIRED_ACCURACY));
} }
if (key == null || key.equals(announcementFrequencyKey)) { if (key == null || key.equals(announcementFrequencyKey)) {
service.setAnnouncementFrequency( service.setAnnouncementFrequency(
@@ -145,7 +144,7 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener {
if (key == null || key.equals(autoResumeTrackTimeoutKey)) { if (key == null || key.equals(autoResumeTrackTimeoutKey)) {
service.setAutoResumeTrackTimeout(sharedPreferences.getInt( service.setAutoResumeTrackTimeout(sharedPreferences.getInt(
autoResumeTrackTimeoutKey, autoResumeTrackTimeoutKey,
MyTracksSettings.DEFAULT_AUTO_RESUME_TRACK_TIMEOUT)); Constants.DEFAULT_AUTO_RESUME_TRACK_TIMEOUT));
} }
if (key == null || key.equals(recordingTrackKey)) { if (key == null || key.equals(recordingTrackKey)) {
long recordingTrackId = sharedPreferences.getLong(recordingTrackKey, -1); long recordingTrackId = sharedPreferences.getLong(recordingTrackKey, -1);
@@ -20,7 +20,6 @@ import static com.google.android.apps.mytracks.Constants.RESUME_TRACK_EXTRA_NAME
import com.google.android.apps.mytracks.MyTracks; import com.google.android.apps.mytracks.MyTracks;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
@@ -39,7 +38,7 @@ import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder; import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
import com.google.android.apps.mytracks.util.ApiFeatures; import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.ApiPlatformAdapter; import com.google.android.apps.mytracks.util.ApiPlatformAdapter;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -84,13 +83,13 @@ public class TrackRecordingService extends Service implements LocationListener {
private WakeLock wakeLock; private WakeLock wakeLock;
private int minRecordingDistance = private int minRecordingDistance =
MyTracksSettings.DEFAULT_MIN_RECORDING_DISTANCE; Constants.DEFAULT_MIN_RECORDING_DISTANCE;
private int maxRecordingDistance = private int maxRecordingDistance =
MyTracksSettings.DEFAULT_MAX_RECORDING_DISTANCE; Constants.DEFAULT_MAX_RECORDING_DISTANCE;
private int minRequiredAccuracy = private int minRequiredAccuracy =
MyTracksSettings.DEFAULT_MIN_REQUIRED_ACCURACY; Constants.DEFAULT_MIN_REQUIRED_ACCURACY;
private int autoResumeTrackTimeout = private int autoResumeTrackTimeout =
MyTracksSettings.DEFAULT_AUTO_RESUME_TRACK_TIMEOUT; Constants.DEFAULT_AUTO_RESUME_TRACK_TIMEOUT;
private long recordingTrackId = -1; private long recordingTrackId = -1;
@@ -218,7 +217,7 @@ public class TrackRecordingService extends Service implements LocationListener {
// Keep track of length along recorded track (needed when a waypoint is // Keep track of length along recorded track (needed when a waypoint is
// inserted): // inserted):
if (MyTracksUtils.isValidLocation(location)) { if (LocationUtils.isValidLocation(location)) {
if (lastValidLocation != null) { if (lastValidLocation != null) {
length += location.distanceTo(lastValidLocation); length += location.distanceTo(lastValidLocation);
} }
@@ -456,7 +455,7 @@ public class TrackRecordingService extends Service implements LocationListener {
if (cursor.moveToLast()) { if (cursor.moveToLast()) {
do { do {
Location location = providerUtils.createLocation(cursor); Location location = providerUtils.createLocation(cursor);
if (MyTracksUtils.isValidLocation(location)) { if (LocationUtils.isValidLocation(location)) {
statsBuilder.addLocation(location, location.getTime()); statsBuilder.addLocation(location, location.getTime());
if (lastValidLocation != null) { if (lastValidLocation != null) {
length += location.distanceTo(lastValidLocation); length += location.distanceTo(lastValidLocation);
@@ -633,7 +632,7 @@ public class TrackRecordingService extends Service implements LocationListener {
} }
private void addLocationToStats(Location location) { private void addLocationToStats(Location location) {
if (MyTracksUtils.isValidLocation(location)) { if (LocationUtils.isValidLocation(location)) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
statsBuilder.addLocation(location, now); statsBuilder.addLocation(location, now);
waypointStatsBuilder.addLocation(location, now); waypointStatsBuilder.addLocation(location, now);
@@ -841,7 +840,7 @@ public class TrackRecordingService extends Service implements LocationListener {
// Check if we haven't exceeded the maximum number of retry attempts. // Check if we haven't exceeded the maximum number of retry attempts.
SharedPreferences sharedPreferences = SharedPreferences sharedPreferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); getSharedPreferences(Constants.SETTINGS_NAME, 0);
int retries = sharedPreferences.getInt( int retries = sharedPreferences.getInt(
getString(R.string.auto_resume_track_current_retry_key), 0); getString(R.string.auto_resume_track_current_retry_key), 0);
Log.d(TAG, Log.d(TAG,
@@ -1123,7 +1122,7 @@ public class TrackRecordingService extends Service implements LocationListener {
// Reset the number of auto-resume retries. // Reset the number of auto-resume retries.
setAutoResumeTrackRetries( setAutoResumeTrackRetries(
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0), 0); getSharedPreferences(Constants.SETTINGS_NAME, 0), 0);
// Persist the current recording track. // Persist the current recording track.
prefManager.setRecordingTrack(recordingTrackId); prefManager.setRecordingTrack(recordingTrackId);
@@ -16,7 +16,8 @@
package com.google.android.apps.mytracks.services.sensors; package com.google.android.apps.mytracks.services.sensors;
import static com.google.android.apps.mytracks.Constants.TAG; import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.services.sensors.ant.AntChannelIdMessage; import com.google.android.apps.mytracks.services.sensors.ant.AntChannelIdMessage;
import com.google.android.apps.mytracks.services.sensors.ant.AntChannelResponseMessage; import com.google.android.apps.mytracks.services.sensors.ant.AntChannelResponseMessage;
@@ -58,7 +59,7 @@ public class AntDirectSensorManager extends AntSensorManager {
// First read the the device id that we will be pairing with. // First read the the device id that we will be pairing with.
SharedPreferences prefs = context.getSharedPreferences( SharedPreferences prefs = context.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
if (prefs != null) { if (prefs != null) {
deviceNumberHRM = deviceNumberHRM =
(short) prefs.getInt(context.getString(R.string.ant_heart_rate_sensor_id_key), 0); (short) prefs.getInt(context.getString(R.string.ant_heart_rate_sensor_id_key), 0);
@@ -133,7 +134,7 @@ public class AntDirectSensorManager extends AntSensorManager {
Log.i(TAG, "Found device id: " + deviceNumberHRM); Log.i(TAG, "Found device id: " + deviceNumberHRM);
SharedPreferences prefs = context.getSharedPreferences( SharedPreferences prefs = context.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, Context.MODE_PRIVATE); Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
editor.putInt(context.getString(R.string.ant_heart_rate_sensor_id_key), deviceNumberHRM); editor.putInt(context.getString(R.string.ant_heart_rate_sensor_id_key), deviceNumberHRM);
editor.commit(); editor.commit();
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks.services.sensors; package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -71,7 +70,7 @@ public class AntSRMSensorManager extends AntSensorManager {
// First read the the device id that we will be announcing. // First read the the device id that we will be announcing.
SharedPreferences prefs = context.getSharedPreferences( SharedPreferences prefs = context.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
if (prefs != null) { if (prefs != null) {
deviceId = (byte) prefs.getInt( deviceId = (byte) prefs.getInt(
context.getString(R.string.ant_srm_bridge_sensor_id_key), context.getString(R.string.ant_srm_bridge_sensor_id_key),
@@ -133,7 +132,7 @@ public class AntSRMSensorManager extends AntSensorManager {
Log.i(Constants.TAG, "Found device id: " + deviceId); Log.i(Constants.TAG, "Found device id: " + deviceId);
SharedPreferences prefs = context.getSharedPreferences( SharedPreferences prefs = context.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, Context.MODE_PRIVATE); Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
editor.putInt(context.getString(R.string.ant_srm_bridge_sensor_id_key), deviceId); editor.putInt(context.getString(R.string.ant_srm_bridge_sensor_id_key), deviceId);
editor.commit(); editor.commit();
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks.services.sensors; package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -82,7 +81,7 @@ public class BluetoothSensorManager extends SensorManager {
return; return;
} }
SharedPreferences prefs = SharedPreferences prefs =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
String address = String address =
prefs.getString(context.getString(R.string.bluetooth_sensor_key), null); prefs.getString(context.getString(R.string.bluetooth_sensor_key), null);
if (address == null) { if (address == null) {
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks.services.sensors; package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.content.Context; import android.content.Context;
@@ -40,7 +39,7 @@ public class SensorManagerFactory {
*/ */
public static SensorManager getSensorManager(Context context) { public static SensorManager getSensorManager(Context context) {
SharedPreferences prefs = SharedPreferences prefs =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (prefs == null) { if (prefs == null) {
return null; return null;
} }
@@ -19,7 +19,7 @@ package com.google.android.apps.mytracks.stats;
import static com.google.android.apps.mytracks.Constants.TAG; import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.apps.mytracks.SettingsActivity;
import android.location.Location; import android.location.Location;
import android.util.Log; import android.util.Log;
@@ -93,7 +93,7 @@ public class TripStatisticsBuilder {
private long totalLocations = 0; private long totalLocations = 0;
private int minRecordingDistance = private int minRecordingDistance =
MyTracksSettings.DEFAULT_MIN_RECORDING_DISTANCE; Constants.DEFAULT_MIN_RECORDING_DISTANCE;
/** /**
* Creates a new trip starting at the given time. * Creates a new trip starting at the given time.
@@ -16,7 +16,7 @@
package com.google.android.apps.mytracks.util; package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -50,7 +50,7 @@ public class ChartURLGenerator {
public static String getChartUrl(Vector<Double> distances, public static String getChartUrl(Vector<Double> distances,
Vector<Double> elevations, Track track, Context context) { Vector<Double> elevations, Track track, Context context) {
SharedPreferences preferences = SharedPreferences preferences =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
boolean metricUnits = true; boolean metricUnits = true;
if (preferences != null) { if (preferences != null) {
metricUnits = preferences.getBoolean( metricUnits = preferences.getBoolean(
@@ -21,15 +21,7 @@ import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.GeoPoint; import com.google.android.maps.GeoPoint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.location.Location; import android.location.Location;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log; import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
@@ -41,9 +33,7 @@ import java.util.Stack;
* *
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
*/ */
public class MyTracksUtils { public class LocationUtils {
private static final int RELEASE_SIGNATURE_HASHCODE = -1855564782;
/** /**
* Computes the distance on the two sphere between the point c0 and the line * Computes the distance on the two sphere between the point c0 and the line
* segment c1 to c2. * segment c1 to c2.
@@ -117,7 +107,7 @@ public class MyTracksUtils {
current = stack.pop(); current = stack.pop();
maxDist = 0; maxDist = 0;
for (idx = current[0] + 1; idx < current[1]; ++idx) { for (idx = current[0] + 1; idx < current[1]; ++idx) {
dist = MyTracksUtils.distance( dist = LocationUtils.distance(
locations.get(idx), locations.get(idx),
locations.get(current[0]), locations.get(current[0]),
locations.get(current[1])); locations.get(current[1]));
@@ -255,80 +245,9 @@ public class MyTracksUtils {
(int) (location.getLongitude() * 1E6)); (int) (location.getLongitude() * 1E6));
} }
/**
* Returns whether or not this is a release build.
*/
public static boolean isRelease(Context context) {
try {
Signature [] sigs = context.getPackageManager().getPackageInfo(
context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;
for (Signature sig : sigs) {
if (sig.hashCode() == RELEASE_SIGNATURE_HASHCODE) {
return true;
}
}
} catch (NameNotFoundException e) {
Log.e(Constants.TAG, "Unable to get signatures", e);
}
return false;
}
/**
* Get the My Tracks version from the manifest.
*
* @return the version, or an empty string in case of failure.
*/
public static String getMyTracksVersion(Context context) {
try {
PackageInfo pi = context.getPackageManager().getPackageInfo(
"com.google.android.maps.mytracks",
PackageManager.GET_META_DATA);
return pi.versionName;
} catch (NameNotFoundException e) {
Log.w(Constants.TAG, "Failed to get version info.", e);
return "";
}
}
/**
* Tries to acquire a partial wake lock if not already acquired. Logs errors
* and gives up trying in case the wake lock cannot be acquired.
*/
public static WakeLock acquireWakeLock(Activity activity, WakeLock wakeLock) {
Log.i(Constants.TAG, "MyTracksUtils: Acquiring wake lock.");
try {
PowerManager pm = (PowerManager) activity
.getSystemService(Context.POWER_SERVICE);
if (pm == null) {
Log.e(Constants.TAG, "MyTracksUtils: Power manager not found!");
return wakeLock;
}
if (wakeLock == null) {
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
Constants.TAG);
if (wakeLock == null) {
Log.e(Constants.TAG,
"MyTracksUtils: Could not create wake lock (null).");
}
return wakeLock;
}
if (!wakeLock.isHeld()) {
wakeLock.acquire();
if (!wakeLock.isHeld()) {
Log.e(Constants.TAG,
"MyTracksUtils: Could not acquire wake lock.");
}
}
} catch (RuntimeException e) {
Log.e(Constants.TAG,
"MyTracksUtils: Caught unexpected exception: " + e.getMessage(), e);
}
return wakeLock;
}
/** /**
* This is a utility class w/ only static members. * This is a utility class w/ only static members.
*/ */
protected MyTracksUtils() { private LocationUtils() {
} }
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.util; package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.DescriptionGenerator; import com.google.android.apps.mytracks.content.DescriptionGenerator;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
@@ -245,7 +245,7 @@ public class StringUtils implements DescriptionGenerator {
Vector<Double> elevations) { Vector<Double> elevations) {
boolean displaySpeed = true; boolean displaySpeed = true;
SharedPreferences preferences = SharedPreferences preferences =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (preferences != null) { if (preferences != null) {
displaySpeed = displaySpeed =
preferences.getBoolean(context.getString(R.string.report_speed_key), true); preferences.getBoolean(context.getString(R.string.report_speed_key), true);
@@ -0,0 +1,111 @@
/*
* 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.util;
import com.google.android.apps.mytracks.Constants;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
/**
* Utility class for acessing basic Android functionality.
*
* @author Rodrigo Damazio
*/
public class SystemUtils {
private static final int RELEASE_SIGNATURE_HASHCODE = -1855564782;
/**
* Returns whether or not this is a release build.
*/
public static boolean isRelease(Context context) {
try {
Signature [] sigs = context.getPackageManager().getPackageInfo(
context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;
for (Signature sig : sigs) {
if (sig.hashCode() == RELEASE_SIGNATURE_HASHCODE) {
return true;
}
}
} catch (NameNotFoundException e) {
Log.e(Constants.TAG, "Unable to get signatures", e);
}
return false;
}
/**
* Get the My Tracks version from the manifest.
*
* @return the version, or an empty string in case of failure.
*/
public static String getMyTracksVersion(Context context) {
try {
PackageInfo pi = context.getPackageManager().getPackageInfo(
"com.google.android.maps.mytracks",
PackageManager.GET_META_DATA);
return pi.versionName;
} catch (NameNotFoundException e) {
Log.w(Constants.TAG, "Failed to get version info.", e);
return "";
}
}
/**
* Tries to acquire a partial wake lock if not already acquired. Logs errors
* and gives up trying in case the wake lock cannot be acquired.
*/
public static WakeLock acquireWakeLock(Activity activity, WakeLock wakeLock) {
Log.i(Constants.TAG, "LocationUtils: Acquiring wake lock.");
try {
PowerManager pm = (PowerManager) activity
.getSystemService(Context.POWER_SERVICE);
if (pm == null) {
Log.e(Constants.TAG, "LocationUtils: Power manager not found!");
return wakeLock;
}
if (wakeLock == null) {
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
Constants.TAG);
if (wakeLock == null) {
Log.e(Constants.TAG,
"LocationUtils: Could not create wake lock (null).");
}
return wakeLock;
}
if (!wakeLock.isHeld()) {
wakeLock.acquire();
if (!wakeLock.isHeld()) {
Log.e(Constants.TAG,
"LocationUtils: Could not acquire wake lock.");
}
}
} catch (RuntimeException e) {
Log.e(Constants.TAG,
"LocationUtils: Caught unexpected exception: " + e.getMessage(), e);
}
return wakeLock;
}
private SystemUtils() {}
}
@@ -36,8 +36,8 @@ public class MyTracksLocation extends Location {
this.sensorDataSet = sd; this.sensorDataSet = sd;
} }
public MyTracksLocation(String string) { public MyTracksLocation(String provider) {
super(string); super(provider);
} }
public Sensor.SensorDataSet getSensorDataSet() { public Sensor.SensorDataSet getSensorDataSet() {
@@ -315,6 +315,7 @@ public interface MyTracksProviderUtils {
/** /**
* Should be called in case the underlying iterator hasn't reached the last record. * Should be called in case the underlying iterator hasn't reached the last record.
* Calling it if it has reached the last record is a no-op.
*/ */
void close(); void close();
} }
@@ -343,6 +344,24 @@ public interface MyTracksProviderUtils {
} }
}; };
/**
* A location factory which uses two location instances (one for the current location,
* and one for the previous), useful when we need to keep the last location.
*/
public class DoubleBufferedLocationFactory implements LocationFactory {
private final Location locs[] = new MyTracksLocation[] {
new MyTracksLocation("gps"),
new MyTracksLocation("gps")
};
private int lastLoc = 0;
@Override
public Location createLocation() {
lastLoc = (lastLoc + 1) % locs.length;
return locs[lastLoc];
}
}
/** /**
* Creates a new read-only iterator over all track points for the given track. It provides * Creates a new read-only iterator over all track points for the given track. It provides
* a lightweight way of iterating over long tracks without failing due to the underlying cursor * a lightweight way of iterating over long tracks without failing due to the underlying cursor
@@ -39,17 +39,17 @@ import java.util.List;
* *
* @author Bartlomiej Niechwiej * @author Bartlomiej Niechwiej
*/ */
public class MyTracksOverlayTest extends AndroidTestCase { public class MapOverlayTest extends AndroidTestCase {
private Canvas canvas; private Canvas canvas;
private MockMyTracksOverlay myTracksOverlay; private MockMyTracksOverlay myTracksOverlay;
private MapView mockView; private MapView mockView;
private Projection mockProjection; private Projection mockProjection;
/** /**
* A mock version of {@code MyTracksOverlay} that does not use * A mock version of {@code MapOverlay} that does not use
* {@class MapView}. * {@class MapView}.
*/ */
private class MockMyTracksOverlay extends MyTracksOverlay { private class MockMyTracksOverlay extends MapOverlay {
public MockMyTracksOverlay(Context context) { public MockMyTracksOverlay(Context context) {
super(context); super(context);
} }
@@ -1,6 +1,6 @@
// Copyright 2010 Google Inc. All Rights Reserved. // Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
/** /**
* Tests for the CSV track exporter. * Tests for the CSV track exporter.
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import static com.google.android.testing.mocking.AndroidMock.eq; import static com.google.android.testing.mocking.AndroidMock.eq;
import static com.google.android.testing.mocking.AndroidMock.expect; import static com.google.android.testing.mocking.AndroidMock.expect;
@@ -22,6 +22,7 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory; import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
import com.google.android.apps.mytracks.io.file.GpxImporter;
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory; import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
import com.google.android.testing.mocking.AndroidMock; import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks; import com.google.android.testing.mocking.UsesMocks;
@@ -1,5 +1,8 @@
// Copyright 2010 Google Inc. All Rights Reserved. // Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.io.file.GpxTrackWriter;
import com.google.android.apps.mytracks.io.file.TrackFormatWriter;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@@ -1,7 +1,8 @@
// Copyright 2010 Google Inc. All Rights Reserved. // Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.file.KmlTrackWriter;
import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.apps.mytracks.util.StringUtils;
import android.location.Location; import android.location.Location;
@@ -1,8 +1,10 @@
// Copyright 2010 Google Inc. All Rights Reserved. // Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.io.file.TcxTrackWriter;
import com.google.android.apps.mytracks.io.file.TrackFormatWriter;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@@ -13,9 +13,11 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import static com.google.android.testing.mocking.AndroidMock.expect; import static com.google.android.testing.mocking.AndroidMock.expect;
import com.google.android.apps.mytracks.io.file.TempFileCleaner;
import com.google.android.testing.mocking.AndroidMock; import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks; import com.google.android.testing.mocking.UsesMocks;
@@ -1,10 +1,11 @@
// Copyright 2010 Google Inc. All Rights Reserved. // Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.file.TrackFormatWriter;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
@@ -1,6 +1,6 @@
// Copyright 2010 Google Inc. All Rights Reserved. // Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io.file;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
@@ -9,6 +9,8 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory; import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
import com.google.android.apps.mytracks.io.file.TrackFormatWriter;
import com.google.android.apps.mytracks.io.file.TrackWriter;
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext; import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory; import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
@@ -17,7 +17,7 @@ package com.google.android.apps.mytracks.services;
import static com.google.android.apps.mytracks.Constants.RESUME_TRACK_EXTRA_NAME; import static com.google.android.apps.mytracks.Constants.RESUME_TRACK_EXTRA_NAME;
import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.MyTracksProvider; import com.google.android.apps.mytracks.content.MyTracksProvider;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
@@ -152,7 +152,7 @@ public class TrackRecordingServiceTest
providerUtils = MyTracksProviderUtils.Factory.get(context); providerUtils = MyTracksProviderUtils.Factory.get(context);
sharedPreferences = context.getSharedPreferences( sharedPreferences = context.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
// Let's use default values. // Let's use default values.
sharedPreferences.edit().clear().commit(); sharedPreferences.edit().clear().commit();
@@ -16,7 +16,7 @@
package com.google.android.apps.mytracks.services.sensors; package com.google.android.apps.mytracks.services.sensors;
import com.dsi.ant.AntMesg; import com.dsi.ant.AntMesg;
import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -31,7 +31,7 @@ public class AntDirectSensorManagerTest extends AndroidTestCase {
public void setUp() { public void setUp() {
sharedPreferences = getContext().getSharedPreferences( sharedPreferences = getContext().getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
// Let's use default values. // Let's use default values.
sharedPreferences.edit().clear().commit(); sharedPreferences.edit().clear().commit();
manager = new AntDirectSensorManager(getContext()); manager = new AntDirectSensorManager(getContext());
@@ -1,6 +1,6 @@
package com.google.android.apps.mytracks.services.sensors; package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.apps.mytracks.Constants;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@@ -16,7 +16,7 @@ public class SensorManagerFactoryTest extends AndroidTestCase {
super.setUp(); super.setUp();
sharedPreferences = getContext().getSharedPreferences( sharedPreferences = getContext().getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); Constants.SETTINGS_NAME, 0);
// Let's use default values. // Let's use default values.
sharedPreferences.edit().clear().commit(); sharedPreferences.edit().clear().commit();
} }