diff --git a/.hgignore b/.hgignore index 1bbe85f92..3bf9706a8 100644 --- a/.hgignore +++ b/.hgignore @@ -5,4 +5,3 @@ syntax:glob */proguard/** .metadata MyTracksTest/annotations.log -MyTracks/src/com/google/android/apps/mytracks/io/mymaps diff --git a/MyTracks/.classpath b/MyTracks/.classpath index 72de4ae42..636d59be6 100644 --- a/MyTracks/.classpath +++ b/MyTracks/.classpath @@ -8,7 +8,6 @@ - diff --git a/MyTracks/AndroidManifest.xml b/MyTracks/AndroidManifest.xml index d6f558ac4..2a1bbd2d7 100755 --- a/MyTracks/AndroidManifest.xml +++ b/MyTracks/AndroidManifest.xml @@ -17,8 +17,8 @@ limitations under the License. + android:versionCode="26" + android:versionName="1.1.4rc1"> @@ -61,16 +61,16 @@ limitations under the License. android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|fontScale" android:exported="false" /> - - - - Es wurde kein Dienst zur Positionsermittlung auf diesem Gerät gefunden. Es wurde kein GPS-Empfänger auf diesem Gerät gefunden. @@ -45,7 +45,7 @@ limitations under the License. Track existiert nicht. Die Datei ist zu groß (maximal 500 KB). Operation abgebrochen. Der Wegpunkt kann nicht einfügt werden. Keine Positionsbestimmung möglich. - + Warte auf ein besseres GPS-Signal. Bitte stelle sicher, dass der Himmel sichtbar ist. Ein neuer Track wird aufgezeichnet. @@ -59,7 +59,7 @@ limitations under the License. Die Position kann derzeit nicht bestimmt werden. Aktiviere mehr Positionsquellen (siehe Sicherheits- und Positionseinstellungen) und stelle sicher, dass der Himmel sichtbar ist. Ein Wegpunkt wurde eingefügt. Ein Statistikwegpunkt wurde eingefügt. - + Bitte warten… Dein Track wird an Google gesendet... @@ -73,28 +73,28 @@ limitations under the License. Importiere GPS-Track. Das kann ein wenig dauern. Schreibe Datei auf SD-Karte. Das kann ein wenig dauern. Aktualisiere Trackstatistik... - + Bist Du Dir wirklich sicher? Alle Tracks und Wegpunkte werden endgültig von diesem Gerät gelöscht. Dieser Track und seine Wegpunkte werden endgültig von diesem Gerät gelöscht. Dieser Wegpunkt wird endgültig von diesem Gerät gelöscht. - + Erstellt von My Tracks für Android. Erstellt von <a href=\'http://mytracks.appspot.com\'>My Tracks</a> für Android. - + Punkte Aufgezeichnet am Aktivität Art des Wegpunktes (Teil %d) - + Dein Track wird aufgezeichnet… - + Nein Ja @@ -111,7 +111,7 @@ limitations under the License. (Ende) - + Anzeigen An eine Google Fusion Tables-Karte senden @@ -140,7 +140,7 @@ limitations under the License. Eine CSV-Datei Eine TCX-Datei Karte zurücksetzen. - + Alle Wegpunkte löschen Dieser Wegpunkt @@ -150,70 +150,70 @@ limitations under the License. Wegpunkt einfügen Statistik einfügen Wegpunkt auswählen. Lange berühren für mehr Optionen. - + Trackdetails Name Beschreibung Aktivität (z. B. Wandern, Fahrradfahren, Laufen, Klettern…) - + Wegpunktdetails Wegpunktname Wegpunktbeschreibung Art des Wegpunktes (z. B. Gebäude, Schlagloch, Sehenswürdigkeit…) - + Einstellungen für My Tracks Anzeige Aufzeichnung Mit Freunden teilen - + In dieser Android-Version nicht verfügbar - + Dauer zwischen Ansagen Kürzeste Zeit zwischen zwei Ansagen - + Kleinste Entfernung zwischen Punkten Kleinste Entfernung zwischen zwei Positionsaufzeichnungen - + Neues Segment, wenn Punkte weiter entfernt als Der Track wird in zwei geteilt, wenn zwei folgende Punkte weiter entfernt sind als hier angegeben. - + Aufzeichnungsfrequenz Kürzeste Zeit zwischen zwei Positionsaufzeichnungen - + Aufzeichnung pausieren, wenn Genauigkeit kleiner als Die Aufzeichnung wird kurzfristig angehalten, wenn Deine Position nicht genauer als hier angegeben ermittelt werden kann. - + Entfernungen in metrischen Einheiten anzeigen Alle Entfernungen werden in metrischen Einheiten angezeigt. Alle Entfernungen werden in imperialen Längeneinheiten angezeigt. - + Karten auf maps.google.com veröffentlichen Hochgeladene Karten auf maps.google.com sind für alle sichtbar. Hochgeladene Karten auf maps.google.com werden nicht öffentlich sichtbar aufgelistet. - + Geschwindigkeitsanzeige Geschwindigkeit wird angezeigt. Pace wird angezeigt. - + Nur URL als Einladung zum Teilen senden Beim Teilen mit Freunden wird nur die Karten-URL gesendet. Beim Teilen mit Freunden wird der GPS-Track selbst gesendet. - + Zerteilungsfrequenz Längste Dauer oder Entfernung, nach der automatisch ein Marker eingefügt wird. - + Zeitbegrenzung der Auto-Wiederaufnahme Maximale Zeit in Minuten, nach der eine abgebrochene Aufzeichnung nach einem Telefonneustart wiederaufgenommen wird. - + Zeitstempel als Trackname Der Trackname wird aus Datum und Zeit zum Aufzeichnungsbeginn zusammengesetzt. Tracknamen erhalten eine fortlaufende Nummer. - + Pace - + Wird nur unter Android 2.0 oder höher unterstützt Sensortyp Der Typ des zu verbindenden Sensors @@ -225,7 +225,7 @@ limitations under the License. Bluetooth-Sensor Der zu verbindende Bluetoothsensor Art der Datenanzeige - + Datensicherung (BETA) SD-Karten-Sicherung @@ -234,13 +234,13 @@ limitations under the License. Jetzt wiederherstellen Alle Tracks und Einstellungen von der SD-Karte holen. Während ein Track aufgezeichnet wird, kann nicht mit der Datensicherung gearbeitet werden. - + Eine Wiederherstellung von der SD-Karte ÜBERSCHREIBT alle vorhandenen Tracks und Einstellungen. Willst Du das wirklich? Wähle die wiederherzustellende Datensicherung aus Keine Datensicherungen gefunden. Schreibe alle Tracks und Einstellungen auf die SD-Karte. Dies kann eine Weile dauern... Lese alle Tracks und Einstellungen von der SD-Karte. Dies kann eine Weile dauern... - + GPS-Satelliten @@ -248,12 +248,12 @@ limitations under the License. Karte mit Freunden teilen Ich möchte gerne eine Karte mit Dir teilen. Vielleicht interessierst Du Dich für diese Karte: - + %s Ich möchte einen GPS-Track mit Dir teilen Vielleicht interessierst Du Dich für diese Track: - - %s. + + Der Track kann mit Google Earth oder anderer Karten-Software visualisiert werden. Track mit Freunden teilen @@ -265,39 +265,39 @@ limitations under the License. Durchschnitt in Bew. Pace in Bew. - + Durchschnittsgeschw. Durchschnitts-Pace - + Höhenprofil Höhengewinn Höhe Breitengrad Längengrad - + Niedrigste Höhenlage Minimale Steigung Minimaler Pace - + Höchste Höhenlage Maximale Steigung Max. Geschwindigkeit - + Lade Track… - + Diagramm-Einstellungen X-Achse Nach Entfernung Nach Zeit - + Y-Achse - + Stunde @@ -309,7 +309,7 @@ limitations under the License. Sekunde Sekunden - + @@ -317,7 +317,7 @@ limitations under the License. Fuß Meilen - + Kilometer pro Stunde @@ -350,12 +350,12 @@ limitations under the License. Höchste Herzfrequenz Bitte warten… - + Lizenzvereinbarung für Endverbraucher Akzeptieren Ablehnen - + Über Hilfe @@ -363,7 +363,7 @@ limitations under the License. Unterstützung: Datenschutz: - + Senden an… @@ -371,12 +371,12 @@ limitations under the License. Jetzt senden Trackstatistik senden Statistik und Punkte senden - + Kein Konto vorhanden Kein Konto gefunden, um Tracks zu versenden. Wähle ein Konto - + Keine externes Speichermedium verfügbar. Stelle sicher, dass eine SD-Karte vorhanden ist und nicht bereits von einem Computer darauf zugegriffen wird. Die Datei kann nicht geschrieben werden. @@ -384,7 +384,7 @@ limitations under the License. Das Verzeichnis auf der SD-Karte kann nicht erstellt werden. Der Track wurde auf die SD-Karte geschrieben. Lesen von der SD-Karte beendet. - + Suche nach neuer Version Jetzt aktualisieren @@ -392,12 +392,12 @@ limitations under the License. Deine Version von %1$s funktioniert möglicherweise nicht mehr richtig und wird nicht mehr unterstützt. Bitte aktualisiere %1$s. Deine Version von %1$s funktioniert möglicherweise nicht mehr richtig. Du kannst sie jetzt aktualisieren, oder auf sie auf eigene Gefahr weiterverwenden. Einige Funktionen wie Datenaustausch mit Google-Diensten werden möglicherweise nicht mehr funktionieren, solange Du die Software nicht aktualisierst. Eine neue Version von %1$s ist jetzt verfügbar. Du kannst Deine installierte Version ohne Probleme weiterverwenden, aber um die neuesten Funktionen in Anspruch nehmen zu können, musst Du die Software aktualisieren. - + Willkommen OK Über My Tracks - + My Tracks keine Entfernung My Tracks %1$s %2$.2f %3$s in %4$s mit %5$s %6$s - + Einheitenbenachrichtigung Voreingestellt sind metrische Einheiten. Willst Du diese Einstellung ändern? - + Bluetooth Bluetooth-Einstellungen @@ -421,12 +421,12 @@ limitations under the License. Öffnet Androids Bluetooth-Einstellungen, um Geräte zu verbinden. Sensor-Einstellungen - + Verbunden mit %s Verbinde mit Bluetooth-Sensor ... Bluetooth-Sensor nicht verbunden. - + Uhrzeit Kraftmesser aktiviert @@ -439,7 +439,7 @@ limitations under the License. Kein Sensor-Dienst Suche... Sende... - + Track-Aufzeichnungs-Benachrichtigungen empfangen Aufgezeichnete Trackdaten lesen diff --git a/MyTracks/src/com/google/android/apps/mytracks/AccountChooser.java b/MyTracks/src/com/google/android/apps/mytracks/AccountChooser.java index cfd1cda39..7a648a304 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/AccountChooser.java +++ b/MyTracks/src/com/google/android/apps/mytracks/AccountChooser.java @@ -59,7 +59,7 @@ public class AccountChooser { public void chooseAccount(final Activity activity, final AccountHandler handler) { final Account[] accounts = AccountManager.get(activity) - .getAccountsByType(MyTracksConstants.ACCOUNT_TYPE); + .getAccountsByType(Constants.ACCOUNT_TYPE); if (accounts.length < 1) { alertNoAccounts(activity, handler); return; @@ -76,7 +76,7 @@ public class AccountChooser { } // Let the user choose. - Log.e(MyTracksConstants.TAG, "Multiple matching accounts found."); + Log.e(Constants.TAG, "Multiple matching accounts found."); final AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setTitle(R.string.choose_account_title); builder.setCancelable(false); @@ -112,7 +112,7 @@ public class AccountChooser { */ private void alertNoAccounts(final Activity activity, final AccountHandler handler) { - Log.e(MyTracksConstants.TAG, "No matching accounts found."); + Log.e(Constants.TAG, "No matching accounts found."); final AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setTitle(R.string.no_account_found_title); builder.setMessage(R.string.no_account_found); diff --git a/MyTracks/src/com/google/android/apps/mytracks/AggregatedStatsActivity.java b/MyTracks/src/com/google/android/apps/mytracks/AggregatedStatsActivity.java index c4e4e0728..7030b30db 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/AggregatedStatsActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/AggregatedStatsActivity.java @@ -40,7 +40,7 @@ public class AggregatedStatsActivity extends Activity implements @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - Log.d(MyTracksConstants.TAG, "StatsActivity: onSharedPreferences changed " + Log.d(Constants.TAG, "StatsActivity: onSharedPreferences changed " + key); if (key != null) { if (key.equals(R.string.metric_units_key)) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/ChartActivity.java b/MyTracks/src/com/google/android/apps/mytracks/ChartActivity.java index bb8353b4f..e617c0a64 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/ChartActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/ChartActivity.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.ChartView.Mode; import com.google.android.apps.mytracks.content.MyTracksLocation; @@ -55,9 +55,9 @@ import java.util.ArrayList; public class ChartActivity extends Activity implements TrackDataListener { private final DoubleBuffer elevationBuffer = - new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); + new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR); private final DoubleBuffer speedBuffer = - new DoubleBuffer(MyTracksConstants.SPEED_SMOOTHING_FACTOR); + new DoubleBuffer(Constants.SPEED_SMOOTHING_FACTOR); private final ArrayList pendingPoints = new ArrayList(); private TrackDataHub dataHub; @@ -186,7 +186,7 @@ public class ChartActivity extends Activity implements TrackDataListener { public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); chartSettingsMenuItem = - menu.add(0, MyTracksConstants.MENU_CHART_SETTINGS, 0, + menu.add(0, Constants.MENU_CHART_SETTINGS, 0, R.string.chart_settings); chartSettingsMenuItem.setIcon(R.drawable.chart_settings); return true; @@ -195,7 +195,7 @@ public class ChartActivity extends Activity implements TrackDataListener { @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case MyTracksConstants.MENU_CHART_SETTINGS: + case Constants.MENU_CHART_SETTINGS: MyTracks.getInstance().getDialogManager().showDialogSafely( DialogManager.DIALOG_CHART_SETTINGS); return true; diff --git a/MyTracks/src/com/google/android/apps/mytracks/ChartView.java b/MyTracks/src/com/google/android/apps/mytracks/ChartView.java index 753a4a753..a3153d014 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/ChartView.java +++ b/MyTracks/src/com/google/android/apps/mytracks/ChartView.java @@ -527,7 +527,7 @@ public class ChartView extends View { } if (nearestWaypoint != null && dmin < 100) { Intent intent = - new Intent(getContext(), MyTracksWaypointDetails.class); + new Intent(getContext(), WaypointDetails.class); intent.putExtra("waypointid", nearestWaypoint.getId()); getContext().startActivity(intent); return true; diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksConstants.java b/MyTracks/src/com/google/android/apps/mytracks/Constants.java similarity index 82% rename from MyTracks/src/com/google/android/apps/mytracks/MyTracksConstants.java rename to MyTracks/src/com/google/android/apps/mytracks/Constants.java index 56d197bfa..35963cfc0 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksConstants.java +++ b/MyTracks/src/com/google/android/apps/mytracks/Constants.java @@ -20,7 +20,7 @@ package com.google.android.apps.mytracks; * * @author Leif Hendrik Wilden */ -public abstract class MyTracksConstants { +public abstract class Constants { /** * Should be used by all log statements @@ -188,32 +188,32 @@ public abstract class MyTracksConstants { public static int getActionFromMenuId(int menuId) { switch (menuId) { - case MyTracksConstants.MENU_SEND_TO_GOOGLE: - return MyTracksConstants.SEND_TO_GOOGLE_DIALOG; - case MyTracksConstants.MENU_EDIT: - return MyTracksConstants.EDIT_DETAILS; - case MyTracksConstants.MENU_DELETE: - return MyTracksConstants.DELETE_TRACK; - case MyTracksConstants.MENU_SHARE_LINK: - return MyTracksConstants.SHARE_LINK; - case MyTracksConstants.MENU_SHARE_KML_FILE: - return MyTracksConstants.SHARE_KML_FILE; - case MyTracksConstants.MENU_SHARE_GPX_FILE: - return MyTracksConstants.SHARE_GPX_FILE; - case MyTracksConstants.MENU_SHARE_CSV_FILE: - return MyTracksConstants.SHARE_CSV_FILE; - case MyTracksConstants.MENU_SHARE_TCX_FILE: - return MyTracksConstants.SHARE_TCX_FILE; - case MyTracksConstants.MENU_SAVE_GPX_FILE: - return MyTracksConstants.SAVE_GPX_FILE; - case MyTracksConstants.MENU_SAVE_KML_FILE: - return MyTracksConstants.SAVE_KML_FILE; - case MyTracksConstants.MENU_SAVE_CSV_FILE: - return MyTracksConstants.SAVE_CSV_FILE; - case MyTracksConstants.MENU_SAVE_TCX_FILE: - return MyTracksConstants.SAVE_TCX_FILE; - case MyTracksConstants.MENU_CLEAR_MAP: - return MyTracksConstants.CLEAR_MAP; + case Constants.MENU_SEND_TO_GOOGLE: + return Constants.SEND_TO_GOOGLE_DIALOG; + case Constants.MENU_EDIT: + return Constants.EDIT_DETAILS; + case Constants.MENU_DELETE: + return Constants.DELETE_TRACK; + case Constants.MENU_SHARE_LINK: + return Constants.SHARE_LINK; + case Constants.MENU_SHARE_KML_FILE: + return Constants.SHARE_KML_FILE; + case Constants.MENU_SHARE_GPX_FILE: + return Constants.SHARE_GPX_FILE; + case Constants.MENU_SHARE_CSV_FILE: + return Constants.SHARE_CSV_FILE; + case Constants.MENU_SHARE_TCX_FILE: + return Constants.SHARE_TCX_FILE; + case Constants.MENU_SAVE_GPX_FILE: + return Constants.SAVE_GPX_FILE; + case Constants.MENU_SAVE_KML_FILE: + return Constants.SAVE_KML_FILE; + case Constants.MENU_SAVE_CSV_FILE: + return Constants.SAVE_CSV_FILE; + case Constants.MENU_SAVE_TCX_FILE: + return Constants.SAVE_TCX_FILE; + case Constants.MENU_CLEAR_MAP: + return Constants.CLEAR_MAP; default: return -1; } @@ -225,5 +225,5 @@ public abstract class MyTracksConstants { /** * This is an abstract utility class. */ - protected MyTracksConstants() { } + protected Constants() { } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksDeleteAllTracks.java b/MyTracks/src/com/google/android/apps/mytracks/DeleteAllTracks.java similarity index 94% rename from MyTracks/src/com/google/android/apps/mytracks/MyTracksDeleteAllTracks.java rename to MyTracks/src/com/google/android/apps/mytracks/DeleteAllTracks.java index ff0a94ae4..6bc980766 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksDeleteAllTracks.java +++ b/MyTracks/src/com/google/android/apps/mytracks/DeleteAllTracks.java @@ -34,12 +34,12 @@ import android.util.Log; * * @author Leif Hendrik Wilden */ -public class MyTracksDeleteAllTracks extends Handler { +public class DeleteAllTracks extends Handler { private final Context context; private final Runnable done; - public MyTracksDeleteAllTracks(Context context, Runnable done) { + public DeleteAllTracks(Context context, Runnable done) { this.context = context; this.done = done; } @@ -58,7 +58,7 @@ public class MyTracksDeleteAllTracks extends Handler { new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int i) { dialog.dismiss(); - Log.w(MyTracksConstants.TAG, "deleting all!"); + Log.w(Constants.TAG, "deleting all!"); MyTracksProviderUtils.Factory.get(context).deleteAllTracks(); SharedPreferences prefs = context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); diff --git a/MyTracks/src/com/google/android/apps/mytracks/DialogManager.java b/MyTracks/src/com/google/android/apps/mytracks/DialogManager.java index 5dec3e5dd..57c107a97 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/DialogManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/DialogManager.java @@ -15,6 +15,8 @@ */ package com.google.android.apps.mytracks; +import static com.google.android.apps.mytracks.Constants.TAG; + import com.google.android.apps.mytracks.io.sendtogoogle.SendDialog; import com.google.android.maps.mytracks.R; @@ -96,7 +98,7 @@ public class DialogManager { activity.resetSendToGoogleStatus(); break; case DIALOG_CHART_SETTINGS: - Log.d(MyTracksConstants.TAG, "MyTracks.onPrepare chart dialog"); + Log.d(TAG, "MyTracks.onPrepare chart dialog"); chartSettingsDialog.setup(activity.getChartActivity()); break; } @@ -170,11 +172,9 @@ public class DialogManager { try { activity.showDialog(id); } catch (BadTokenException e) { - Log.w(MyTracksConstants.TAG, - "Could not display dialog with id " + id, e); + Log.w(TAG, "Could not display dialog with id " + id, e); } catch (IllegalStateException e) { - Log.w(MyTracksConstants.TAG, - "Could not display dialog with id " + id, e); + Log.w(TAG, "Could not display dialog with id " + id, e); } } }); @@ -190,9 +190,9 @@ public class DialogManager { try { dialog.show(); } catch (BadTokenException e) { - Log.w(MyTracksConstants.TAG, "Could not display dialog", e); + Log.w(TAG, "Could not display dialog", e); } catch (IllegalStateException e) { - Log.w(MyTracksConstants.TAG, "Could not display dialog", e); + Log.w(TAG, "Could not display dialog", e); } } }); diff --git a/MyTracks/src/com/google/android/apps/mytracks/Eula.java b/MyTracks/src/com/google/android/apps/mytracks/Eula.java index aed5a40a0..c54926795 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/Eula.java +++ b/MyTracks/src/com/google/android/apps/mytracks/Eula.java @@ -98,7 +98,7 @@ class Eula { ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges( preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true)); Intent startIntent = new Intent(activity, WelcomeActivity.class); - activity.startActivityForResult(startIntent, MyTracksConstants.WELCOME); + activity.startActivityForResult(startIntent, Constants.WELCOME); } private static void refuse(Activity activity) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java b/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java index 86c5bc9cf..349c1cd67 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java +++ b/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java @@ -71,14 +71,14 @@ public class ExportAllTracks { format = TrackFileFormat.TCX; break; default: - Log.w(MyTracksConstants.TAG, "Unknown export format: " + which); + Log.w(Constants.TAG, "Unknown export format: " + which); } } }; public ExportAllTracks(Activity activity) { this.activity = activity; - Log.i(MyTracksConstants.TAG, "ExportAllTracks: Starting"); + Log.i(Constants.TAG, "ExportAllTracks: Starting"); AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setSingleChoiceItems(R.array.export_formats, 0, itemClick); @@ -130,9 +130,9 @@ public class ExportAllTracks { // TODO check what happens if we started recording after getting this lock. if (wakeLock != null && wakeLock.isHeld()) { wakeLock.release(); - Log.i(MyTracksConstants.TAG, "ExportAllTracks: Releasing wake lock."); + Log.i(Constants.TAG, "ExportAllTracks: Releasing wake lock."); } - Log.i(MyTracksConstants.TAG, "ExportAllTracks: Done"); + Log.i(Constants.TAG, "ExportAllTracks: Done"); Toast.makeText(activity, R.string.export_done, Toast.LENGTH_SHORT).show(); } @@ -163,7 +163,7 @@ public class ExportAllTracks { } final int trackCount = cursor.getCount(); - Log.i(MyTracksConstants.TAG, + Log.i(Constants.TAG, "ExportAllTracks: Exporting: " + cursor.getCount() + " tracks."); int idxTrackId = cursor.getColumnIndexOrThrow(TracksColumns._ID); activity.runOnUiThread(new Runnable() { @@ -186,7 +186,7 @@ public class ExportAllTracks { }); long id = cursor.getLong(idxTrackId); - Log.i(MyTracksConstants.TAG, "ExportAllTracks: exporting: " + id); + Log.i(Constants.TAG, "ExportAllTracks: exporting: " + id); TrackWriter writer = TrackWriterFactory.newWriter(activity, providerUtils, id, format); writer.writeTrack(); diff --git a/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java b/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java index 799a91d5a..64d5799bb 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java +++ b/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java @@ -60,7 +60,7 @@ public class ImportAllTracks { public ImportAllTracks(Activity activity) { this.activity = activity; - Log.i(MyTracksConstants.TAG, "ImportAllTracks: Starting"); + Log.i(Constants.TAG, "ImportAllTracks: Starting"); fileUtils = new FileUtils(); gpxPath = fileUtils.buildExternalDirectoryPath("gpx"); HandlerThread handlerThread; @@ -98,10 +98,10 @@ public class ImportAllTracks { // TODO check what happens if we started recording after getting this lock. if (wakeLock != null && wakeLock.isHeld()) { wakeLock.release(); - Log.i(MyTracksConstants.TAG, "ImportAllTracks: Releasing wake lock."); + Log.i(Constants.TAG, "ImportAllTracks: Releasing wake lock."); } - Log.i(MyTracksConstants.TAG, "ImportAllTracks: Done"); + Log.i(Constants.TAG, "ImportAllTracks: Done"); AlertDialog.Builder builder = new AlertDialog.Builder(activity); if (gpxFileCount == 0) { builder.setMessage(activity.getString(R.string.import_empty, gpxPath + "/")); @@ -141,7 +141,7 @@ public class ImportAllTracks { return; } - Log.i(MyTracksConstants.TAG, "ImportAllTracks: Importing: " + gpxFileCount + " tracks."); + Log.i(Constants.TAG, "ImportAllTracks: Importing: " + gpxFileCount + " tracks."); activity.runOnUiThread(new Runnable() { public void run() { makeProgressDialog(gpxFileCount); @@ -180,19 +180,19 @@ public class ImportAllTracks { * notifications and returns false on failure. */ private boolean importFile(File gpxFile, MyTracksProviderUtils providerUtils) { - Log.i(MyTracksConstants.TAG, "ImportAllTracks: importing: " + gpxFile.getName()); + Log.i(Constants.TAG, "ImportAllTracks: importing: " + gpxFile.getName()); try { GpxImporter.importGPXFile(new FileInputStream(gpxFile), providerUtils); return true; } catch (FileNotFoundException e) { - Log.w(MyTracksConstants.TAG, "GPX file wasn't found/went missing: " + Log.w(Constants.TAG, "GPX file wasn't found/went missing: " + gpxFile.getAbsolutePath(), e); } catch (ParserConfigurationException e) { - Log.w(MyTracksConstants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e); + Log.w(Constants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e); } catch (SAXException e) { - Log.w(MyTracksConstants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e); + Log.w(Constants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e); } catch (IOException e) { - Log.w(MyTracksConstants.TAG, "Error reading file: " + gpxFile.getAbsolutePath(), e); + Log.w(Constants.TAG, "Error reading file: " + gpxFile.getAbsolutePath(), e); } Toast.makeText(activity, activity.getString(R.string.import_error, gpxFile.getName()), Toast.LENGTH_LONG).show(); diff --git a/MyTracks/src/com/google/android/apps/mytracks/MenuManager.java b/MyTracks/src/com/google/android/apps/mytracks/MenuManager.java index 5d9812535..6bb09842e 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MenuManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MenuManager.java @@ -64,14 +64,14 @@ class MenuManager { return true; } case R.id.menu_list_tracks: { - activity.startActivityForResult(new Intent(activity, MyTracksList.class), - MyTracksConstants.SHOW_TRACK); + activity.startActivityForResult(new Intent(activity, TrackList.class), + Constants.SHOW_TRACK); return true; } case R.id.menu_list_markers: { - Intent startIntent = new Intent(activity, MyTracksWaypointsList.class); + Intent startIntent = new Intent(activity, WaypointsList.class); startIntent.putExtra("trackid", activity.getSelectedTrackId()); - activity.startActivityForResult(startIntent, MyTracksConstants.SHOW_WAYPOINT); + activity.startActivityForResult(startIntent, Constants.SHOW_WAYPOINT); return true; } case R.id.menu_sensor_state: { @@ -86,7 +86,7 @@ class MenuManager { case R.id.menu_help: { return startActivity(WelcomeActivity.class); } - case MyTracksConstants.MENU_CLEAR_MAP: { + case Constants.MENU_CLEAR_MAP: { activity.clearSelectedTrack(); return true; } diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyMapsList.java b/MyTracks/src/com/google/android/apps/mytracks/MyMapsList.java index 949c90026..7b74ac606 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyMapsList.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MyMapsList.java @@ -18,9 +18,8 @@ package com.google.android.apps.mytracks; import com.google.android.accounts.Account; import com.google.android.apps.mytracks.io.AuthManager; import com.google.android.apps.mytracks.io.AuthManagerFactory; -import com.google.android.apps.mytracks.io.MyMapsFactory; import com.google.android.apps.mytracks.io.mymaps.MapsFacade; -import com.google.android.apps.mytracks.io.mymaps.MapsService; +import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants; import com.google.android.maps.mytracks.R; import android.app.Activity; @@ -84,7 +83,7 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback super.onCreate(icicle); auth = AuthManagerFactory.getAuthManager(this, GET_LOGIN, null, true, - MapsService.getServiceName()); + MyMapsConstants.SERVICE_NAME); setContentView(R.layout.list); @@ -125,7 +124,7 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback auth.doLogin(new Runnable() { public void run() { // Runs in UI thread. - mapsClient = MyMapsFactory.newMapsClient(MyMapsList.this, auth); + mapsClient = new MapsFacade(MyMapsList.this, auth); startLookup(); } @@ -200,7 +199,7 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback shareIntent.putExtra(Intent.EXTRA_TEXT, String.format( getText(R.string.share_map_body_format).toString(), listItem[1], - MapsService.buildMapUrl(listItem[0]))); + MapsFacade.buildMapUrl(listItem[0]))); startActivity(Intent.createChooser(shareIntent, getText(R.string.share_map).toString())); return true; diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java b/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java index afcd37996..4c6e9b31e 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java @@ -15,6 +15,7 @@ */ package com.google.android.apps.mytracks; +import static com.google.android.apps.mytracks.Constants.TAG; import static com.google.android.apps.mytracks.DialogManager.DIALOG_IMPORT_PROGRESS; import static com.google.android.apps.mytracks.DialogManager.DIALOG_PROGRESS; import static com.google.android.apps.mytracks.DialogManager.DIALOG_SEND_TO_GOOGLE; @@ -35,7 +36,8 @@ import com.google.android.apps.mytracks.io.TempFileCleaner; import com.google.android.apps.mytracks.io.TrackWriter; import com.google.android.apps.mytracks.io.TrackWriterFactory; import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat; -import com.google.android.apps.mytracks.io.mymaps.MapsService; +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.sendtogoogle.ResultDialogFactory; import com.google.android.apps.mytracks.io.sendtogoogle.SendDialog; import com.google.android.apps.mytracks.io.sendtogoogle.SendResult; @@ -163,7 +165,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, private final ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { - Log.d(MyTracksConstants.TAG, "MyTracks: Service now connected."); + Log.d(Constants.TAG, "MyTracks: Service now connected."); // Delay setting the service until we are done with initialization. ITrackRecordingService trackRecordingService = ITrackRecordingService.Stub.asInterface(service); @@ -181,7 +183,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, @Override public void onServiceDisconnected(ComponentName className) { - Log.d(MyTracksConstants.TAG, "MyTracks: Service now disconnected."); + Log.d(TAG, "MyTracks: Service now disconnected."); trackRecordingService = null; } }; @@ -226,7 +228,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, // TODO: We catch Exception, because after eliminating the service process // all exceptions it may throw are no longer wrapped in a RemoteException. } catch (Exception e) { - Log.e(MyTracksConstants.TAG, "MyTracks: Remote exception.", e); + Log.e(TAG, "MyTracks: Remote exception.", e); // Fall back to alternative check method. return dataHub.isRecording(); @@ -240,7 +242,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, @Override protected void onCreate(Bundle savedInstanceState) { - Log.d(MyTracksConstants.TAG, "MyTracks.onCreate"); + Log.d(TAG, "MyTracks.onCreate"); super.onCreate(savedInstanceState); instance = this; ApiFeatures apiFeatures = ApiFeatures.getInstance(); @@ -303,34 +305,32 @@ public class MyTracks extends TabActivity implements OnTouchListener, // Do nothing. } else if (action.equals(Intent.ACTION_VIEW)) { if (intent.getScheme() != null && intent.getScheme().equals("file")) { - Log.w(MyTracksConstants.TAG, - "Received a VIEW intent with file scheme. Importing."); + Log.w(TAG, "Received a VIEW intent with file scheme. Importing."); importGpxFile(intent.getData().getPath()); } else { - Log.w(MyTracksConstants.TAG, - "Received a VIEW intent with unsupported scheme " - + intent.getScheme()); + Log.w(TAG, "Received a VIEW intent with unsupported scheme " + intent.getScheme()); } } else { - Log.w(MyTracksConstants.TAG, - "Received an intent with unsupported action " + action); + Log.w(TAG, "Received an intent with unsupported action " + action); } } else { - Log.d(MyTracksConstants.TAG, "Received an intent with no action."); + Log.d(TAG, "Received an intent with no action."); } } @Override protected void onDestroy() { - Log.d(MyTracksConstants.TAG, "MyTracks.onDestroy"); + Log.d(TAG, "MyTracks.onDestroy"); + dataHub.destroy(); + tryUnbindTrackRecordingService(); super.onDestroy(); } @Override protected void onStop() { - Log.d(MyTracksConstants.TAG, "MyTracks.onStop"); + Log.d(TAG, "MyTracks.onStop"); dataHub.stop(); @@ -343,7 +343,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, protected void onPause() { // Called when activity is going into the background, but has not (yet) been // killed. Shouldn't block longer than approx. 2 seconds. - Log.d(MyTracksConstants.TAG, "MyTracks.onPause"); + Log.d(TAG, "MyTracks.onPause"); tryUnbindTrackRecordingService(); super.onPause(); } @@ -352,14 +352,14 @@ public class MyTracks extends TabActivity implements OnTouchListener, protected void onResume() { // Called when the current activity is being displayed or re-displayed // to the user. - Log.d(MyTracksConstants.TAG, "MyTracks.onResume"); + Log.d(TAG, "MyTracks.onResume"); tryBindTrackRecordingService(); super.onResume(); } @Override protected void onStart() { - Log.d(MyTracksConstants.TAG, "MyTracks.onStart"); + Log.d(TAG, "MyTracks.onStart"); super.onStart(); dataHub.start(); } @@ -422,9 +422,9 @@ public class MyTracks extends TabActivity implements OnTouchListener, try { insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS); } catch (RemoteException e) { - Log.e(MyTracksConstants.TAG, "Cannot insert statistics marker.", e); + Log.e(TAG, "Cannot insert statistics marker.", e); } catch (IllegalStateException e) { - Log.e(MyTracksConstants.TAG, "Cannot insert statistics marker.", e); + Log.e(TAG, "Cannot insert statistics marker.", e); } return true; } @@ -437,13 +437,13 @@ public class MyTracks extends TabActivity implements OnTouchListener, final Intent results) { TrackFileFormat exportFormat = null; switch (requestCode) { - case MyTracksConstants.GET_LOGIN: { + case Constants.GET_LOGIN: { if (resultCode != RESULT_OK || auth == null || !auth.authResult(resultCode, results)) { dialogManager.dismissDialogSafely(DIALOG_PROGRESS); } break; } - case MyTracksConstants.SHOW_TRACK: { + case Constants.SHOW_TRACK: { if (results != null) { final long trackId = results.getLongExtra("trackid", -1); if (trackId >= 0) { @@ -451,14 +451,14 @@ public class MyTracks extends TabActivity implements OnTouchListener, // The track list passed the requested action as result code. Hand // it off to the onAcitivtyResult for further processing: - if (resultCode != MyTracksConstants.SHOW_TRACK) { + if (resultCode != Constants.SHOW_TRACK) { onActivityResult(resultCode, Activity.RESULT_OK, results); } } } break; } - case MyTracksConstants.SHOW_WAYPOINT: { + case Constants.SHOW_WAYPOINT: { if (results != null) { final long waypointId = results.getLongExtra("waypointid", -1); if (waypointId >= 0) { @@ -472,28 +472,28 @@ public class MyTracks extends TabActivity implements OnTouchListener, } break; } - case MyTracksConstants.DELETE_TRACK: { + case Constants.DELETE_TRACK: { if (results != null && resultCode == RESULT_OK) { final long trackId = results.getLongExtra("trackid", dataHub.getSelectedTrackId()); deleteTrack(trackId); } break; } - case MyTracksConstants.EDIT_DETAILS: { + case Constants.EDIT_DETAILS: { if (results != null && resultCode == RESULT_OK) { final long trackId = results.getLongExtra("trackid", dataHub.getSelectedTrackId()); - Intent intent = new Intent(this, MyTracksDetails.class); + Intent intent = new Intent(this, TrackDetails.class); intent.putExtra("trackid", trackId); startActivity(intent); } break; } - case MyTracksConstants.SEND_TO_GOOGLE_DIALOG: { + case Constants.SEND_TO_GOOGLE_DIALOG: { shareRequested = false; dialogManager.showDialogSafely(DIALOG_SEND_TO_GOOGLE); break; } - case MyTracksConstants.GET_MAP: { + case Constants.GET_MAP: { // User picked a map to upload to if (resultCode == RESULT_OK) { results.putExtra("trackid", dataHub.getSelectedTrackId()); @@ -506,7 +506,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, } break; } - case MyTracksConstants.AUTHENTICATE_TO_MY_MAPS: { + case Constants.AUTHENTICATE_TO_MY_MAPS: { // Authenticated with Google My Maps if (results != null && resultCode == RESULT_OK) { final String mapId; @@ -528,7 +528,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, } break; } - case MyTracksConstants.AUTHENTICATE_TO_FUSION_TABLES: { + case Constants.AUTHENTICATE_TO_FUSION_TABLES: { // Authenticated with Google Fusion Tables if (results != null && resultCode == RESULT_OK) { final long trackId; @@ -544,7 +544,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, } break; } - case MyTracksConstants.AUTHENTICATE_TO_DOCLIST: { + case Constants.AUTHENTICATE_TO_DOCLIST: { // Authenticated with Google Docs if (resultCode == RESULT_OK) { authenticateToGoogleTrix(); @@ -553,7 +553,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, } break; } - case MyTracksConstants.AUTHENTICATE_TO_TRIX: { + case Constants.AUTHENTICATE_TO_TRIX: { // Authenticated with Trix if (resultCode == RESULT_OK) { final long trackId = results.getLongExtra("trackid", dataHub.getSelectedTrackId()); @@ -563,16 +563,16 @@ public class MyTracks extends TabActivity implements OnTouchListener, } break; } - case MyTracksConstants.SAVE_GPX_FILE: + case Constants.SAVE_GPX_FILE: if (exportFormat == null) { exportFormat = TrackFileFormat.GPX; } //$FALL-THROUGH$ - case MyTracksConstants.SAVE_KML_FILE: + case Constants.SAVE_KML_FILE: if (exportFormat == null) { exportFormat = TrackFileFormat.KML; } //$FALL-THROUGH$ - case MyTracksConstants.SAVE_CSV_FILE: + case Constants.SAVE_CSV_FILE: if (exportFormat == null) { exportFormat = TrackFileFormat.CSV; } //$FALL-THROUGH$ - case MyTracksConstants.SAVE_TCX_FILE: + case Constants.SAVE_TCX_FILE: if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; } if (results != null && resultCode == Activity.RESULT_OK) { @@ -582,11 +582,11 @@ public class MyTracks extends TabActivity implements OnTouchListener, } } break; - case MyTracksConstants.SHARE_LINK: { + case Constants.SHARE_LINK: { Track selectedTrack = providerUtils.getTrack(dataHub.getSelectedTrackId()); if (selectedTrack != null) { if (!TextUtils.isEmpty(selectedTrack.getMapId())) { - shareLinkToMap(MapsService.buildMapUrl(selectedTrack.getMapId())); + shareLinkToMap(MapsFacade.buildMapUrl(selectedTrack.getMapId())); } else if (!TextUtils.isEmpty(selectedTrack.getTableId())) { shareLinkToMap(getFusionTablesUrl(dataHub.getSelectedTrackId())); } else { @@ -596,16 +596,16 @@ public class MyTracks extends TabActivity implements OnTouchListener, } break; } - case MyTracksConstants.SHARE_GPX_FILE: + case Constants.SHARE_GPX_FILE: if (exportFormat == null) { exportFormat = TrackFileFormat.GPX; } //$FALL-THROUGH$ - case MyTracksConstants.SHARE_KML_FILE: + case Constants.SHARE_KML_FILE: if (exportFormat == null) { exportFormat = TrackFileFormat.KML; } //$FALL-THROUGH$ - case MyTracksConstants.SHARE_CSV_FILE: + case Constants.SHARE_CSV_FILE: if (exportFormat == null) { exportFormat = TrackFileFormat.CSV; } //$FALL-THROUGH$ - case MyTracksConstants.SHARE_TCX_FILE: { + case Constants.SHARE_TCX_FILE: { if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; } if (results != null && resultCode == Activity.RESULT_OK) { @@ -616,18 +616,17 @@ public class MyTracks extends TabActivity implements OnTouchListener, } break; } - case MyTracksConstants.CLEAR_MAP: { + case Constants.CLEAR_MAP: { dataHub.unloadCurrentTrack(); break; } - case MyTracksConstants.WELCOME: { + case Constants.WELCOME: { CheckUnits.check(this); break; } default: { - Log.w(MyTracksConstants.TAG, - "Warning unhandled request code: " + requestCode); + Log.w(TAG, "Warning unhandled request code: " + requestCode); } } } @@ -668,19 +667,19 @@ public class MyTracks extends TabActivity implements OnTouchListener, InputStream is = new FileInputStream(fileName); trackIdsImported = GpxImporter.importGPXFile(is, providerUtils); } catch (SAXException e) { - Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); + Log.e(TAG, "Caught an unexpected exception.", e); message = R.string.error_generic; } catch (ParserConfigurationException e) { - Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); + Log.e(TAG, "Caught an unexpected exception.", e); message = R.string.error_generic; } catch (IOException e) { - Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); + Log.e(TAG, "Caught an unexpected exception.", e); message = R.string.error_unable_to_read_file; } catch (NullPointerException e) { - Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); + Log.e(TAG, "Caught an unexpected exception.", e); message = R.string.error_invalid_gpx_format; } catch (OutOfMemoryError e) { - Log.e(MyTracksConstants.TAG, "Caught an unexpected exception.", e); + Log.e(TAG, "Caught an unexpected exception.", e); message = R.string.error_out_of_memory; } if (trackIdsImported != null && trackIdsImported.length > 0) { @@ -803,16 +802,15 @@ public class MyTracks extends TabActivity implements OnTouchListener, final String service) { auth = authMap.get(service); if (auth == null) { - Log.i(MyTracksConstants.TAG, - "Creating a new authentication for service: " + service); + Log.i(TAG, "Creating a new authentication for service: " + service); auth = AuthManagerFactory.getAuthManager(this, - MyTracksConstants.GET_LOGIN, + Constants.GET_LOGIN, null, true, service); authMap.put(service, auth); } - Log.d(MyTracksConstants.TAG, "Logging in to " + service + "..."); + Log.d(TAG, "Logging in to " + service + "..."); if (AuthManagerFactory.useModernAuthManager()) { runOnUiThread(new Runnable() { @Override @@ -839,7 +837,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, final String service, final Account account) { auth.doLogin(new Runnable() { public void run() { - Log.d(MyTracksConstants.TAG, "Loggin success for " + service + "!"); + Log.d(TAG, "Loggin success for " + service + "!"); onActivityResult(requestCode, RESULT_OK, results); } }, account); @@ -859,7 +857,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, Toast.makeText(this, getString(R.string.error_unable_to_start_recording), Toast.LENGTH_SHORT).show(); - Log.w(MyTracksConstants.TAG, "Unable to start recording.", e); + Log.w(TAG, "Unable to start recording.", e); } } @@ -891,11 +889,11 @@ public class MyTracks extends TabActivity implements OnTouchListener, // TODO: We catch Exception, because after eliminating the service process // all exceptions it may throw are no longer wrapped in a RemoteException. } catch (Exception e) { - Log.e(MyTracksConstants.TAG, "Unable to stop recording.", e); + Log.e(TAG, "Unable to stop recording.", e); } if (currentTrackId > 0) { - Intent intent = new Intent(MyTracks.this, MyTracksDetails.class); + Intent intent = new Intent(MyTracks.this, TrackDetails.class); intent.putExtra("trackid", currentTrackId); intent.putExtra("hasCancelButton", false); startActivity(intent); @@ -905,8 +903,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, try { stopService(new Intent(MyTracks.this, TrackRecordingService.class)); } catch (SecurityException e) { - Log.e(MyTracksConstants.TAG, - "Encountered a security exception when trying to stop service.", e); + Log.e(TAG, "Encountered a security exception when trying to stop service.", e); } trackRecordingService = null; } @@ -915,7 +912,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, * Initiates the process to send tracks to google. * This is called once the user has selected sending options via the * SendToGoogleDialog. - * + * * TODO: Change this whole flow to an actual state machine. */ public void sendToGoogle() { @@ -935,7 +932,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, } else if (sendToGoogleDialog.getSendToDocs()) { authenticateToGoogleDocs(); } else { - Log.w(MyTracksConstants.TAG, "Nowhere to upload to"); + Log.w(TAG, "Nowhere to upload to"); onSendToGoogleDone(); } } @@ -944,7 +941,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, if (!sendToGoogleDialog.getCreateNewMap()) { // Ask the user to choose a map to upload into Intent listIntent = new Intent(this, MyMapsList.class); - startActivityForResult(listIntent, MyTracksConstants.GET_MAP); + startActivityForResult(listIntent, Constants.GET_MAP); // The callback for GET_MAP calls authenticateToGoogleMaps } else { authenticateToGoogleMaps(null); @@ -957,8 +954,8 @@ public class MyTracks extends TabActivity implements OnTouchListener, setProgressValue(0); setProgressMessage( R.string.progress_message_authenticating_mymaps); - authenticate(results, MyTracksConstants.AUTHENTICATE_TO_MY_MAPS, - MapsService.getServiceName()); + authenticate(results, Constants.AUTHENTICATE_TO_MY_MAPS, + MyMapsConstants.SERVICE_NAME); // AUTHENTICATE_TO_MY_MAPS callback calls sendToGoogleMaps } @@ -978,7 +975,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, } catch (RuntimeException e) { // If that fails whatever reasons we'll just log an error, but // continue. - Log.w(MyTracksConstants.TAG, "Updating map id failed.", e); + Log.w(TAG, "Updating map id failed.", e); } } @@ -1010,7 +1007,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, setProgressValue(0); setProgressMessage(R.string.progress_message_authenticating_fusiontables); - authenticate(results, MyTracksConstants.AUTHENTICATE_TO_FUSION_TABLES, + authenticate(results, Constants.AUTHENTICATE_TO_FUSION_TABLES, SendToFusionTables.SERVICE_ID); // AUTHENTICATE_TO_FUSION_TABLES callback calls sendToFusionTables } @@ -1032,10 +1029,10 @@ public class MyTracks extends TabActivity implements OnTouchListener, } catch (RuntimeException e) { // If that fails whatever reasons we'll just log an error, but // continue. - Log.w(MyTracksConstants.TAG, "Updating table id failed.", e); + Log.w(TAG, "Updating table id failed.", e); } } - + onSendToFusionTablesDone(); } }; @@ -1063,7 +1060,7 @@ public class MyTracks extends TabActivity implements OnTouchListener, setProgressMessage( R.string.progress_message_authenticating_docs); authenticate(new Intent(), - MyTracksConstants.AUTHENTICATE_TO_DOCLIST, + Constants.AUTHENTICATE_TO_DOCLIST, SendToDocs.GDATA_SERVICE_NAME_DOCLIST); // AUTHENTICATE_TO_DOCLIST callback calls authenticateToGoogleTrix } @@ -1073,16 +1070,16 @@ public class MyTracks extends TabActivity implements OnTouchListener, setProgressMessage( R.string.progress_message_authenticating_docs); authenticate(new Intent(), - MyTracksConstants.AUTHENTICATE_TO_TRIX, + Constants.AUTHENTICATE_TO_TRIX, SendToDocs.GDATA_SERVICE_NAME_TRIX); // AUTHENTICATE_TO_TRIX callback calls sendToGoogleDocs } private void sendToGoogleDocs(final long trackId) { - Log.d(MyTracksConstants.TAG, "Sending to Docs...."); + Log.d(TAG, "Sending to Docs...."); setProgressValue(50); setProgressMessage(R.string.progress_message_sending_docs); - final SendToDocs sender = new SendToDocs(this, + final SendToDocs sender = new SendToDocs(this, authMap.get(SendToDocs.GDATA_SERVICE_NAME_TRIX), authMap.get(SendToDocs.GDATA_SERVICE_NAME_DOCLIST), trackId); sendToTrackId = trackId; @@ -1151,11 +1148,11 @@ public class MyTracks extends TabActivity implements OnTouchListener, DialogManager.showDialogSafely(this, sendToGoogleResultDialog); } - private boolean shareLinkToMap(boolean sentToMyMaps, boolean sentToFusionTables) { + boolean shareLinkToMap(boolean sentToMyMaps, boolean sentToFusionTables) { String url = null; if (sentToMyMaps && sendToMyMapsSuccess) { // Prefer a link to My Maps - url = MapsService.buildMapUrl(sendToMyMapsMapId); + url = MapsFacade.buildMapUrl(sendToMyMapsMapId); } else if (sentToFusionTables && sendToFusionTablesSuccess) { // Otherwise try using the link to fusion tables url = getFusionTablesUrl(sendToTrackId); @@ -1206,11 +1203,11 @@ public class MyTracks extends TabActivity implements OnTouchListener, * Binds to track recording service if it is running. */ private void tryBindTrackRecordingService() { - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "MyTracks: Trying to bind to track recording service..."); bindService(new Intent(this, TrackRecordingService.class), serviceConnection, 0); - Log.d(MyTracksConstants.TAG, "MyTracks: ...bind finished!"); + Log.d(TAG, "MyTracks: ...bind finished!"); isBound = true; } @@ -1220,14 +1217,12 @@ public class MyTracks extends TabActivity implements OnTouchListener, */ private void tryUnbindTrackRecordingService() { if (isBound) { - Log.d(MyTracksConstants.TAG, - "MyTracks: Trying to unbind from track recording service..."); + Log.d(TAG, "MyTracks: Trying to unbind from track recording service..."); try { unbindService(serviceConnection); - Log.d(MyTracksConstants.TAG, "MyTracks: ...unbind finished!"); + Log.d(TAG, "MyTracks: ...unbind finished!"); } catch (IllegalArgumentException e) { - Log.d(MyTracksConstants.TAG, - "MyTracks: Tried unbinding, but service was not registered.", e); + Log.d(TAG, "MyTracks: Tried unbinding, but service was not registered.", e); } isBound = false; } @@ -1319,24 +1314,24 @@ public class MyTracks extends TabActivity implements OnTouchListener, } public boolean getSendToGoogleSuccess() { - return sendToMyMapsSuccess && sendToFusionTablesSuccess && sendToDocsSuccess; + return sendToFusionTablesSuccess && sendToDocsSuccess; } // @VisibleForTesting long getRecordingTrackId() { return sharedPreferences.getLong(getString(R.string.recording_track_key), -1); } - + // @VisibleForTesting SharedPreferences getSharedPreferences() { return sharedPreferences; } - + // @VisibleForTesting static void clearInstance() { instance = null; } - + // @VisibleForTesting ITrackRecordingService getTrackRecordingService() { return trackRecordingService; diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksMap.java b/MyTracks/src/com/google/android/apps/mytracks/MyTracksMap.java index 32bbb8e49..8a85f7b42 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksMap.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MyTracksMap.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.Track; @@ -343,37 +343,37 @@ public class MyTracksMap extends MapActivity public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { menu.setHeaderTitle(R.string.tracklist_this_track); - menu.add(0, MyTracksConstants.MENU_EDIT, 0, + menu.add(0, Constants.MENU_EDIT, 0, R.string.tracklist_edit_track); if (!dataHub.isRecordingSelected()) { - menu.add(0, MyTracksConstants.MENU_SEND_TO_GOOGLE, 0, + menu.add(0, Constants.MENU_SEND_TO_GOOGLE, 0, R.string.tracklist_send_to_google); - SubMenu share = menu.addSubMenu(0, MyTracksConstants.MENU_SHARE, 0, + SubMenu share = menu.addSubMenu(0, Constants.MENU_SHARE, 0, R.string.tracklist_share_track); - share.add(0, MyTracksConstants.MENU_SHARE_LINK, 0, + share.add(0, Constants.MENU_SHARE_LINK, 0, R.string.tracklist_share_link); - share.add(0, MyTracksConstants.MENU_SHARE_GPX_FILE, 0, + share.add(0, Constants.MENU_SHARE_GPX_FILE, 0, R.string.tracklist_share_gpx_file); - share.add(0, MyTracksConstants.MENU_SHARE_KML_FILE, 0, + share.add(0, Constants.MENU_SHARE_KML_FILE, 0, R.string.tracklist_share_kml_file); - share.add(0, MyTracksConstants.MENU_SHARE_CSV_FILE, 0, + share.add(0, Constants.MENU_SHARE_CSV_FILE, 0, R.string.tracklist_share_csv_file); - share.add(0, MyTracksConstants.MENU_SHARE_TCX_FILE, 0, + share.add(0, Constants.MENU_SHARE_TCX_FILE, 0, R.string.tracklist_share_tcx_file); SubMenu save = menu.addSubMenu(0, - MyTracksConstants.MENU_WRITE_TO_SD_CARD, 0, + Constants.MENU_WRITE_TO_SD_CARD, 0, R.string.tracklist_write_to_sd); - save.add(0, MyTracksConstants.MENU_SAVE_GPX_FILE, 0, + save.add(0, Constants.MENU_SAVE_GPX_FILE, 0, R.string.tracklist_save_as_gpx); - save.add(0, MyTracksConstants.MENU_SAVE_KML_FILE, 0, + save.add(0, Constants.MENU_SAVE_KML_FILE, 0, R.string.tracklist_save_as_kml); - save.add(0, MyTracksConstants.MENU_SAVE_CSV_FILE, 0, + save.add(0, Constants.MENU_SAVE_CSV_FILE, 0, R.string.tracklist_save_as_csv); - save.add(0, MyTracksConstants.MENU_SAVE_TCX_FILE, 0, + save.add(0, Constants.MENU_SAVE_TCX_FILE, 0, R.string.tracklist_save_as_tcx); - menu.add(0, MyTracksConstants.MENU_CLEAR_MAP, 0, + menu.add(0, Constants.MENU_CLEAR_MAP, 0, R.string.tracklist_clear_map); - menu.add(0, MyTracksConstants.MENU_DELETE, 0, + menu.add(0, Constants.MENU_DELETE, 0, R.string.tracklist_delete_track); } } @@ -383,7 +383,7 @@ public class MyTracksMap extends MapActivity public boolean onMenuItemSelected(int featureId, MenuItem item) { if (!super.onMenuItemSelected(featureId, item)) { MyTracks.getInstance().onActivityResult( - MyTracksConstants.getActionFromMenuId(item.getItemId()), RESULT_OK, + Constants.getActionFromMenuId(item.getItemId()), RESULT_OK, new Intent()); return true; } @@ -393,10 +393,10 @@ public class MyTracksMap extends MapActivity @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); - myLocation = menu.add(0, MyTracksConstants.MENU_MY_LOCATION, 0, + myLocation = menu.add(0, Constants.MENU_MY_LOCATION, 0, R.string.mylocation); myLocation.setIcon(android.R.drawable.ic_menu_mylocation); - toggleLayers = menu.add(0, MyTracksConstants.MENU_TOGGLE_LAYERS, 0, + toggleLayers = menu.add(0, Constants.MENU_TOGGLE_LAYERS, 0, R.string.switch_to_sat); toggleLayers.setIcon(android.R.drawable.ic_menu_mapmode); return true; @@ -412,7 +412,7 @@ public class MyTracksMap extends MapActivity @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case MyTracksConstants.MENU_MY_LOCATION: { + case Constants.MENU_MY_LOCATION: { dataHub.forceUpdateLocation(); keepMyLocationVisible = true; if (mapView.getZoomLevel() < 18) { @@ -420,7 +420,7 @@ public class MyTracksMap extends MapActivity } return true; } - case MyTracksConstants.MENU_TOGGLE_LAYERS: { + case Constants.MENU_TOGGLE_LAYERS: { mapView.setSatellite(!mapView.isSatellite()); return true; } @@ -497,7 +497,7 @@ public class MyTracksMap extends MapActivity @Override public void onCurrentLocationChanged(Location location) { - if (!location.getProvider().equals(MyTracksConstants.GPS_PROVIDER)) { + if (!location.getProvider().equals(Constants.GPS_PROVIDER)) { Log.d(TAG, "MyTracksMap: Network location update received (provider '" + location.getProvider() + "'."); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksOverlay.java b/MyTracks/src/com/google/android/apps/mytracks/MyTracksOverlay.java index 9e4e1620d..d0b30e668 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksOverlay.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MyTracksOverlay.java @@ -103,7 +103,7 @@ public class MyTracksOverlay extends Overlay { this.waypoints = new ArrayList(); this.points = new ArrayList(1024); this.pendingPoints = new ArrayBlockingQueue( - MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS, true); + Constants.MAX_DISPLAYED_TRACK_POINTS, true); // TODO: Can we use a FrameAnimation or similar here rather // than individual resources for each arrow direction? @@ -460,7 +460,7 @@ public class MyTracksOverlay extends Overlay { if (waypoint != null && dmin < 15000000 / Math.pow(2, mapView.getZoomLevel())) { - Intent intent = new Intent(context, MyTracksWaypointDetails.class); + Intent intent = new Intent(context, WaypointDetails.class); intent.putExtra("waypointid", waypoint.getId()); context.startActivity(intent); return true; diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksReceiver.java b/MyTracks/src/com/google/android/apps/mytracks/MyTracksReceiver.java index 9847ab2ee..040e872e6 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksReceiver.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MyTracksReceiver.java @@ -16,8 +16,8 @@ package com.google.android.apps.mytracks; import static android.content.Intent.ACTION_BOOT_COMPLETED; -import static com.google.android.apps.mytracks.MyTracksConstants.RESUME_TRACK_EXTRA_NAME; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +import static com.google.android.apps.mytracks.Constants.RESUME_TRACK_EXTRA_NAME; +import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.services.TrackRecordingService; diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksSettings.java b/MyTracks/src/com/google/android/apps/mytracks/MyTracksSettings.java index 0e02d05f8..e16cd64dd 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksSettings.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MyTracksSettings.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.io.backup.BackupActivityHelper; import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener; diff --git a/MyTracks/src/com/google/android/apps/mytracks/SensorStateActivity.java b/MyTracks/src/com/google/android/apps/mytracks/SensorStateActivity.java index fb9559d26..5302ad80b 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/SensorStateActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/SensorStateActivity.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.services.ITrackRecordingService; import com.google.android.apps.mytracks.services.sensors.SensorUtils; @@ -103,7 +103,7 @@ public class SensorStateActivity extends Activity { ITrackRecordingService service = mt == null ? null : mt.getTrackRecordingService(); if (service == null) { - Log.d(MyTracksConstants.TAG, "Could not get track recording service."); + Log.d(Constants.TAG, "Could not get track recording service."); updateSensorState(Sensor.SensorState.NONE); updateSensorData(null); return; @@ -116,9 +116,9 @@ public class SensorStateActivity extends Activity { updateSensorData(sds); } } catch (RemoteException e) { - Log.e(MyTracksConstants.TAG, "Could not read sensor data.", e); + Log.e(Constants.TAG, "Could not read sensor data.", e); } catch (InvalidProtocolBufferException e) { - Log.e(MyTracksConstants.TAG, "Could not read sensor data.", e); + Log.e(Constants.TAG, "Could not read sensor data.", e); } updateSensorData(sds); @@ -126,7 +126,7 @@ public class SensorStateActivity extends Activity { int i = service.getSensorState(); updateSensorState(Sensor.SensorState.valueOf(i)); } catch (RemoteException e) { - Log.e(MyTracksConstants.TAG, "Could not read sensor state.", e); + Log.e(Constants.TAG, "Could not read sensor state.", e); updateSensorState(Sensor.SensorState.NONE); } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/StatsActivity.java b/MyTracks/src/com/google/android/apps/mytracks/StatsActivity.java index 5ba219f0f..a9fa70935 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/StatsActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/StatsActivity.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Waypoint; @@ -175,14 +175,14 @@ public class StatsActivity extends Activity implements TrackDataListener { public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuItem currentSegment = menu.add(0, - MyTracksConstants.MENU_CURRENT_SEGMENT, 0, R.string.current_segment); + Constants.MENU_CURRENT_SEGMENT, 0, R.string.current_segment); currentSegment.setIcon(R.drawable.ic_menu_lastsegment); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { - MenuItem item = menu.findItem(MyTracksConstants.MENU_CURRENT_SEGMENT); + MenuItem item = menu.findItem(Constants.MENU_CURRENT_SEGMENT); if (item != null) { item.setTitle(showCurrentSegment ? getString(R.string.current_track) @@ -194,7 +194,7 @@ public class StatsActivity extends Activity implements TrackDataListener { @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case MyTracksConstants.MENU_CURRENT_SEGMENT: + case Constants.MENU_CURRENT_SEGMENT: showCurrentSegment = !showCurrentSegment; // TODO: Re-read only the data that interests us return true; diff --git a/MyTracks/src/com/google/android/apps/mytracks/StatsUtilities.java b/MyTracks/src/com/google/android/apps/mytracks/StatsUtilities.java index c37ecab65..f6327dace 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/StatsUtilities.java +++ b/MyTracks/src/com/google/android/apps/mytracks/StatsUtilities.java @@ -235,7 +235,7 @@ public class StatsUtilities { } public void setSpeedLabel(int id, int speedString, int paceString) { - Log.w(MyTracksConstants.TAG, "Setting view " + id + + Log.w(Constants.TAG, "Setting view " + id + " to " + reportSpeed + " speed: " + speedString + " pace: " + paceString); @@ -243,7 +243,7 @@ public class StatsUtilities { if (tv != null) { tv.setText(reportSpeed ? speedString : paceString); } else { - Log.w(MyTracksConstants.TAG, "Could not find id: " + id); + Log.w(Constants.TAG, "Could not find id: " + id); } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/TrackDataHub.java b/MyTracks/src/com/google/android/apps/mytracks/TrackDataHub.java index d97912f33..bb9d0165d 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/TrackDataHub.java +++ b/MyTracks/src/com/google/android/apps/mytracks/TrackDataHub.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.TrackDataListener.ProviderState; import com.google.android.apps.mytracks.content.MyTracksLocation; @@ -359,7 +359,7 @@ public class TrackDataHub { final long now = System.currentTimeMillis(); Location loc = locationManager.getLastKnownLocation( - MyTracksConstants.GPS_PROVIDER); + Constants.GPS_PROVIDER); if (loc == null || loc.getTime() < now - MAX_LOCATION_AGE_MS) { // We don't have a recent GPS fix, just use cell towers if available loc = locationManager.getLastKnownLocation( @@ -502,25 +502,25 @@ public class TrackDataHub { // Listen to compass Sensor compass = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); if (compass != null) { - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "TrackDataHub: Now registering sensor listeners."); sensorManager.registerListener(compassListener, compass, SensorManager.SENSOR_DELAY_UI); } // Listen to GPS LocationProvider gpsProvider = - locationManager.getProvider(MyTracksConstants.GPS_PROVIDER); + locationManager.getProvider(Constants.GPS_PROVIDER); if (gpsProvider == null) { Toast.makeText(context, R.string.error_no_gps_location_provider, Toast.LENGTH_LONG).show(); hasProviderEnabled = false; return; } else { - Log.d(MyTracksConstants.TAG, "TrackDataHub: Using location provider " + Log.d(Constants.TAG, "TrackDataHub: Using location provider " + gpsProvider.getName()); } locationManager.requestLocationUpdates(gpsProvider.getName(), 0 /*minTime*/, 0 /*minDist*/, locationListener); - hasProviderEnabled = locationManager.isProviderEnabled(MyTracksConstants.GPS_PROVIDER); + hasProviderEnabled = locationManager.isProviderEnabled(Constants.GPS_PROVIDER); // Listen to network location try { @@ -529,7 +529,7 @@ public class TrackDataHub { } catch (RuntimeException e) { // If anything at all goes wrong with getting a cell location do not // abort. Cell location is not essential to this app. - Log.w(MyTracksConstants.TAG, + Log.w(Constants.TAG, "Could not register network location listener."); } } @@ -777,7 +777,7 @@ public class TrackDataHub { private void notifyWaypointUpdated(final TrackDataListener... listeners) { // Always reload all the waypoints. final Cursor cursor = providerUtils.getWaypointsCursor( - selectedTrackId, 0, MyTracksConstants.MAX_DISPLAYED_WAYPOINTS_POINTS); + selectedTrackId, 0, Constants.MAX_DISPLAYED_WAYPOINTS_POINTS); listenerHandler.post(new Runnable() { @Override @@ -857,7 +857,7 @@ public class TrackDataHub { long minPointId = keepState ? lastSeenLocationId + 1 : 0; long maxPointId = keepState ? -1 : lastSeenLocationId; - if (numLoadedPoints >= MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS) { + if (numLoadedPoints >= Constants.MAX_DISPLAYED_TRACK_POINTS) { // We're about to exceed the maximum allowed number of points, so reload // the whole track with fewer points (the sampling frequency will be // lower). We do this for every listener even if we were loading just for @@ -931,7 +931,7 @@ public class TrackDataHub { // frequency. long numTotalPoints = lastStoredLocationId - localFirstSeenLocationId; pointSamplingFrequency = - (int) (1 + numTotalPoints / MyTracksConstants.TARGET_DISPLAYED_TRACK_POINTS); + (int) (1 + numTotalPoints / Constants.TARGET_DISPLAYED_TRACK_POINTS); } // Include a point if it fits one of the following criteria: diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksDetails.java b/MyTracks/src/com/google/android/apps/mytracks/TrackDetails.java similarity index 97% rename from MyTracks/src/com/google/android/apps/mytracks/MyTracksDetails.java rename to MyTracks/src/com/google/android/apps/mytracks/TrackDetails.java index 47d387d37..fcdd4dfa0 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksDetails.java +++ b/MyTracks/src/com/google/android/apps/mytracks/TrackDetails.java @@ -37,7 +37,7 @@ import android.widget.EditText; * * @author Leif Hendrik Wilden */ -public class MyTracksDetails extends Activity implements OnClickListener { +public class TrackDetails extends Activity implements OnClickListener { /** * The id of the track being edited (taken from bundle, "trackid") @@ -56,7 +56,7 @@ public class MyTracksDetails extends Activity implements OnClickListener { // Required extra when launching this intent: trackId = getIntent().getLongExtra("trackid", -1); if (trackId < 0) { - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "MyTracksDetails intent was launched w/o track id."); finish(); return; diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksList.java b/MyTracks/src/com/google/android/apps/mytracks/TrackList.java similarity index 85% rename from MyTracks/src/com/google/android/apps/mytracks/MyTracksList.java rename to MyTracks/src/com/google/android/apps/mytracks/TrackList.java index ad424e530..cf5004650 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksList.java +++ b/MyTracks/src/com/google/android/apps/mytracks/TrackList.java @@ -45,7 +45,7 @@ import android.widget.TextView; * * @author Leif Hendrik Wilden */ -public class MyTracksList extends ListActivity +public class TrackList extends ListActivity implements SharedPreferences.OnSharedPreferenceChangeListener, View.OnClickListener { @@ -70,40 +70,40 @@ public class MyTracksList extends ListActivity AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; contextPosition = info.position; - trackId = MyTracksList.this.listView.getAdapter().getItemId( + trackId = TrackList.this.listView.getAdapter().getItemId( contextPosition); - menu.add(0, MyTracksConstants.MENU_SHOW, 0, + menu.add(0, Constants.MENU_SHOW, 0, R.string.tracklist_show_track); - menu.add(0, MyTracksConstants.MENU_EDIT, 0, + menu.add(0, Constants.MENU_EDIT, 0, R.string.tracklist_edit_track); if (!MyTracks.getInstance().isRecording() || trackId != recordingTrackId) { - menu.add(0, MyTracksConstants.MENU_SEND_TO_GOOGLE, 0, + menu.add(0, Constants.MENU_SEND_TO_GOOGLE, 0, R.string.tracklist_send_to_google); - SubMenu share = menu.addSubMenu(0, MyTracksConstants.MENU_SHARE, 0, + SubMenu share = menu.addSubMenu(0, Constants.MENU_SHARE, 0, R.string.tracklist_share_track); - share.add(0, MyTracksConstants.MENU_SHARE_LINK, 0, + share.add(0, Constants.MENU_SHARE_LINK, 0, R.string.tracklist_share_link); - share.add(0, MyTracksConstants.MENU_SHARE_GPX_FILE, 0, + share.add(0, Constants.MENU_SHARE_GPX_FILE, 0, R.string.tracklist_share_gpx_file); - share.add(0, MyTracksConstants.MENU_SHARE_KML_FILE, 0, + share.add(0, Constants.MENU_SHARE_KML_FILE, 0, R.string.tracklist_share_kml_file); - share.add(0, MyTracksConstants.MENU_SHARE_CSV_FILE, 0, + share.add(0, Constants.MENU_SHARE_CSV_FILE, 0, R.string.tracklist_share_csv_file); - share.add(0, MyTracksConstants.MENU_SHARE_TCX_FILE, 0, + share.add(0, Constants.MENU_SHARE_TCX_FILE, 0, R.string.tracklist_share_tcx_file); SubMenu save = menu.addSubMenu(0, - MyTracksConstants.MENU_WRITE_TO_SD_CARD, 0, + Constants.MENU_WRITE_TO_SD_CARD, 0, R.string.tracklist_write_to_sd); - save.add(0, MyTracksConstants.MENU_SAVE_GPX_FILE, 0, + save.add(0, Constants.MENU_SAVE_GPX_FILE, 0, R.string.tracklist_save_as_gpx); - save.add(0, MyTracksConstants.MENU_SAVE_KML_FILE, 0, + save.add(0, Constants.MENU_SAVE_KML_FILE, 0, R.string.tracklist_save_as_kml); - save.add(0, MyTracksConstants.MENU_SAVE_CSV_FILE, 0, + save.add(0, Constants.MENU_SAVE_CSV_FILE, 0, R.string.tracklist_save_as_csv); - save.add(0, MyTracksConstants.MENU_SAVE_TCX_FILE, 0, + save.add(0, Constants.MENU_SAVE_TCX_FILE, 0, R.string.tracklist_save_as_tcx); - menu.add(0, MyTracksConstants.MENU_DELETE, 0, + menu.add(0, Constants.MENU_DELETE, 0, R.string.tracklist_delete_track); } } @@ -132,7 +132,7 @@ public class MyTracksList extends ListActivity protected void onListItemClick(ListView l, View v, int position, long id) { Intent result = new Intent(); result.putExtra("trackid", id); - setResult(MyTracksConstants.SHOW_TRACK, result); + setResult(Constants.SHOW_TRACK, result); finish(); } @@ -140,24 +140,24 @@ public class MyTracksList extends ListActivity public boolean onMenuItemSelected(int featureId, MenuItem item) { if (!super.onMenuItemSelected(featureId, item)) { switch (item.getItemId()) { - case MyTracksConstants.MENU_SHOW: { + case Constants.MENU_SHOW: { onListItemClick(null, null, 0, trackId); return true; } - case MyTracksConstants.MENU_EDIT: { - Intent intent = new Intent(this, MyTracksDetails.class); + case Constants.MENU_EDIT: { + Intent intent = new Intent(this, TrackDetails.class); intent.putExtra("trackid", trackId); startActivity(intent); return true; } - case MyTracksConstants.MENU_SHARE: - case MyTracksConstants.MENU_WRITE_TO_SD_CARD: + case Constants.MENU_SHARE: + case Constants.MENU_WRITE_TO_SD_CARD: return false; default: { Intent result = new Intent(); result.putExtra("trackid", trackId); setResult( - MyTracksConstants.getActionFromMenuId(item.getItemId()), result); + Constants.getActionFromMenuId(item.getItemId()), result); finish(); return true; } @@ -170,7 +170,7 @@ public class MyTracksList extends ListActivity public void onClick(View v) { switch (v.getId()) { case R.id.tracklist_btn_delete_all: { - Handler h = new MyTracksDeleteAllTracks(this, null); + Handler h = new DeleteAllTracks(this, null); h.handleMessage(null); break; } diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksWaypointDetails.java b/MyTracks/src/com/google/android/apps/mytracks/WaypointDetails.java similarity index 98% rename from MyTracks/src/com/google/android/apps/mytracks/MyTracksWaypointDetails.java rename to MyTracks/src/com/google/android/apps/mytracks/WaypointDetails.java index 5e9f110b7..d26b9a87b 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksWaypointDetails.java +++ b/MyTracks/src/com/google/android/apps/mytracks/WaypointDetails.java @@ -39,7 +39,7 @@ import android.widget.ImageView; * * @author Leif Hendrik Wilden */ -public class MyTracksWaypointDetails extends Activity +public class WaypointDetails extends Activity implements OnClickListener { public static final String WAYPOINT_ID_EXTRA = "com.google.android.apps.mytracks.WAYPOINT_ID"; @@ -82,7 +82,7 @@ public class MyTracksWaypointDetails extends Activity // Required extra when launching this intent: waypointId = getIntent().getLongExtra(WAYPOINT_ID_EXTRA, -1); if (waypointId < 0) { - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "MyTracksWaypointsDetails intent was launched w/o waypoint id."); finish(); return; diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksWaypointsList.java b/MyTracks/src/com/google/android/apps/mytracks/WaypointsList.java similarity index 89% rename from MyTracks/src/com/google/android/apps/mytracks/MyTracksWaypointsList.java rename to MyTracks/src/com/google/android/apps/mytracks/WaypointsList.java index 0b2cb17af..fddb1ddee 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksWaypointsList.java +++ b/MyTracks/src/com/google/android/apps/mytracks/WaypointsList.java @@ -49,7 +49,7 @@ import android.widget.TextView; * * @author Leif Hendrik Wilden */ -public class MyTracksWaypointsList extends ListActivity +public class WaypointsList extends ListActivity implements View.OnClickListener { private int contextPosition = -1; @@ -71,14 +71,14 @@ public class MyTracksWaypointsList extends ListActivity AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; contextPosition = info.position; - waypointId = MyTracksWaypointsList.this.listView.getAdapter() + waypointId = WaypointsList.this.listView.getAdapter() .getItemId(contextPosition); int type = providerUtils.getWaypoint(info.id).getType(); - menu.add(0, MyTracksConstants.MENU_SHOW, 0, + menu.add(0, Constants.MENU_SHOW, 0, R.string.waypointslist_show_waypoint); - menu.add(0, MyTracksConstants.MENU_EDIT, 0, + menu.add(0, Constants.MENU_EDIT, 0, R.string.waypointslist_edit_waypoint); - menu.add(0, MyTracksConstants.MENU_DELETE, 0, + menu.add(0, Constants.MENU_DELETE, 0, R.string.waypointslist_delete_waypoint).setEnabled( recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT || info.id != providerUtils.getLastWaypointId(recordingTrackId)); @@ -89,8 +89,8 @@ public class MyTracksWaypointsList extends ListActivity protected void onListItemClick(ListView l, View v, int position, long id) { Intent result = new Intent(); result.putExtra("trackid", trackId); - result.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, id); - setResult(MyTracksConstants.EDIT_WAYPOINT, result); + result.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, id); + setResult(Constants.EDIT_WAYPOINT, result); finish(); } @@ -98,18 +98,18 @@ public class MyTracksWaypointsList extends ListActivity public boolean onMenuItemSelected(int featureId, MenuItem item) { if (!super.onMenuItemSelected(featureId, item)) { switch (item.getItemId()) { - case MyTracksConstants.MENU_SHOW: { + case Constants.MENU_SHOW: { onListItemClick(null, null, 0, waypointId); return true; } - case MyTracksConstants.MENU_EDIT: { - Intent intent = new Intent(this, MyTracksWaypointDetails.class); + case Constants.MENU_EDIT: { + Intent intent = new Intent(this, WaypointDetails.class); intent.putExtra("trackid", trackId); - intent.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, waypointId); + intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, waypointId); startActivity(intent); return true; } - case MyTracksConstants.MENU_DELETE: { + case Constants.MENU_DELETE: { deleteWaypoint(waypointId); } } @@ -185,18 +185,18 @@ public class MyTracksWaypointsList extends ListActivity try { id = MyTracks.getInstance().insertWaypoint(request); } catch (RemoteException e) { - Log.e(MyTracksConstants.TAG, "Cannot insert marker.", e); + Log.e(Constants.TAG, "Cannot insert marker.", e); return; } catch (IllegalStateException e) { - Log.e(MyTracksConstants.TAG, "Cannot insert marker.", e); + Log.e(Constants.TAG, "Cannot insert marker.", e); return; } if (id < 0) { - Log.e(MyTracksConstants.TAG, "Failed to insert marker."); + Log.e(Constants.TAG, "Failed to insert marker."); return; } - Intent intent = new Intent(this, MyTracksWaypointDetails.class); - intent.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, id); + Intent intent = new Intent(this, WaypointDetails.class); + intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, id); startActivity(intent); } @@ -261,7 +261,7 @@ public class MyTracksWaypointsList extends ListActivity public void onClick(DialogInterface dialog, int i) { dialog.dismiss(); providerUtils.deleteWaypoint(waypointId, - new StringUtils(MyTracksWaypointsList.this)); + new StringUtils(WaypointsList.this)); } }); builder.setNegativeButton(getString(R.string.no), diff --git a/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProvider.java b/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProvider.java index e1c26901a..7c437a172 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProvider.java +++ b/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProvider.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.content; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.util.ApiFeatures; import android.content.ContentProvider; @@ -382,7 +382,7 @@ public class MyTracksProvider extends ContentProvider { } if (ApiFeatures.getInstance().canReuseSQLiteQueryBuilder()) { - Log.i(MyTracksConstants.TAG, + Log.i(Constants.TAG, "Build query: " + qb.buildQuery(projection, selection, selectionArgs, null, null, sortOrder, null)); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/AuthManagerFactory.java b/MyTracks/src/com/google/android/apps/mytracks/io/AuthManagerFactory.java index d701a530c..8532e807d 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/AuthManagerFactory.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/AuthManagerFactory.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.io; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import android.app.Activity; import android.os.Build; @@ -46,11 +46,11 @@ public class AuthManagerFactory { public static AuthManager getAuthManager(Activity activity, int code, Bundle extras, boolean requireGoogle, String service) { if (useModernAuthManager()) { - Log.i(MyTracksConstants.TAG, + Log.i(Constants.TAG, "Creating modern auth manager: " + service); return new ModernAuthManager(activity, code, extras, requireGoogle, service); } else { - Log.i(MyTracksConstants.TAG, + Log.i(Constants.TAG, "Creating legacy auth manager: " + service); return new AuthManagerOld(activity, code, extras, requireGoogle, service); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/GpxImporter.java b/MyTracks/src/com/google/android/apps/mytracks/io/GpxImporter.java index 02f5af832..f92385038 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/GpxImporter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/GpxImporter.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.io; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.stats.TripStatisticsBuilder; @@ -174,7 +174,7 @@ public class GpxImporter extends DefaultHandler { parser.parse(is, handler); long end = System.currentTimeMillis(); - Log.d(MyTracksConstants.TAG, "Total import time: " + (end - start) + "ms"); + Log.d(Constants.TAG, "Total import time: " + (end - start) + "ms"); trackIds = handler.getImportedTrackIds(); } finally { @@ -462,7 +462,7 @@ public class GpxImporter extends DefaultHandler { // check for negative time change if (timeDifference < 0) { - Log.w(MyTracksConstants.TAG, "Found negative time change."); + Log.w(Constants.TAG, "Found negative time change."); } else { // We don't have a speed and bearing in GPX, make something up from diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/ModernAuthManager.java b/MyTracks/src/com/google/android/apps/mytracks/io/ModernAuthManager.java index 511584541..24c721bc4 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/ModernAuthManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/ModernAuthManager.java @@ -23,7 +23,7 @@ import com.google.android.accounts.AuthenticatorException; import com.google.android.accounts.OperationCanceledException; import com.google.android.apps.mytracks.AccountChooser; import com.google.android.apps.mytracks.MyTracks; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import android.app.Activity; import android.content.Intent; @@ -104,20 +104,20 @@ public class ModernAuthManager implements AuthManager { if (result.containsKey(AccountManager.KEY_INTENT)) { Intent intent = (Intent) result.get(AccountManager.KEY_INTENT); clearNewTaskFlag(intent); - activity.startActivityForResult(intent, MyTracksConstants.GET_LOGIN); + activity.startActivityForResult(intent, Constants.GET_LOGIN); return; } authToken = result.getString( AccountManager.KEY_AUTHTOKEN); - Log.e(MyTracksConstants.TAG, "Got auth token."); + Log.e(Constants.TAG, "Got auth token."); runWhenFinished(); } catch (OperationCanceledException e) { - Log.e(MyTracksConstants.TAG, "Operation Canceled", e); + Log.e(Constants.TAG, "Operation Canceled", e); } catch (IOException e) { - Log.e(MyTracksConstants.TAG, "IOException", e); + Log.e(Constants.TAG, "IOException", e); } catch (AuthenticatorException e) { - Log.e(MyTracksConstants.TAG, "Authentication Failed", e); + Log.e(Constants.TAG, "Authentication Failed", e); } } }, null /* handler */); @@ -149,9 +149,9 @@ public class ModernAuthManager implements AuthManager { if (results != null) { authToken = results.getStringExtra( AccountManager.KEY_AUTHTOKEN); - Log.w(MyTracksConstants.TAG, "authResult: " + authToken); + Log.w(Constants.TAG, "authResult: " + authToken); } else { - Log.e(MyTracksConstants.TAG, "No auth result results!!"); + Log.e(Constants.TAG, "No auth result results!!"); } runWhenFinished(); return authToken != null; @@ -181,7 +181,7 @@ public class ModernAuthManager implements AuthManager { activity.runOnUiThread(new Runnable() { public void run() { - accountManager.invalidateAuthToken(MyTracksConstants.ACCOUNT_TYPE, + accountManager.invalidateAuthToken(Constants.ACCOUNT_TYPE, authToken); MyTracks.getInstance().getAccountChooser().chooseAccount(activity, new AccountChooser.AccountHandler() { diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/MyMapsFactory.java b/MyTracks/src/com/google/android/apps/mytracks/io/MyMapsFactory.java deleted file mode 100644 index 8d17e1667..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/io/MyMapsFactory.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.google.android.apps.mytracks.io; - -import com.google.android.apps.mytracks.io.gdata.GDataClientFactory; -import com.google.android.apps.mytracks.io.mymaps.MapsFacade; -import com.google.android.apps.mytracks.io.mymaps.MapsService; -import com.google.android.apps.mytracks.io.mymaps.MapsStringsProvider; -import com.google.android.apps.mytracks.io.mymaps.MapsFacade.AuthenticationRefresher; -import com.google.android.maps.mytracks.R; - -import android.app.Activity; -import android.content.Context; - -/** - * Factory to easily instantiate a {@link MapsFacade}. - * - * @author Rodrigo Damazio - */ -public class MyMapsFactory { - - /** - * Simple provider for reading strings from resources. - */ - private static class MyMapsStringProvider implements MapsStringsProvider { - private final Context context; - - public MyMapsStringProvider(Context context) { - this.context = context; - } - - @Override - public String getNewMapDescription() { - return context.getString(R.string.new_map_description); - } - - @Override - public String getStart() { - return context.getString(R.string.start); - } - - @Override - public String getEnd() { - return context.getString(R.string.end); - } - } - - /** - * Creates a new Maps fa�ade interface instance. - * - * @param context current context - * @param auth a valid authentication manager - * @return the fa�ade - */ - public static MapsFacade newMapsClient(Activity context, final AuthManager auth) { - MapsFacade client = MapsService.newClient(context, - GDataClientFactory.getGDataClient(context), - new MyMapsStringProvider(context), - auth.getAuthToken()); - client.setAuthenticationRefresher(new AuthenticationRefresher() { - @Override - public void invalidateAndRefresh(Runnable done) { - auth.invalidateAndRefresh(done); - } - }); - return client; - } - - private MyMapsFactory() {} -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/SendToDocs.java b/MyTracks/src/com/google/android/apps/mytracks/io/SendToDocs.java index 5c9254cd0..22e974b2d 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/SendToDocs.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/SendToDocs.java @@ -16,7 +16,7 @@ package com.google.android.apps.mytracks.io; import com.google.android.apps.mytracks.MyTracks; -import com.google.android.apps.mytracks.MyTracksConstants; +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.Track; @@ -82,7 +82,7 @@ public class SendToDocs { metricUnits = true; } - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "Sending to Google Docs: trackId = " + trackId); handlerThread = new HandlerThread("SendToGoogleDocs"); handlerThread.start(); @@ -105,7 +105,7 @@ public class SendToDocs { try { if (trackId == -1) { - Log.w(MyTracksConstants.TAG, "Cannot get track id."); + Log.w(Constants.TAG, "Cannot get track id."); return; } @@ -113,14 +113,14 @@ public class SendToDocs { Track track = MyTracksProviderUtils.Factory.get(activity).getTrack(trackId); if (track == null) { - Log.w(MyTracksConstants.TAG, "Cannot get track."); + Log.w(Constants.TAG, "Cannot get track."); return; } // Transmit track stats via GData feed: // ------------------------------- - Log.d(MyTracksConstants.TAG, "SendToDocs: Uploading to spreadsheet"); + Log.d(Constants.TAG, "SendToDocs: Uploading to spreadsheet"); success = uploadToDocs(track); if (success) { if (createdNewSpreadSheet) { @@ -133,7 +133,7 @@ public class SendToDocs { } else { statusMessage = activity.getString(R.string.error_sending_to_docs); } - Log.d(MyTracksConstants.TAG, "SendToDocs: Done."); + Log.d(Constants.TAG, "SendToDocs: Done."); } finally { if (onCompletion != null) { activity.runOnUiThread(onCompletion); @@ -176,7 +176,7 @@ public class SendToDocs { SpreadsheetsClient gdataClient = new SpreadsheetsClient(androidClient, new XmlDocsGDataParserFactory(new AndroidXmlParserFactory())); trixWrapper.setClient(gdataClient); - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "GData connection prepared: " + this.docListAuth); String sheetTitle = "My Tracks"; @@ -194,7 +194,7 @@ public class SendToDocs { spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper, sheetTitle); } catch (IOException e) { - Log.i(MyTracksConstants.TAG, "Spreadsheet lookup failed.", e); + Log.i(Constants.TAG, "Spreadsheet lookup failed.", e); return false; } @@ -205,14 +205,14 @@ public class SendToDocs { try { Thread.sleep(5000); } catch (InterruptedException e) { - Log.e(MyTracksConstants.TAG, "Sleep interrupted", e); + Log.e(Constants.TAG, "Sleep interrupted", e); } try { spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper, sheetTitle); } catch (IOException e) { - Log.i(MyTracksConstants.TAG, "2nd spreadsheet lookup failed.", e); + Log.i(Constants.TAG, "2nd spreadsheet lookup failed.", e); return false; } } @@ -220,13 +220,13 @@ public class SendToDocs { // We were unable to find an existing spreadsheet, so create a new one. MyTracks.getInstance().setProgressValue(70); if (spreadsheetId == null) { - Log.i(MyTracksConstants.TAG, "Creating new spreadsheet: " + sheetTitle); + Log.i(Constants.TAG, "Creating new spreadsheet: " + sheetTitle); try { spreadsheetId = docsHelper.createSpreadsheet(activity, docListWrapper, sheetTitle); } catch (IOException e) { - Log.i(MyTracksConstants.TAG, "Failed to create new spreadsheet " + Log.i(Constants.TAG, "Failed to create new spreadsheet " + sheetTitle, e); return false; } @@ -239,19 +239,19 @@ public class SendToDocs { // reported an error. Seems to be a know bug, // see http://code.google.com/p/gdata-issues/issues/detail?id=929 // Try to find the created spreadsheet: - Log.w(MyTracksConstants.TAG, + Log.w(Constants.TAG, "Create might have failed. Trying to find created document."); try { Thread.sleep(5000); } catch (InterruptedException e) { - Log.e(MyTracksConstants.TAG, "Sleep interrupted", e); + Log.e(Constants.TAG, "Sleep interrupted", e); } try { spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper, sheetTitle); } catch (IOException e) { - Log.i(MyTracksConstants.TAG, "Failed create-failed lookup", e); + Log.i(Constants.TAG, "Failed create-failed lookup", e); return false; } @@ -261,19 +261,19 @@ public class SendToDocs { try { Thread.sleep(5000); } catch (InterruptedException e) { - Log.e(MyTracksConstants.TAG, "Sleep interrupted", e); + Log.e(Constants.TAG, "Sleep interrupted", e); } try { spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper, sheetTitle); } catch (IOException e) { - Log.i(MyTracksConstants.TAG, "Failed create-failed relookup", e); + Log.i(Constants.TAG, "Failed create-failed relookup", e); return false; } } if (spreadsheetId == null) { - Log.i(MyTracksConstants.TAG, + Log.i(Constants.TAG, "Creating new spreadsheet really failed."); return false; } @@ -287,7 +287,7 @@ public class SendToDocs { throw new IOException("Worksheet ID lookup returned empty"); } } catch (IOException e) { - Log.i(MyTracksConstants.TAG, "Looking up worksheet id failed.", e); + Log.i(Constants.TAG, "Looking up worksheet id failed.", e); return false; } @@ -295,9 +295,9 @@ public class SendToDocs { docsHelper.addTrackRow(activity, trixAuth, spreadsheetId, worksheetId, track, metricUnits); - Log.i(MyTracksConstants.TAG, "Done uploading to docs."); + Log.i(Constants.TAG, "Done uploading to docs."); } catch (IOException e) { - Log.e(MyTracksConstants.TAG, "Unable to upload docs.", e); + Log.e(Constants.TAG, "Unable to upload docs.", e); return false; } finally { if (androidClient != null) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java b/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java index c15013a50..adc7c31ed 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.io; -import com.google.android.apps.mytracks.MyTracksConstants; +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.content.MyTracksProviderUtils; @@ -151,7 +151,7 @@ public class SendToFusionTables implements Runnable { @Override public void run() { - Log.d(MyTracksConstants.TAG, "Sending to Fusion tables: trackId = " + trackId); + Log.d(Constants.TAG, "Sending to Fusion tables: trackId = " + trackId); doUpload(); } @@ -172,7 +172,7 @@ public class SendToFusionTables implements Runnable { private void doUpload() { ((GoogleHeaders) transport.defaultHeaders).setGoogleLogin(auth.getAuthToken()); int statusMessageId = R.string.error_sending_to_fusiontables; - boolean success = false; + boolean success = true; try { progressIndicator.setProgressValue(PROGRESS_INITIALIZATION); progressIndicator.setProgressMessage(R.string.progress_message_reading_track); @@ -204,11 +204,10 @@ public class SendToFusionTables implements Runnable { } statusMessageId = R.string.status_new_fusiontable_has_been_created; - success = true; - Log.d(MyTracksConstants.TAG, "SendToFusionTables: Done: " + success); + Log.d(Constants.TAG, "SendToFusionTables: Done: " + success); progressIndicator.setProgressValue(PROGRESS_COMPLETE); - } finally { + final boolean finalSuccess = success; final int finalStatusMessageId = statusMessageId; context.runOnUiThread(new Runnable() { @@ -229,14 +228,14 @@ public class SendToFusionTables implements Runnable { * @return true in case of success. */ private boolean createNewTable(Track track) { - Log.d(MyTracksConstants.TAG, "Creating a new fusion table."); + Log.d(Constants.TAG, "Creating a new fusion table."); String query = "CREATE TABLE '" + sqlEscape(track.getName()) + "' (name:STRING,description:STRING,geometry:LOCATION,marker:STRING)"; return runUpdate(query); } private boolean makeTableUnlisted(String tableId) { - Log.d(MyTracksConstants.TAG, "Setting visibility to unlisted."); + Log.d(Constants.TAG, "Setting visibility to unlisted."); String query = "UPDATE TABLE " + tableId + " SET VISIBILITY = UNLISTED"; return runUpdate(query); } @@ -275,7 +274,7 @@ public class SendToFusionTables implements Runnable { */ private boolean createNewPoint(String name, String description, Location location, String marker) { - Log.d(MyTracksConstants.TAG, "Creating a new row with a point."); + Log.d(Constants.TAG, "Creating a new row with a point."); String query = "INSERT INTO " + tableId + " (name,description,geometry,marker) VALUES " + values(name, description, getKmlPoint(location), marker); return runUpdate(query); @@ -288,7 +287,7 @@ public class SendToFusionTables implements Runnable { * @return true in case of success. */ private boolean createNewLineString(Track track) { - Log.d(MyTracksConstants.TAG, "Creating a new row with a point."); + Log.d(Constants.TAG, "Creating a new row with a point."); String query = "INSERT INTO " + tableId + " (name,description,geometry) VALUES " + values(track.getName(), track.getDescription(), getKmlLineString(track)); @@ -306,7 +305,7 @@ public class SendToFusionTables implements Runnable { Cursor locationsCursor = providerUtils.getLocationsCursor(track.getId(), 0, -1, false); try { if (!locationsCursor.moveToFirst()) { - Log.w(MyTracksConstants.TAG, "Unable to get any points to upload"); + Log.w(Constants.TAG, "Unable to get any points to upload"); return false; } @@ -319,14 +318,14 @@ public class SendToFusionTables implements Runnable { // Limit the number of elevation readings. Ideally we would want around 250. int elevationSamplingFrequency = Math.max(1, (int) (totalLocations / 250.0)); - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "Using elevation sampling factor: " + elevationSamplingFrequency + " on " + totalLocations); double totalDistance = 0; Vector distances = new Vector(); Vector elevations = new Vector(); - DoubleBuffer elevationBuffer = new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); + DoubleBuffer elevationBuffer = new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR); List locations = new ArrayList(MAX_POINTS_PER_UPLOAD); Location lastLocation = null; @@ -448,7 +447,7 @@ public class SendToFusionTables implements Runnable { int numLocations = locations.size(); if (numLocations < 2) { - Log.d(MyTracksConstants.TAG, "Not preparing/uploading too few points"); + Log.d(Constants.TAG, "Not preparing/uploading too few points"); totalLocationsUploaded += numLocations; return true; } @@ -464,16 +463,16 @@ public class SendToFusionTables implements Runnable { context.getString(R.string.part), totalSegmentsUploaded)); } totalSegmentsUploaded++; - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "SendToFusionTables: Prepared feature for upload w/ " + splitTrack.getLocations().size() + " points."); // Transmit tracks via GData feed: // ------------------------------- - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "SendToFusionTables: Uploading to table " + tableId + " w/ auth " + auth); if (!uploadTrackPoints(splitTrack)) { - Log.e(MyTracksConstants.TAG, "Uploading failed"); + Log.e(Constants.TAG, "Uploading failed"); return false; } } @@ -519,7 +518,7 @@ public class SendToFusionTables implements Runnable { // Close up the last segment. prepareTrackSegment(segment, splitTracks); - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "MyTracksSendToFusionTables: Starting new track segment..."); startNewTrackSegment = false; segment = new Track(); @@ -582,7 +581,7 @@ public class SendToFusionTables implements Runnable { int numLocations = splitTrack.getLocations().size(); if (numLocations < 2) { // Need at least two points for a polyline: - Log.w(MyTracksConstants.TAG, "Not uploading too few points"); + Log.w(Constants.TAG, "Not uploading too few points"); return true; } return createNewLineString(splitTrack); @@ -605,14 +604,14 @@ public class SendToFusionTables implements Runnable { try { c = providerUtils.getWaypointsCursor( track.getId(), 0, - MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS); + Constants.MAX_LOADED_WAYPOINTS_POINTS); if (c != null) { if (c.moveToFirst()) { // This will skip the 1st waypoint (it carries the stats for the // last segment). while (c.moveToNext()) { Waypoint wpt = providerUtils.createWaypoint(c); - Log.d(MyTracksConstants.TAG, "SendToFusionTables: Creating waypoint."); + Log.d(Constants.TAG, "SendToFusionTables: Creating waypoint."); success = createNewPoint(wpt.getName(), wpt.getDescription(), wpt.getLocation(), MARKER_TYPE_WAYPOINT); if (!success) { @@ -622,7 +621,7 @@ public class SendToFusionTables implements Runnable { } } if (!success) { - Log.w(MyTracksConstants.TAG, "SendToFusionTables: upload waypoints failed."); + Log.w(Constants.TAG, "SendToFusionTables: upload waypoints failed."); } return success; } finally { @@ -657,7 +656,7 @@ public class SendToFusionTables implements Runnable { wrapper.setAuthManager(auth); wrapper.setRetryOnAuthFailure(true); wrapper.setClient(transport); - Log.d(MyTracksConstants.TAG, "GData connection prepared: " + this.auth); + Log.d(Constants.TAG, "GData connection prepared: " + this.auth); wrapper.runQuery(new QueryFunction() { @Override public void query(HttpTransport client) @@ -672,7 +671,7 @@ public class SendToFusionTables implements Runnable { isc.inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql)); request.content = isc; - Log.d(MyTracksConstants.TAG, "Running update query " + url.toString() + ": " + sql); + Log.d(Constants.TAG, "Running update query " + url.toString() + ": " + sql); HttpResponse response; try { response = request.execute(); @@ -687,12 +686,12 @@ public class SendToFusionTables implements Runnable { String[] lines = s.split(Strings.LINE_SEPARATOR); if (lines[0].equals("tableid")) { tableId = lines[1]; - Log.d(MyTracksConstants.TAG, "tableId = " + tableId); + Log.d(Constants.TAG, "tableId = " + tableId); } else { - Log.w(MyTracksConstants.TAG, "Unrecognized response: " + lines[0]); + Log.w(Constants.TAG, "Unrecognized response: " + lines[0]); } } else { - Log.d(MyTracksConstants.TAG, "Query failed: " + response.statusMessage + " (" + + Log.d(Constants.TAG, "Query failed: " + response.statusMessage + " (" + response.statusCode + ")"); throw new GDataWrapper.HttpException(response.statusCode, response.statusMessage); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java b/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java index 542606426..4145f3a6f 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java @@ -15,14 +15,14 @@ */ package com.google.android.apps.mytracks.io; -import com.google.android.apps.mytracks.MyTracksConstants; +import static com.google.android.apps.mytracks.Constants.TAG; +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.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.Track; 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.WaypointData; import com.google.android.apps.mytracks.stats.DoubleBuffer; import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.util.MyTracksUtils; @@ -93,7 +93,7 @@ public class SendToMyMaps implements Runnable { @Override public void run() { - Log.d(MyTracksConstants.TAG, "Sending to MyMaps: trackId = " + trackId); + Log.d(TAG, "Sending to MyMaps: trackId = " + trackId); doUpload(); } @@ -111,7 +111,7 @@ public class SendToMyMaps implements Runnable { track.setDescription("

" + track.getDescription() + "

" + stringUtils.generateTrackDescription(track, null, null) + "

"); - mapsClient = MyMapsFactory.newMapsClient(context, auth); + mapsClient = new MapsFacade(context, auth); // Create a new map if necessary: boolean isNewMap = mapId.equals(NEW_MAP_ID); @@ -142,17 +142,16 @@ public class SendToMyMaps implements Runnable { if (success) { Cursor c = providerUtils.getWaypointsCursor( track.getId(), 0, - MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS); + Constants.MAX_LOADED_WAYPOINTS_POINTS); if (c != null) { try { if (c.getCount() > 1 && c.moveToFirst()) { // This will skip the 1st waypoint (it carries the stats for the // last segment). - ArrayList waypoints = new ArrayList(c.getCount() - 1); + ArrayList waypoints = new ArrayList(c.getCount() - 1); while (c.moveToNext()) { Waypoint wpt = providerUtils.createWaypoint(c); - waypoints.add(new WaypointData( - wpt.getName(), wpt.getDescription(), wpt.getIcon(), wpt.getLocation())); + waypoints.add(wpt); } success = mapsClient.uploadWaypoints(mapId, waypoints); @@ -165,8 +164,7 @@ public class SendToMyMaps implements Runnable { } if (!success) { - Log.w(MyTracksConstants.TAG, - "SendToMyMaps: upload waypoints failed."); + Log.w(TAG, "SendToMyMaps: upload waypoints failed."); } } @@ -175,7 +173,7 @@ public class SendToMyMaps implements Runnable { ? R.string.status_new_mymap_has_been_created : R.string.status_tracks_have_been_uploaded; } - Log.d(MyTracksConstants.TAG, "SendToMyMaps: Done: " + success); + Log.d(TAG, "SendToMyMaps: Done: " + success); progressIndicator.setProgressValue(100); } finally { if (mapsClient != null) { @@ -210,7 +208,7 @@ public class SendToMyMaps implements Runnable { providerUtils.getLocationsCursor(track.getId(), 0, -1, false); try { if (!locationsCursor.moveToFirst()) { - Log.w(MyTracksConstants.TAG, "Unable to get any points to upload"); + Log.w(TAG, "Unable to get any points to upload"); return false; } @@ -223,7 +221,7 @@ public class SendToMyMaps implements Runnable { // Limit the number of elevation readings. Ideally we would want around 250. int elevationSamplingFrequency = Math.max(1, (int) (totalLocations / 250.0)); - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "Using elevation sampling factor: " + elevationSamplingFrequency + " on " + totalLocations); double totalDistance = 0; @@ -231,7 +229,7 @@ public class SendToMyMaps implements Runnable { Vector distances = new Vector(); Vector elevations = new Vector(); DoubleBuffer elevationBuffer = - new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); + new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR); List locations = new ArrayList(MAX_POINTS_PER_UPLOAD); progressIndicator.setProgressMessage( @@ -312,7 +310,7 @@ public class SendToMyMaps implements Runnable { int numLocations = locations.size(); if (numLocations < 2) { - Log.d(MyTracksConstants.TAG, "Not preparing/uploading too few points"); + Log.d(TAG, "Not preparing/uploading too few points"); totalLocationsUploaded += numLocations; return true; } @@ -330,16 +328,16 @@ public class SendToMyMaps implements Runnable { context.getString(R.string.part), totalSegmentsUploaded)); } totalSegmentsUploaded++; - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "SendToMyMaps: Prepared feature for upload w/ " + splitTrack.getLocations().size() + " points."); // Transmit tracks via GData feed: // ------------------------------- - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "SendToMyMaps: Uploading to map " + mapId + " w/ auth " + auth); if (!mapsClient.uploadTrackPoints(mapId, splitTrack.getName(), splitTrack.getLocations())) { - Log.e(MyTracksConstants.TAG, "Uploading failed"); + Log.e(TAG, "Uploading failed"); return false; } } @@ -385,7 +383,7 @@ public class SendToMyMaps implements Runnable { // Close up the last segment. prepareTrackSegment(segment, splitTracks); - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "MyTracksSendToMyMaps: Starting new track segment..."); startNewTrackSegment = false; segment = new Track(); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/TcxTrackWriter.java b/MyTracks/src/com/google/android/apps/mytracks/io/TcxTrackWriter.java index dfd3513ad..cf965b4c6 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/TcxTrackWriter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/TcxTrackWriter.java @@ -1,12 +1,12 @@ /* * Copyright 2010 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 @@ -17,11 +17,13 @@ package com.google.android.apps.mytracks.io; import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.Sensor; +import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Waypoint; -import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat; +import com.google.android.apps.mytracks.util.MyTracksUtils; +import android.content.Context; import android.location.Location; import android.os.Build; @@ -30,6 +32,7 @@ import java.io.PrintWriter; import java.nio.charset.Charset; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import java.util.TimeZone; /** @@ -37,20 +40,35 @@ import java.util.TimeZone; * As defined by: * http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 * + * The TCX file written by this class has been verified as compatible with + * Garmin Training Center 3.5.3. + * * @author Sandor Dornbush */ public class TcxTrackWriter implements TrackFormatWriter { + protected static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + + // These are the only sports allowed by the TCX v2 specification for fields + // of type Sport_t. + private static final String TCX_SPORT_BIKING = "Biking"; + private static final String TCX_SPORT_RUNNING = "Running"; + private static final String TCX_SPORT_OTHER = "Other"; + + // Values for fields of type Build_t/Type. + private static final String TCX_TYPE_RELEASE = "Release"; + private static final String TCX_TYPE_INTERNAL = "Internal"; + + private final SimpleDateFormat timestampFormatter; + private final Context context; private PrintWriter pw = null; private Track track; - static final SimpleDateFormat TIMESTAMP_FORMAT = - new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - static { - TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); - } + public TcxTrackWriter(Context context) { + this.context = context; - public TcxTrackWriter() { + timestampFormatter = new SimpleDateFormat(TIMESTAMP_FORMAT); + timestampFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); } @Override @@ -93,16 +111,13 @@ public class TcxTrackWriter implements TrackFormatWriter { if (pw == null) { return; } + + String startTime = timestampFormatter.format(track.getStatistics().getStartTime()); + pw.println(" "); - pw.print(" "); - pw.print(" "); - pw.print(TIMESTAMP_FORMAT.format(track.getStatistics().getStartTime())); - pw.println(""); - pw.println(" "); + pw.format(" \n", categoryToTcxSport(track.getCategory())); + pw.format(" %s\n", startTime); + pw.format(" \n", startTime); pw.print(" "); pw.print(track.getStatistics().getTotalTime() / 1000); pw.println(""); @@ -113,7 +128,7 @@ public class TcxTrackWriter implements TrackFormatWriter { // Calories are a required element just put in 0. pw.print("0"); pw.println("Active"); - pw.println("Manual)"); + pw.println("Manual"); } @Override @@ -130,7 +145,7 @@ public class TcxTrackWriter implements TrackFormatWriter { } pw.println(" "); Date d = new Date(location.getTime()); - pw.println(" "); + pw.println(" "); pw.println(" "); pw.print(" "); @@ -194,10 +209,18 @@ public class TcxTrackWriter implements TrackFormatWriter { } pw.println(" "); pw.print(" "); - pw.print(""); - pw.print(Build.MODEL); - pw.print(""); - pw.println(")"); + pw.format("%s\n", Build.MODEL); + + // The following code is correct. ID is inconsistently capitalized in the + // TCX schema. + pw.println("0"); + pw.println("0"); + + pw.println(""); + pw.println("0"); + pw.println("0"); + pw.println(""); + pw.println(""); pw.println(" "); pw.println(" "); } @@ -207,8 +230,31 @@ public class TcxTrackWriter implements TrackFormatWriter { if (pw == null) { return; } - pw.print(" "); - pw.print("My Tracks by Google"); + pw.println(" "); + + // We put the version in the name because there isn't a better place for + // 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 either. + pw.format("My Tracks %s by Google\n", MyTracksUtils.getMyTracksVersion(context)); + + pw.println(""); + + // The TCX spec for the Version tag is too strict to allow us to use our + // user-visible version number, so we use our version code instead. We + // also set the minor version to 1 if this is a development build to + // signify that this build is newer than the one associated with the + // version code given in VersionMajor. + pw.println(""); + pw.format("%d\n", MyTracksUtils.getMyTracksVersion(context)); + pw.format("%d\n", MyTracksUtils.isRelease(context) ? 0 : 1); + pw.println(""); + + pw.format("%s\n", MyTracksUtils.isRelease(context) ? TCX_TYPE_RELEASE + : TCX_TYPE_INTERNAL); + pw.println(""); + pw.format("%s\n", Locale.getDefault().getLanguage()); + pw.println("000-00000-00"); pw.println(""); pw.println(""); } @@ -217,4 +263,15 @@ public class TcxTrackWriter implements TrackFormatWriter { public void writeWaypoint(Waypoint waypoint) { // TODO Write out the waypoints somewhere. } + + private String categoryToTcxSport(String category) { + category = category.trim(); + if (category.equalsIgnoreCase(TCX_SPORT_RUNNING)) { + return TCX_SPORT_RUNNING; + } else if (category.equalsIgnoreCase(TCX_SPORT_BIKING)) { + return TCX_SPORT_BIKING; + } else { + return TCX_SPORT_OTHER; + } + } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/TrackWriter.java b/MyTracks/src/com/google/android/apps/mytracks/io/TrackWriter.java index 26fb19f87..c18788572 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/TrackWriter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/TrackWriter.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.io; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.Track; @@ -160,16 +160,16 @@ public class TrackWriter { String fileName = fileUtils.buildUniqueFileName( directory, track.getName(), writer.getExtension()); if (fileName == null) { - Log.e(MyTracksConstants.TAG, + Log.e(Constants.TAG, "Unable to get a unique filename for " + fileName); return false; } - Log.i(MyTracksConstants.TAG, "Writing track to: " + fileName); + Log.i(Constants.TAG, "Writing track to: " + fileName); try { writer.prepare(track, newOutputStream(fileName)); } catch (FileNotFoundException e) { - Log.e(MyTracksConstants.TAG, "Failed to open output file.", e); + Log.e(Constants.TAG, "Failed to open output file.", e); errorMessage = R.string.io_write_failed; return false; } @@ -187,12 +187,12 @@ public class TrackWriter { } if (!fileUtils.isSdCardAvailable()) { - Log.i(MyTracksConstants.TAG, "Could not find SD card."); + Log.i(Constants.TAG, "Could not find SD card."); errorMessage = R.string.io_no_external_storage_found; return false; } if (!fileUtils.ensureDirectoryExists(directory)) { - Log.i(MyTracksConstants.TAG, "Could not create export directory."); + Log.i(Constants.TAG, "Could not create export directory."); errorMessage = R.string.io_create_dir_failed; return false; } @@ -230,7 +230,7 @@ public class TrackWriter { // same time. Cursor cursor = null; cursor = providerUtils.getWaypointsCursor(trackId, 0, - MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS); + Constants.MAX_LOADED_WAYPOINTS_POINTS); if (cursor != null) { try { if (cursor.moveToFirst()) { @@ -253,14 +253,14 @@ public class TrackWriter { * Does the actual work of writing the track to the now open file. */ void writeDocument() { - Log.d(MyTracksConstants.TAG, "Started writing track."); + Log.d(Constants.TAG, "Started writing track."); writer.writeHeader(); writeWaypoints(track.getId()); writeLocations(); writer.writeFooter(); writer.close(); success = true; - Log.d(MyTracksConstants.TAG, "Done writing track."); + Log.d(Constants.TAG, "Done writing track."); errorMessage = R.string.io_write_finished; } @@ -296,7 +296,7 @@ public class TrackWriter { locationFactory); try { if (!it.hasNext()) { - Log.w(MyTracksConstants.TAG, "Unable to get any points to write"); + Log.w(Constants.TAG, "Unable to get any points to write"); return; } while (it.hasNext()) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/TrackWriterFactory.java b/MyTracks/src/com/google/android/apps/mytracks/io/TrackWriterFactory.java index 55261f8a5..785454b0b 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/TrackWriterFactory.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/TrackWriterFactory.java @@ -1,12 +1,12 @@ /* * Copyright 2010 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 @@ -53,7 +53,7 @@ public class TrackWriterFactory { TCX { @Override public TrackFormatWriter newFormatWriter(Context context) { - return new TcxTrackWriter(); + return new TcxTrackWriter(context); } }; diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/backup/BackupActivityHelper.java b/MyTracks/src/com/google/android/apps/mytracks/io/backup/BackupActivityHelper.java index e66cd29d8..0de343479 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/backup/BackupActivityHelper.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/backup/BackupActivityHelper.java @@ -16,7 +16,7 @@ package com.google.android.apps.mytracks.io.backup; import com.google.android.apps.mytracks.MyTracks; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.maps.mytracks.R; @@ -97,7 +97,7 @@ public class BackupActivityHelper { backup.writeToDefaultFile(); showToast(R.string.io_write_finished); } catch (IOException e) { - Log.e(MyTracksConstants.TAG, "Failed to write backup", e); + Log.e(Constants.TAG, "Failed to write backup", e); showToast(R.string.io_write_failed); } finally { dismissDialog(progressDialog); @@ -199,7 +199,7 @@ public class BackupActivityHelper { backup.restoreFromDate(date); showToast(R.string.io_read_finished); } catch (IOException e) { - Log.e(MyTracksConstants.TAG, "Failed to restore backup", e); + Log.e(Constants.TAG, "Failed to restore backup", e); showToast(R.string.io_read_failed); } finally { dismissDialog(progressDialog); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/backup/ExternalFileBackup.java b/MyTracks/src/com/google/android/apps/mytracks/io/backup/ExternalFileBackup.java index cc346e2f7..cde8c1954 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/backup/ExternalFileBackup.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/backup/ExternalFileBackup.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.io.backup; -import com.google.android.apps.mytracks.MyTracksConstants; +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.TracksColumns; @@ -88,7 +88,7 @@ class ExternalFileBackup { private File getBackupsDirectory(boolean create) { String dirName = fileUtils.buildExternalDirectoryPath(BACKUPS_SUBDIR); final File dir = new File(dirName); - Log.d(MyTracksConstants.TAG, "Dir: " + dir.getAbsolutePath()); + Log.d(Constants.TAG, "Dir: " + dir.getAbsolutePath()); if (create) { // Try to create - if that fails, return null return fileUtils.ensureDirectoryExists(dir) ? dir : null; @@ -147,7 +147,7 @@ class ExternalFileBackup { * Synchronously writes a backup to the given file. */ private void writeToFile(File outputFile) throws IOException { - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "Writing backup to file " + outputFile.getAbsolutePath()); // Create all the auxiliary classes that will do the writing @@ -219,7 +219,7 @@ class ExternalFileBackup { * Synchronously restores the backup from the given file. */ private void restoreFromFile(File inputFile) throws IOException { - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "Restoring from file " + inputFile.getAbsolutePath()); PreferenceBackupHelper preferencesHelper = new PreferenceBackupHelper(); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/backup/MyTracksBackupAgent.java b/MyTracks/src/com/google/android/apps/mytracks/io/backup/MyTracksBackupAgent.java index f9bb2f352..729e0125f 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/backup/MyTracksBackupAgent.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/backup/MyTracksBackupAgent.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.io.backup; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.MyTracksSettings; import android.app.backup.BackupAgent; @@ -40,12 +40,12 @@ public class MyTracksBackupAgent extends BackupAgent { @Override public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException { - Log.i(MyTracksConstants.TAG, "Performing backup"); + Log.i(Constants.TAG, "Performing backup"); SharedPreferences preferences = this.getSharedPreferences( MyTracksSettings.SETTINGS_NAME, 0); backupPreferences(data, preferences); - Log.i(MyTracksConstants.TAG, "Backup complete"); + Log.i(Constants.TAG, "Backup complete"); } private void backupPreferences(BackupDataOutput data, @@ -63,18 +63,18 @@ public class MyTracksBackupAgent extends BackupAgent { @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { - Log.i(MyTracksConstants.TAG, "Restoring from backup"); + Log.i(Constants.TAG, "Restoring from backup"); while (data.readNextHeader()) { String key = data.getKey(); - Log.d(MyTracksConstants.TAG, "Restoring entity " + key); + Log.d(Constants.TAG, "Restoring entity " + key); if (key.equals(PREFERENCES_ENTITY)) { restorePreferences(data); } else { - Log.e(MyTracksConstants.TAG, "Found unknown backup entity: " + key); + Log.e(Constants.TAG, "Found unknown backup entity: " + key); data.skipEntityData(); } } - Log.i(MyTracksConstants.TAG, "Done restoring from backup"); + Log.i(Constants.TAG, "Done restoring from backup"); } /** diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/docs/DocsHelper.java b/MyTracks/src/com/google/android/apps/mytracks/io/docs/DocsHelper.java index e46a2573d..ce9752f39 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/docs/DocsHelper.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/docs/DocsHelper.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.io.docs; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.io.AuthManager; import com.google.android.apps.mytracks.io.gdata.GDataWrapper; @@ -144,7 +144,7 @@ public class DocsHelper { String id = result.substring( idStringStart + DOCS_SPREADSHEET_URL.length(), idTagCloseIndex); - Log.i(MyTracksConstants.TAG, "Created new spreadsheet: " + id); + Log.i(Constants.TAG, "Created new spreadsheet: " + id); idSaver.set(id); }}); @@ -184,7 +184,7 @@ public class DocsHelper { while (listParser.hasMoreData()) { Entry entry = listParser.readNextEntry(null); String entryTitle = entry.getTitle(); - Log.i(MyTracksConstants.TAG, "Found docs entry: " + entryTitle); + Log.i(Constants.TAG, "Found docs entry: " + entryTitle); if (entryTitle.equals(title)) { String entryId = entry.getId(); int lastSlash = entryId.lastIndexOf('/'); @@ -233,7 +233,7 @@ public class DocsHelper { trixWrapper.getAuthManager().getAuthToken()); sheetParser.init(); if (!sheetParser.hasMoreData()) { - Log.i(MyTracksConstants.TAG, "Found no worksheets"); + Log.i(Constants.TAG, "Found no worksheets"); return; } @@ -308,7 +308,7 @@ public class DocsHelper { if (track.getMapId().length() > 0) { tagBuilder.append("map", String.format("%s?msa=0&msid=%s", - MyTracksConstants.MAPSHOP_BASE_URL, track.getMapId())); + Constants.MAPSHOP_BASE_URL, track.getMapId())); } String postText = new StringBuilder() @@ -319,14 +319,14 @@ public class DocsHelper { .append("") .toString(); - Log.i(MyTracksConstants.TAG, + Log.i(Constants.TAG, "Inserting at: " + spreadsheetId + " => " + worksheetUri); - Log.i(MyTracksConstants.TAG, postText); + Log.i(Constants.TAG, postText); writeRowData(trixAuth, worksheetUri, postText); - Log.i(MyTracksConstants.TAG, "Post finished."); + Log.i(Constants.TAG, "Post finished."); } /** @@ -358,7 +358,7 @@ public class DocsHelper { String line; while ((line = rd.readLine()) != null) { // Process line. - Log.i(MyTracksConstants.TAG, "r: " + line); + Log.i(Constants.TAG, "r: " + line); } wr.close(); rd.close(); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/gdata/GDataClientFactory.java b/MyTracks/src/com/google/android/apps/mytracks/io/gdata/GDataClientFactory.java index 15dd588d0..a0a717bb1 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/gdata/GDataClientFactory.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/gdata/GDataClientFactory.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.io.gdata; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.wireless.gdata.client.GDataClient; import android.content.Context; @@ -43,7 +43,7 @@ public class GDataClientFactory { } catch (LinkageError e) { // On all other platforms use the client implementation packaged in the // apk. - Log.i(MyTracksConstants.TAG, "Using mytracks AndroidGDataClient.", e); + Log.i(Constants.TAG, "Using mytracks AndroidGDataClient.", e); return new com.google.android.apps.mytracks.io.gdata.AndroidGDataClient(); } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/gdata/GDataWrapper.java b/MyTracks/src/com/google/android/apps/mytracks/io/gdata/GDataWrapper.java index 75626c825..e26cbf947 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/gdata/GDataWrapper.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/gdata/GDataWrapper.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.io.gdata; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.io.AuthManager; import android.util.Log; @@ -173,14 +173,14 @@ public class GDataWrapper { return true; } - Log.d(MyTracksConstants.TAG, "GData error encountered: " + errorMessage); + Log.d(Constants.TAG, "GData error encountered: " + errorMessage); if (errorType == ERROR_AUTH && auth != null) { if (!retryOnAuthFailure || !invalidateAndRefreshAuthToken()) { return false; } } - Log.d(MyTracksConstants.TAG, "retrying function/query"); + Log.d(Constants.TAG, "retrying function/query"); } return false; } @@ -206,11 +206,11 @@ public class GDataWrapper { errorMessage = null; } catch (AuthenticationException e) { - Log.e(MyTracksConstants.TAG, "AuthenticationException", e); + Log.e(Constants.TAG, "AuthenticationException", e); errorType = ERROR_AUTH; errorMessage = e.getMessage(); } catch (HttpException e) { - Log.e(MyTracksConstants.TAG, + Log.e(Constants.TAG, "HttpException, code " + e.getStatusCode() + " message " + e.getMessage(), e); errorMessage = e.getMessage(); if (e.getStatusCode() == 401) { @@ -219,11 +219,11 @@ public class GDataWrapper { errorType = ERROR_CONNECTION; } } catch (FileNotFoundException e) { - Log.e(MyTracksConstants.TAG, "Exception", e); + Log.e(Constants.TAG, "Exception", e); errorType = ERROR_AUTH; errorMessage = e.getMessage(); } catch (IOException e) { - Log.e(MyTracksConstants.TAG, "Exception", e); + Log.e(Constants.TAG, "Exception", e); errorMessage = e.getMessage(); if (errorMessage != null && errorMessage.contains("503")) { errorType = ERROR_INTERNAL; @@ -231,11 +231,11 @@ public class GDataWrapper { errorType = ERROR_CONNECTION; } } catch (ParseException e) { - Log.e(MyTracksConstants.TAG, "Exception", e); + Log.e(Constants.TAG, "Exception", e); errorType = ERROR_LOCAL; errorMessage = e.getMessage(); } catch (ConflictDetectedException e) { - Log.e(MyTracksConstants.TAG, "Exception", e); + Log.e(Constants.TAG, "Exception", e); errorType = ERROR_CONFLICT; errorMessage = e.getMessage(); } @@ -249,7 +249,7 @@ public class GDataWrapper { * times out. */ private boolean invalidateAndRefreshAuthToken() { - Log.d(MyTracksConstants.TAG, "Retrying due to auth failure"); + Log.d(Constants.TAG, "Retrying due to auth failure"); // This FutureTask doesn't do anything -- it exists simply to be // blocked upon using get(). FutureTask whenFinishedFuture = new FutureTask(new Runnable() { @@ -259,18 +259,18 @@ public class GDataWrapper { auth.invalidateAndRefresh(whenFinishedFuture); try { - Log.d(MyTracksConstants.TAG, "waiting for invalidate"); + Log.d(Constants.TAG, "waiting for invalidate"); whenFinishedFuture.get(AUTH_TOKEN_INVALIDATE_REFRESH_TIMEOUT, TimeUnit.MILLISECONDS); - Log.d(MyTracksConstants.TAG, "invalidate finished"); + Log.d(Constants.TAG, "invalidate finished"); return true; } catch (InterruptedException e) { - Log.e(MyTracksConstants.TAG, "Failed to invalidate", e); + Log.e(Constants.TAG, "Failed to invalidate", e); } catch (ExecutionException e) { - Log.e(MyTracksConstants.TAG, "Failed to invalidate", e); + Log.e(Constants.TAG, "Failed to invalidate", e); } catch (TimeoutException e) { - Log.e(MyTracksConstants.TAG, "Invalidate didn't complete in time", e); + Log.e(Constants.TAG, "Invalidate didn't complete in time", e); } finally { whenFinishedFuture.cancel(false); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/GeoRect.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/GeoRect.java new file mode 100644 index 000000000..a990e95bc --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/GeoRect.java @@ -0,0 +1,50 @@ +// Copyright 2009 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +import com.google.android.maps.GeoPoint; + +/** + * A rectangle in geographical space. + */ +class GeoRect { + public int top; + public int left; + public int bottom; + public int right; + + public GeoRect() { + top = 0; + left = 0; + bottom = 0; + right = 0; + } + + public GeoRect(GeoPoint center, int latSpan, int longSpan) { + top = center.getLatitudeE6() - latSpan / 2; + left = center.getLongitudeE6() - longSpan / 2; + bottom = center.getLatitudeE6() + latSpan / 2; + right = center.getLongitudeE6() + longSpan / 2; + } + + public GeoPoint getCenter() { + return new GeoPoint(top / 2 + bottom / 2, left / 2 + right / 2); + } + + public int getLatSpan() { + return bottom - top; + } + + public int getLongSpan() { + return right - left; + } + + public boolean contains(GeoPoint geoPoint) { + if (geoPoint.getLatitudeE6() >= top + && geoPoint.getLatitudeE6() <= bottom + && geoPoint.getLongitudeE6() >= left + && geoPoint.getLongitudeE6() <= right) { + return true; + } + return false; + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapFeatureEntry.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapFeatureEntry.java new file mode 100644 index 000000000..e667c99b4 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapFeatureEntry.java @@ -0,0 +1,36 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +import com.google.wireless.gdata.data.Entry; + +import java.util.HashMap; +import java.util.Map; + +/** + * GData entry for a map feature. + */ +class MapFeatureEntry extends Entry { + + private String mPrivacy = null; + private Map mAttributes = new HashMap(); + + public void setPrivacy(String privacy) { + mPrivacy = privacy; + } + + public String getPrivacy() { + return mPrivacy; + } + + public void setAttribute(String name, String value) { + mAttributes.put(name, value); + } + + public void removeAttribute(String name) { + mAttributes.remove(name); + } + + public Map getAllAttributes() { + return mAttributes; + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsClient.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsClient.java new file mode 100644 index 000000000..7d1194b8c --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsClient.java @@ -0,0 +1,101 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +import com.google.wireless.gdata.client.GDataClient; +import com.google.wireless.gdata.client.GDataParserFactory; +import com.google.wireless.gdata.client.GDataServiceClient; + +import android.util.Log; + +/** + * Client to talk to Google Maps via GData. + */ +class MapsClient extends GDataServiceClient { + private static final boolean DEBUG = false; + public static final boolean LOG_COMMUNICATION = false; + + private static final String MAPS_BASE_FEED_URL = + "http://maps.google.com/maps/feeds/"; + private static final String MAPS_MAP_FEED_PATH = "maps/default/full"; + private static final String MAPS_FEATURE_FEED_PATH_BEFORE_MAPID = "features/"; + private static final String MAPS_FEATURE_FEED_PATH_AFTER_MAPID = "/full"; + private static final String MAPS_VERSION_FEED_PATH_FORMAT = + "%smaps/%s/versions/%s/full/%s"; + + private static final String MAP_ENTRY_ID_BEFORE_USER_ID = "maps/feeds/maps/"; + private static final String MAP_ENTRY_ID_BETWEEN_USER_ID_AND_MAP_ID = "/"; + private static final String V2_ONLY_PARAM = "?v=2.0"; + + public MapsClient(GDataClient dataClient, + GDataParserFactory dataParserFactory) { + super(dataClient, dataParserFactory); + } + + @Override + public String getServiceName() { + return MyMapsConstants.SERVICE_NAME; + } + + public static String buildMapUrl(String mapId) { + return MyMapsConstants.MAPSHOP_BASE_URL + "?msa=0&msid=" + mapId; + } + + public static String getMapsFeed() { + if (DEBUG) { + Log.d("Maps Client", "Requesting map feed:"); + } + return MAPS_BASE_FEED_URL + MAPS_MAP_FEED_PATH + V2_ONLY_PARAM; + } + + public static String getFeaturesFeed(String mapid) { + StringBuilder feed = new StringBuilder(); + feed.append(MAPS_BASE_FEED_URL); + feed.append(MAPS_FEATURE_FEED_PATH_BEFORE_MAPID); + feed.append(mapid); + feed.append(MAPS_FEATURE_FEED_PATH_AFTER_MAPID); + feed.append(V2_ONLY_PARAM); + return feed.toString(); + } + + public static String getMapIdFromMapEntryId(String entryId) { + String userId = null; + String mapId = null; + if (DEBUG) { + Log.d("Maps GData Client", "Getting mapid from entry id: " + entryId); + } + int userIdStart = + entryId.indexOf(MAP_ENTRY_ID_BEFORE_USER_ID) + + MAP_ENTRY_ID_BEFORE_USER_ID.length(); + int userIdEnd = + entryId.indexOf(MAP_ENTRY_ID_BETWEEN_USER_ID_AND_MAP_ID, userIdStart); + if (userIdStart >= 0 && userIdEnd < entryId.length() + && userIdStart <= userIdEnd) { + userId = entryId.substring(userIdStart, userIdEnd); + } + int mapIdStart = + entryId.indexOf(MAP_ENTRY_ID_BETWEEN_USER_ID_AND_MAP_ID, userIdEnd) + + MAP_ENTRY_ID_BETWEEN_USER_ID_AND_MAP_ID.length(); + if (mapIdStart >= 0 && mapIdStart < entryId.length()) { + mapId = entryId.substring(mapIdStart); + } + if (userId == null) { + userId = ""; + } + if (mapId == null) { + mapId = ""; + } + if (DEBUG) { + Log.d("Maps GData Client", "Got user id: " + userId); + Log.d("Maps GData Client", "Got map id: " + mapId); + } + return userId + "." + mapId; + } + + public static String getVersionFeed(String versionUserId, + String versionClient, String currentVersion) { + return String.format(MAPS_VERSION_FEED_PATH_FORMAT, + MAPS_BASE_FEED_URL, versionUserId, + versionClient, currentVersion); + } + +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsFacade.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsFacade.java new file mode 100644 index 000000000..86a92ec5c --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsFacade.java @@ -0,0 +1,372 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +import com.google.android.apps.mytracks.content.Waypoint; +import com.google.android.apps.mytracks.io.AuthManager; +import com.google.android.maps.GeoPoint; +import com.google.android.maps.mytracks.R; +import com.google.wireless.gdata.client.HttpException; +import com.google.wireless.gdata.data.Entry; +import com.google.wireless.gdata.parser.GDataParser; +import com.google.wireless.gdata.parser.ParseException; + +import android.content.Context; +import android.location.Location; +import android.text.TextUtils; +import android.util.Log; + +import java.io.IOException; +import java.util.Collection; + +import org.xmlpull.v1.XmlPullParserException; + +/** + * Single interface which abstracts all access to the Google Maps service. + * + * @author Rodrigo Damazio + */ +public class MapsFacade { + + /** + * Interface for receiving data back from getMapsList. + * All calls to the interface will happen before getMapsList returns. + */ + public interface MapsListCallback { + void onReceivedMapListing(String mapId, String title, String description, + boolean isPublic); + } + + private static final String END_ICON_URL = + "http://maps.google.com/mapfiles/ms/micons/red-dot.png"; + private static final String START_ICON_URL = + "http://maps.google.com/mapfiles/ms/micons/green-dot.png"; + + private final Context context; + private final MyMapsGDataWrapper wrapper; + private final MyMapsGDataConverter gdataConverter; + private final String authToken; + + public MapsFacade(Context context, AuthManager auth) { + this.context = context; + this.authToken = auth.getAuthToken(); + + wrapper = new MyMapsGDataWrapper(context, auth); + wrapper.setRetryOnAuthFailure(true); + + try { + gdataConverter = new MyMapsGDataConverter(); + } catch (XmlPullParserException e) { + throw new IllegalStateException("Unable to create maps data converter", e); + } + } + + public static String buildMapUrl(String mapId) { + return MapsClient.buildMapUrl(mapId); + } + + /** + * Returns a list of all maps for the current user. + * + * @param callback callback to call for each map returned + * @return true on success, false otherwise + */ + public boolean getMapsList(final MapsListCallback callback) { + return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() { + @Override + public void query(MapsClient client) throws IOException, Exception { + GDataParser listParser = client.getParserForFeed( + MapFeatureEntry.class, MapsClient.getMapsFeed(), authToken); + listParser.init(); + while (listParser.hasMoreData()) { + MapFeatureEntry entry = + (MapFeatureEntry) listParser.readNextEntry(null); + MyMapsMapMetadata metadata = + MyMapsGDataConverter.getMapMetadataForEntry(entry); + String mapId = MyMapsGDataConverter.getMapidForEntry(entry); + + callback.onReceivedMapListing( + mapId, metadata.getTitle(), metadata.getDescription(), metadata.getSearchable()); + } + listParser.close(); + listParser = null; + } + }); + } + + /** + * Creates a new map for the current user. + * + * @param title title of the map + * @param category category of the map + * @param description description for the map + * @param isPublic whether the map should be public + * @param mapIdBuilder builder to append the map ID to + * @return true on success, false otherwise + */ + public boolean createNewMap( + final String title, final String category, final String description, + final boolean isPublic, final StringBuilder mapIdBuilder) { + if (mapIdBuilder.length() > 0) { + throw new IllegalArgumentException("mapIdBuilder should be empty"); + } + + return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() { + @Override + public void query(MapsClient client) throws IOException, Exception { + Log.d(MyMapsConstants.TAG, "Creating a new map."); + String mapFeed = MapsClient.getMapsFeed(); + Log.d(MyMapsConstants.TAG, "Map feed is " + mapFeed); + MyMapsMapMetadata metaData = new MyMapsMapMetadata(); + metaData.setTitle(title); + metaData.setDescription(description + " - " + + category + " - " + context.getString(R.string.new_map_description)); + metaData.setSearchable(isPublic); + Entry entry = MyMapsGDataConverter.getMapEntryForMetadata(metaData); + Log.d(MyMapsConstants.TAG, "Title: " + entry.getTitle()); + Entry map = client.createEntry(mapFeed, authToken, entry); + + String mapId = MapsClient.getMapIdFromMapEntryId(map.getId()); + mapIdBuilder.append(mapId); + Log.d(MyMapsConstants.TAG, "New map id is: " + mapId); + } + }); + } + + /** + * Uploads a single start or end marker to the given map. + * + * @param mapId ID of the map to upload to + * @param trackName name of the track being started/ended + * @param trackDescription description of the track being started/ended + * @param location the location of the marker + * @param isStart true to add a start marker, false to add an end marker + * @return true on success, false otherwise + */ + public boolean uploadMarker(final String mapId, final String trackName, + final String trackDescription, final Location loc, final boolean isStart) { + return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() { + @Override + public void query(MapsClient client) + throws IOException, Exception { + String featureFeed = MapsClient.getFeaturesFeed(mapId); + GeoPoint geoPoint = getGeoPoint(loc); + insertMarker(client, featureFeed, trackName, trackDescription, geoPoint, isStart); + } + }); + } + + /** + * Inserts a place mark. Second try if 1st try fails. Will throw exception on + * 2nd failure. + */ + private void insertMarker(MapsClient client, + String featureFeed, + String trackName, String trackDescription, + GeoPoint geoPoint, + boolean isStart) throws IOException, Exception { + MyMapsFeature feature = + buildMyMapsPlacemarkFeature(trackName, trackDescription, geoPoint, isStart); + Entry entry = gdataConverter.getEntryForFeature(feature); + Log.d(MyMapsConstants.TAG, "SendToMyMaps: Creating placemark " + + entry.getTitle()); + try { + client.createEntry(featureFeed, authToken, entry); + Log.d(MyMapsConstants.TAG, "SendToMyMaps: createEntry success!"); + } catch (IOException e) { + Log.w(MyMapsConstants.TAG, + "SendToMyMaps: createEntry 1st try failed. Trying again."); + // Retry once (often IOException is thrown on a timeout): + client.createEntry(featureFeed, authToken, entry); + Log.d(MyMapsConstants.TAG, + "SendToMyMaps: createEntry success on 2nd try!"); + } + } + + /** + * Builds a placemark MyMapsFeature from a track. + * + * @param track the track + * @param isStart true if it's the start of the track, or false for end + * @return a MyMapsFeature + */ + private MyMapsFeature buildMyMapsPlacemarkFeature( + String trackName, String trackDescription, + GeoPoint geoPoint, boolean isStart) { + String iconUrl; + if (isStart) { + iconUrl = START_ICON_URL; + } else { + iconUrl = END_ICON_URL; + } + String title = trackName + " " + + (isStart ? context.getString(R.string.start) + : context.getString(R.string.end)); + String description = isStart ? "" : trackDescription; + return buildMyMapsPlacemarkFeature(title, description, iconUrl, geoPoint); + } + + /** + * Builds a MyMapsFeature from a track. + * + * @param wpt the waypoint + * @return a MyMapsFeature + */ + private static MyMapsFeature buildMyMapsPlacemarkFeature( + String title, String description, String iconUrl, GeoPoint geoPoint) { + MyMapsFeature myMapsFeature = new MyMapsFeature(); + myMapsFeature.generateAndroidId(); + myMapsFeature.setType(MyMapsFeature.MARKER); + myMapsFeature.setIconUrl(iconUrl); + myMapsFeature.setDescription(description); + myMapsFeature.addPoint(geoPoint); + if (TextUtils.isEmpty(title)) { + // Features must have a name (otherwise GData upload may fail): + myMapsFeature.setTitle("-"); + } else { + myMapsFeature.setTitle(title); + } + myMapsFeature.setDescription(description.replaceAll("\n", "
")); + return myMapsFeature; + } + + /** + * Uploads a series of waypoints to the given map. + * + * @param mapId ID of the map to upload to + * @param waypoints the waypoints to upload + * @return true on success, false otherwise + */ + public boolean uploadWaypoints( + final String mapId, final Iterable waypoints) { + return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() { + public void query(MapsClient client) { + // TODO(rdamazio): Stream through the waypoints in chunks. + // I am leaving the number of waypoints very high which should not be a + // problem because we don't try to load them into objects all at the + // same time. + String featureFeed = MapsClient.getFeaturesFeed(mapId); + + try { + for (Waypoint waypoint : waypoints) { + MyMapsFeature feature = buildMyMapsPlacemarkFeature( + waypoint.getName(), waypoint.getDescription(), waypoint.getIcon(), + getGeoPoint(waypoint.getLocation())); + Entry entry = gdataConverter.getEntryForFeature(feature); + + Log.d(MyMapsConstants.TAG, + "SendToMyMaps: Creating waypoint."); + try { + client.createEntry(featureFeed, authToken, entry); + Log.d(MyMapsConstants.TAG, + "SendToMyMaps: createEntry success!"); + } catch (IOException e) { + Log.w(MyMapsConstants.TAG, + "SendToMyMaps: createEntry 1st try failed. Retrying."); + + // Retry once (often IOException is thrown on a timeout): + client.createEntry(featureFeed, authToken, entry); + Log.d(MyMapsConstants.TAG, + "SendToMyMaps: createEntry success on 2nd try!"); + } + } + } catch (ParseException e) { + Log.w(MyMapsConstants.TAG, "ParseException caught.", e); + } catch (HttpException e) { + Log.w(MyMapsConstants.TAG, "HttpException caught.", e); + } catch (IOException e) { + Log.w(MyMapsConstants.TAG, "IOException caught.", e); + } + } + }); + } + + /** + * Uploads a series of points to the given map. + * + * @param mapId ID of the map to upload to + * @param trackName the name of the track + * @param locations the locations to upload + * @return true on success, false otherwise + */ + public boolean uploadTrackPoints( + final String mapId, final String trackName, final Collection locations) { + return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() { + @Override + public void query(MapsClient client) + throws IOException, Exception { + String featureFeed = MapsClient.getFeaturesFeed(mapId); + Log.d(MyMapsConstants.TAG, "Feature feed url: " + featureFeed); + uploadTrackPoints(client, featureFeed, trackName, locations); + } + }); + } + + private boolean uploadTrackPoints( + MapsClient client, + String featureFeed, + String trackName, Collection locations) + throws IOException, Exception { + Entry entry = null; + int numLocations = locations.size(); + if (numLocations < 2) { + // Need at least two points for a polyline: + Log.w(MyMapsConstants.TAG, "Not uploading too few points"); + return true; + } + + // Put the line: + entry = gdataConverter.getEntryForFeature( + buildMyMapsLineFeature(trackName, locations)); + Log.d(MyMapsConstants.TAG, + "SendToMyMaps: Creating line " + entry.getTitle()); + try { + client.createEntry(featureFeed, authToken, entry); + Log.d(MyMapsConstants.TAG, "SendToMyMaps: createEntry success!"); + } catch (IOException e) { + Log.w(MyMapsConstants.TAG, + "SendToMyMaps: createEntry 1st try failed. Trying again."); + // Retry once (often IOException is thrown on a timeout): + client.createEntry(featureFeed, authToken, entry); + Log.d(MyMapsConstants.TAG, + "SendToMyMaps: createEntry success on 2nd try!"); + } + return true; + } + + /** + * Builds a MyMapsFeature from a track. + * + * @param track the track + * @return a MyMapsFeature + */ + private static MyMapsFeature buildMyMapsLineFeature(String trackName, + Iterable locations) { + MyMapsFeature myMapsFeature = new MyMapsFeature(); + myMapsFeature.generateAndroidId(); + myMapsFeature.setType(MyMapsFeature.LINE); + if (TextUtils.isEmpty(trackName)) { + // Features must have a name (otherwise GData upload may fail): + myMapsFeature.setTitle("-"); + } else { + myMapsFeature.setTitle(trackName); + } + myMapsFeature.setColor(0x80FF0000); + for (Location loc : locations) { + myMapsFeature.addPoint(getGeoPoint(loc)); + } + return myMapsFeature; + } + + /** + * Cleans up after a series of uploads. + * This closes the connection to Maps and resets retry counters. + */ + public void cleanUp() { + wrapper.cleanUp(); + } + + private static GeoPoint getGeoPoint(Location location) { + return new GeoPoint((int) (location.getLatitude() * 1E6), + (int) (location.getLongitude() * 1E6)); + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsConstants.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsConstants.java new file mode 100644 index 000000000..77cb3a330 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsConstants.java @@ -0,0 +1,17 @@ +// Copyright 2009 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +/** + * Constants for My Maps. + */ +public class MyMapsConstants { + static final String TAG = "MapsApi"; + static final String MAPSHOP_BASE_URL = + "http://maps.google.com/maps/ms"; + public static final String SERVICE_NAME = "local"; + + /** + * Private constructor to prevent instantiation. + */ + private MyMapsConstants() { } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsFeature.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsFeature.java new file mode 100644 index 000000000..2cd24d641 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsFeature.java @@ -0,0 +1,233 @@ +// Copyright 2009 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +import com.google.android.maps.GeoPoint; + +import java.io.Serializable; +import java.util.Vector; + +/** + * MyMapsFeature contains all of the data associated with a feature in My Maps, + * where a feature is a marker, line, or shape. Some of the data is stored in a + * {@link MyMapsFeatureMetadata} object so that it can be more efficiently + * transmitted to other activities. + */ +class MyMapsFeature implements Serializable { + + private static final long serialVersionUID = 8439035544430497236L; + + /** A marker feature displays an icon at a single point on the map. */ + public static final int MARKER = 0; + + /** + * A line feature displays a line connecting a set of points on the map. + */ + public static final int LINE = 1; + + /** + * A shape feature displays a border defined by connecting a set of points, + * including connecting the last to the first, and displays the area + * confined by this border. + */ + public static final int SHAPE = 2; + + /** The local feature id for this feature, if needed. */ + private String androidId; + + /** + * The latitudes of the points of this feature in order, specified in + * millionths of a degree north. + */ + private final Vector latitudeE6 = new Vector(); + + /** + * The longitudes of the points of this feature in order, specified in + * millionths of a degree east. + */ + private final Vector longitudeE6 = new Vector(); + + /** The metadata of this feature in a format efficient for transmission. */ + private MyMapsFeatureMetadata featureInfo = new MyMapsFeatureMetadata(); + + /** + * Initializes a valid but empty feature. It will default to a + * {@link #MARKER} with a blue placemark with a dot as an icon at the + * location (0, 0). + */ + public MyMapsFeature() { + } + + /** + * Adds a new point to the end of this feature. + * + * @param point The new point to add + */ + public synchronized void addPoint(GeoPoint point) { + latitudeE6.add(point.getLatitudeE6()); + longitudeE6.add(point.getLongitudeE6()); + } + + /** + * Generates a new local id for this feature based on the current time and + * a random number. + */ + public synchronized void generateAndroidId() { + Long time = System.currentTimeMillis(); + Integer random = (int) (Math.random() * 10000); + androidId = time.toString() + "." + random.toString(); + } + + /** + * Retrieves the current local id for this feature if one is available. + * + * @return The local id for this feature + */ + public String getAndroidId() { + return androidId; + } + + /** + * Retrieves the current (html) description of this feature. The description + * is stored in the feature metadata. + * + * @return The description of this feature + */ + public String getDescription() { + return featureInfo.getDescription(); + } + + /** + * Sets the description of this feature. That description is stored in the + * feature metadata. + * + * @param description The new description of this feature + */ + public synchronized void setDescription(String description) { + featureInfo.setDescription(description); + } + + /** + * Retrieves the point at the given index for this feature. + * + * @param index The index of the point desired + * @return A {@link GeoPoint} representing the point or null if that point + * doesn't exist + */ + public GeoPoint getPoint(int index) { + if (latitudeE6.size() <= index) { + return null; + } + return new GeoPoint(latitudeE6.get(index), longitudeE6.get(index)); + } + + /** + * Counts the number of points in this feature and return that count. + * + * @return The number of points in this feature + */ + public int getPointCount() { + return latitudeE6.size(); + } + + /** + * Retrieves the title of this feature. That title is stored in the feature + * metadata. + * + * @return the current title of this feature + */ + public String getTitle() { + return featureInfo.getTitle(); + } + + /** + * Retrieves the type of this feature. That type is stored in the feature + * metadata. + * + * @return One of {@link #MARKER}, {@link #LINE}, or {@link #SHAPE} + * identifying the type of this feature + */ + public int getType() { + return featureInfo.getType(); + } + + /** + * Retrieves the current color of this feature as an ARGB color integer. + * That color is stored in the feature metadata. + * + * @return The ARGB color of this feature + */ + public int getColor() { + return featureInfo.getColor(); + } + + /** + * Retrieves the current line width of this feature. That line width is + * stored in the feature metadata. + * + * @return The line width of this feature + */ + public int getLineWidth() { + return featureInfo.getLineWidth(); + } + + /** + * Retrieves the current fill color of this feature as an ARGB color + * integer. That color is stored in the feature metadata. + * + * @return The ARGB fill color of this feature + */ + public int getFillColor() { + return featureInfo.getFillColor(); + } + + /** + * Retrieves the current icon url of this feature. That icon url is stored + * in the feature metadata. + * + * @return The icon url for this feature + */ + public String getIconUrl() { + return featureInfo.getIconUrl(); + } + + /** + * Sets the title of this feature. That title is stored in the feature + * metadata. + * + * @param title The new title of this feature + */ + public synchronized void setTitle(String title) { + featureInfo.setTitle(title); + } + + /** + * Sets the type of this feature. That type is stored in the feature + * metadata. + * + * @param type The new type of the feature. That type must be one of + * {@link #MARKER}, {@link #LINE}, or {@link #SHAPE} + */ + public synchronized void setType(int type) { + featureInfo.setType(type); + } + + /** + * Sets the ARGB color of this feature. That color is stored in the feature + * metadata. + * + * @param color The new ARGB color of this feature + */ + public synchronized void setColor(int color) { + featureInfo.setColor(color); + } + + /** + * Sets the icon url of this feature. That icon url is stored in the feature + * metadata. + * + * @param url The new icon url of the feature + */ + public synchronized void setIconUrl(String url) { + featureInfo.setIconUrl(url); + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsFeatureMetadata.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsFeatureMetadata.java new file mode 100644 index 000000000..7e94d24b9 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsFeatureMetadata.java @@ -0,0 +1,87 @@ +// Copyright 2009 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +/** + * Metadata about a maps feature. + */ +class MyMapsFeatureMetadata { + + private static final String BLUE_DOT_URL = + "http://maps.google.com/mapfiles/ms/micons/blue-dot.png"; + private static final int DEFAULT_COLOR = 0x800000FF; + private static final int DEFAULT_FILL_COLOR = 0xC00000FF; + + private String title; + private String description; + private int type; + private int color; + private int lineWidth; + private int fillColor; + private String iconUrl; + + public MyMapsFeatureMetadata() { + title = ""; + description = ""; + type = MyMapsFeature.MARKER; + color = DEFAULT_COLOR; + lineWidth = 5; + fillColor = DEFAULT_FILL_COLOR; + iconUrl = BLUE_DOT_URL; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public int getColor() { + return color; + } + + public void setColor(int color) { + this.color = color; + } + + public int getLineWidth() { + return lineWidth; + } + + public void setLineWidth(int width) { + lineWidth = width; + } + + public int getFillColor() { + return fillColor; + } + + public void setFillColor(int color) { + fillColor = color; + } + + public String getIconUrl() { + return iconUrl; + } + + public void setIconUrl(String url) { + iconUrl = new String(url); + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsGDataConverter.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsGDataConverter.java new file mode 100644 index 000000000..f2d7bad7e --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsGDataConverter.java @@ -0,0 +1,183 @@ +// Copyright 2009 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +import com.google.wireless.gdata.data.Entry; +import com.google.wireless.gdata.data.StringUtils; + +import android.graphics.Color; +import android.util.Log; + +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.io.StringWriter; + +/** + * Converter from GData objects to MyMaps objects. + */ +class MyMapsGDataConverter { + + private final XmlSerializer xmlSerializer; + + public MyMapsGDataConverter() throws XmlPullParserException { + xmlSerializer = XmlPullParserFactory.newInstance().newSerializer(); + } + + public static MyMapsMapMetadata getMapMetadataForEntry( + MapFeatureEntry entry) { + MyMapsMapMetadata metadata = new MyMapsMapMetadata(); + if ("public".equals(entry.getPrivacy())) { + metadata.setSearchable(true); + } else { + metadata.setSearchable(false); + } + metadata.setTitle(entry.getTitle()); + + String desc = entry.getContent(); + if (desc.length() > 12) { + metadata.setDescription(desc.substring(9, desc.length() - 3)); + } + + String editUri = entry.getEditUri(); + if (editUri != null) { + metadata.setGDataEditUri(editUri); + } + + return metadata; + } + + public static String getMapidForEntry(Entry entry) { + return MapsClient.getMapIdFromMapEntryId(entry.getId()); + } + + public static Entry getMapEntryForMetadata(MyMapsMapMetadata metadata) { + MapFeatureEntry entry = new MapFeatureEntry(); + entry.setEditUri(metadata.getGDataEditUri()); + entry.setTitle(metadata.getTitle()); + entry.setContent(metadata.getDescription()); + entry.setPrivacy(metadata.getSearchable() ? "public" : "unlisted"); + entry.setAuthor("android"); + entry.setEmail("nobody@google.com"); + return entry; + } + + public MapFeatureEntry getEntryForFeature(MyMapsFeature feature) { + MapFeatureEntry entry = new MapFeatureEntry(); + entry.setTitle(feature.getTitle()); + entry.setAuthor("android"); + entry.setEmail("nobody@google.com"); + entry.setCategoryScheme("http://schemas.google.com/g/2005#kind"); + entry.setCategory("http://schemas.google.com/g/2008#mapfeature"); + entry.setEditUri(""); + if (!StringUtils.isEmpty(feature.getAndroidId())) { + entry.setAttribute("_androidId", feature.getAndroidId()); + } + try { + StringWriter writer = new StringWriter(); + xmlSerializer.setOutput(writer); + xmlSerializer.startTag(null, "Placemark"); + xmlSerializer.attribute(null, "xmlns", "http://earth.google.com/kml/2.2"); + xmlSerializer.startTag(null, "Style"); + if (feature.getType() == MyMapsFeature.MARKER) { + xmlSerializer.startTag(null, "IconStyle"); + xmlSerializer.startTag(null, "Icon"); + xmlSerializer.startTag(null, "href"); + xmlSerializer.text(feature.getIconUrl()); + xmlSerializer.endTag(null, "href"); + xmlSerializer.endTag(null, "Icon"); + xmlSerializer.endTag(null, "IconStyle"); + } else { + xmlSerializer.startTag(null, "LineStyle"); + xmlSerializer.startTag(null, "color"); + int color = feature.getColor(); + // Reverse the color because KML is ABGR and Android is ARGB + xmlSerializer.text(Integer.toHexString( + Color.argb(Color.alpha(color), Color.blue(color), + Color.green(color), Color.red(color)))); + xmlSerializer.endTag(null, "color"); + xmlSerializer.startTag(null, "width"); + xmlSerializer.text(Integer.toString(feature.getLineWidth())); + xmlSerializer.endTag(null, "width"); + xmlSerializer.endTag(null, "LineStyle"); + + if (feature.getType() == MyMapsFeature.SHAPE) { + xmlSerializer.startTag(null, "PolyStyle"); + xmlSerializer.startTag(null, "color"); + int fcolor = feature.getFillColor(); + // Reverse the color because KML is ABGR and Android is ARGB + xmlSerializer.text(Integer.toHexString(Color.argb(Color.alpha(fcolor), + Color.blue(fcolor), Color.green(fcolor), Color.red(fcolor)))); + xmlSerializer.endTag(null, "color"); + xmlSerializer.startTag(null, "fill"); + xmlSerializer.text("1"); + xmlSerializer.endTag(null, "fill"); + xmlSerializer.startTag(null, "outline"); + xmlSerializer.text("1"); + xmlSerializer.endTag(null, "outline"); + xmlSerializer.endTag(null, "PolyStyle"); + } + } + xmlSerializer.endTag(null, "Style"); + xmlSerializer.startTag(null, "name"); + xmlSerializer.text(feature.getTitle()); + xmlSerializer.endTag(null, "name"); + xmlSerializer.startTag(null, "description"); + xmlSerializer.cdsect(feature.getDescription()); + xmlSerializer.endTag(null, "description"); + StringBuilder pointBuilder = new StringBuilder(); + for (int i = 0; i < feature.getPointCount(); ++i) { + if (i > 0) { + pointBuilder.append('\n'); + } + pointBuilder.append(feature.getPoint(i).getLongitudeE6() / 1e6); + pointBuilder.append(','); + pointBuilder.append(feature.getPoint(i).getLatitudeE6() / 1e6); + pointBuilder.append(",0.000000"); + } + String pointString = pointBuilder.toString(); + if (feature.getType() == MyMapsFeature.MARKER) { + xmlSerializer.startTag(null, "Point"); + xmlSerializer.startTag(null, "coordinates"); + xmlSerializer.text(pointString); + xmlSerializer.endTag(null, "coordinates"); + xmlSerializer.endTag(null, "Point"); + } else if (feature.getType() == MyMapsFeature.LINE) { + xmlSerializer.startTag(null, "LineString"); + xmlSerializer.startTag(null, "tessellate"); + xmlSerializer.text("1"); + xmlSerializer.endTag(null, "tessellate"); + xmlSerializer.startTag(null, "coordinates"); + xmlSerializer.text(pointString); + xmlSerializer.endTag(null, "coordinates"); + xmlSerializer.endTag(null, "LineString"); + } else { + xmlSerializer.startTag(null, "Polygon"); + xmlSerializer.startTag(null, "outerBoundaryIs"); + xmlSerializer.startTag(null, "LinearRing"); + xmlSerializer.startTag(null, "tessellate"); + xmlSerializer.text("1"); + xmlSerializer.endTag(null, "tessellate"); + xmlSerializer.startTag(null, "coordinates"); + xmlSerializer.text(pointString + "\n" + + Double.toString(feature.getPoint(0).getLongitudeE6() / 1e6) + + "," + + Double.toString(feature.getPoint(0).getLatitudeE6() / 1e6) + + ",0.000000"); + xmlSerializer.endTag(null, "coordinates"); + xmlSerializer.endTag(null, "LinearRing"); + xmlSerializer.endTag(null, "outerBoundaryIs"); + xmlSerializer.endTag(null, "Polygon"); + } + xmlSerializer.endTag(null, "Placemark"); + xmlSerializer.flush(); + entry.setContent(writer.toString()); + Log.d("My Google Maps", "Generated kml:\n" + entry.getContent()); + Log.d("My Google Maps", "Edit URI: " + entry.getEditUri()); + } catch (IOException e) { + e.printStackTrace(); + } + return entry; + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsGDataWrapper.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsGDataWrapper.java new file mode 100644 index 000000000..3e5cb9c3f --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsGDataWrapper.java @@ -0,0 +1,169 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +import com.google.android.apps.mytracks.io.AuthManager; +import com.google.android.apps.mytracks.io.gdata.GDataClientFactory; +import com.google.android.common.gdata.AndroidXmlParserFactory; +import com.google.wireless.gdata.client.GDataClient; +import com.google.wireless.gdata.client.HttpException; +import com.google.wireless.gdata.parser.xml.SimplePullParser.ParseException; +import com.google.wireless.gdata2.ConflictDetectedException; +import com.google.wireless.gdata2.client.AuthenticationException; + +import android.content.Context; +import android.util.Log; + +import java.io.IOException; + +/** + * MyMapsGDataWrapper provides a wrapper around GData operations that maintains + * the GData client, and provides a method to run gdata queries with proper + * error handling. After a query is run, the wrapper can be queried about the + * error that occurred. + */ +class MyMapsGDataWrapper { + /** + * A QueryFunction is passed in when executing a query. The query function + * of the class is called with the GData client as a parameter. The + * function should execute whatever operations it desires on the client + * without concern for whether the client will throw an error. + */ + interface QueryFunction { + public abstract void query(MapsClient client) + throws AuthenticationException, IOException, ParseException, + ConflictDetectedException, Exception; + } + + // The types of error that may be encountered + /** No error occurred. */ + public static final int ERROR_NO_ERROR = 0; + /** There was an authentication error, the auth token may be invalid. */ + public static final int ERROR_AUTH = 1; + /** There was an internal error on the server side. */ + public static final int ERROR_INTERNAL = 2; + /** There was an error connecting to the server. */ + public static final int ERROR_CONNECTION = 3; + /** The item queried did not exit. */ + public static final int ERROR_NOT_FOUND = 4; + /** There was an error parsing or serializing locally. */ + public static final int ERROR_LOCAL = 5; + /** There was a conflict, update the entry and try again. */ + public static final int ERROR_CONFLICT = 6; + /** + * A query was run after cleaning up the wrapper, so the client was invalid. + */ + public static final int ERROR_CLEANED_UP = 7; + /** An unknown error occurred. */ + public static final int ERROR_UNKNOWN = 100; + + private final GDataClient androidGdataClient; + private final AuthManager auth; + private final MapsClient client; + + private String errorMessage; + private int errorType; + private boolean retryOnAuthFailure; + private int retriesPending; + private boolean cleanupCalled; + + public MyMapsGDataWrapper(Context context, AuthManager auth) { + androidGdataClient = GDataClientFactory.getGDataClient(context); + this.auth = auth; + client = + new MapsClient(androidGdataClient, new XmlMapsGDataParserFactory( + new AndroidXmlParserFactory())); + errorType = ERROR_NO_ERROR; + errorMessage = null; + retryOnAuthFailure = false; + retriesPending = 0; + cleanupCalled = false; + } + + public boolean runQuery(final QueryFunction query) { + if (client == null) { + errorType = ERROR_CLEANED_UP; + errorMessage = "GData Wrapper has already been cleaned up!"; + return false; + } + try { + query.query(client); + errorType = ERROR_NO_ERROR; + errorMessage = null; + return true; + } catch (AuthenticationException e) { + Log.e(MyMapsConstants.TAG, "Exception", e); + errorType = ERROR_AUTH; + errorMessage = e.getMessage(); + } catch (HttpException e) { + Log.e(MyMapsConstants.TAG, "HttpException", e); + errorMessage = e.getMessage(); + if (errorMessage != null && errorMessage.contains("401")) { + errorType = ERROR_AUTH; + } else { + errorType = ERROR_CONNECTION; + } + } catch (IOException e) { + Log.e(MyMapsConstants.TAG, "Exception", e); + errorMessage = e.getMessage(); + if (errorMessage != null && errorMessage.contains("503")) { + errorType = ERROR_INTERNAL; + } else { + errorType = ERROR_CONNECTION; + } + } catch (ParseException e) { + Log.e(MyMapsConstants.TAG, "Exception", e); + errorType = ERROR_LOCAL; + errorMessage = e.getMessage(); + } catch (ConflictDetectedException e) { + Log.e(MyMapsConstants.TAG, "Exception", e); + errorType = ERROR_CONFLICT; + errorMessage = e.getMessage(); + } catch (Exception e) { + Log.e(MyMapsConstants.TAG, "Exception", e); + errorType = ERROR_UNKNOWN; + errorMessage = e.getMessage(); + e.printStackTrace(); + } + Log.d(MyMapsConstants.TAG, "GData error encountered: " + errorMessage); + if (errorType == ERROR_AUTH && auth != null) { + Runnable whenFinished = null; + if (retryOnAuthFailure) { + retriesPending++; + whenFinished = new Runnable() { + public void run() { + retriesPending--; + retryOnAuthFailure = false; + runQuery(query); + if (cleanupCalled && retriesPending == 0) { + cleanUp(); + } + } + }; + } + auth.invalidateAndRefresh(whenFinished); + } + return false; + } + + public int getErrorType() { + return errorType; + } + + public String getErrorMessage() { + return errorMessage; + } + + // cleanUp must be called when done using this wrapper to close the client. + // Note that the cleanup will be delayed if auth failure retries were + // requested and there is a pending retry. + public void cleanUp() { + if (retriesPending == 0 && !cleanupCalled) { + androidGdataClient.close(); + } + cleanupCalled = true; + } + + public void setRetryOnAuthFailure(boolean retry) { + retryOnAuthFailure = retry; + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsMapMetadata.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsMapMetadata.java new file mode 100644 index 000000000..4ffb459b8 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MyMapsMapMetadata.java @@ -0,0 +1,52 @@ +// Copyright 2009 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +/** + * Metadata about a "my maps" map. + */ +class MyMapsMapMetadata { + + private String title; + private String description; + private String gdataEditUri; + private boolean searchable; + + public MyMapsMapMetadata() { + title = ""; + description = ""; + gdataEditUri = ""; + searchable = false; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = new String(title); + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = new String(description); + } + + public boolean getSearchable() { + return searchable; + } + + public void setSearchable(boolean searchable) { + this.searchable = searchable; + } + + public String getGDataEditUri() { + return gdataEditUri; + } + + public void setGDataEditUri(String editUri) { + this.gdataEditUri = new String(editUri); + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/XmlMapsGDataParser.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/XmlMapsGDataParser.java new file mode 100644 index 000000000..7af41d7ed --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/XmlMapsGDataParser.java @@ -0,0 +1,163 @@ +// Copyright 2009 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +import com.google.wireless.gdata.data.Entry; +import com.google.wireless.gdata.data.Feed; +import com.google.wireless.gdata.data.XmlUtils; +import com.google.wireless.gdata.parser.ParseException; +import com.google.wireless.gdata.parser.xml.XmlGDataParser; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Parser for XML gdata maps data. + */ +class XmlMapsGDataParser extends XmlGDataParser { + + public XmlMapsGDataParser(InputStream is, XmlPullParser xpp) + throws ParseException { + super(is, xpp); + } + + @Override + protected Feed createFeed() { + return new Feed(); + } + + @Override + protected Entry createEntry() { + return new MapFeatureEntry(); + } + + @Override + protected void handleExtraElementInFeed(Feed feed) { + // Do nothing + } + + @Override + protected void handleExtraLinkInEntry( + String rel, String type, String href, Entry entry) + throws XmlPullParserException, IOException { + if (!(entry instanceof MapFeatureEntry)) { + throw new IllegalArgumentException("Expected MapFeatureEntry!"); + } + if (rel.endsWith("#view")) { + return; + } + super.handleExtraLinkInEntry(rel, type, href, entry); + } + + /** + * Parses the current entry in the XML document. Assumes that the parser is + * currently pointing just after an <entry>. + * + * @param plainEntry The entry that will be filled. + * @throws XmlPullParserException Thrown if the XML cannot be parsed. + * @throws IOException Thrown if the underlying inputstream cannot be read. + */ + @Override + protected void handleEntry(Entry plainEntry) + throws XmlPullParserException, IOException, ParseException { + XmlPullParser parser = getParser(); + if (!(plainEntry instanceof MapFeatureEntry)) { + throw new IllegalArgumentException("Expected MapFeatureEntry!"); + } + MapFeatureEntry entry = (MapFeatureEntry) plainEntry; + + int eventType = parser.getEventType(); + entry.setPrivacy("public"); + while (eventType != XmlPullParser.END_DOCUMENT) { + switch (eventType) { + case XmlPullParser.START_TAG: + String name = parser.getName(); + if ("entry".equals(name)) { + // stop parsing here. + return; + } else if ("id".equals(name)) { + entry.setId(XmlUtils.extractChildText(parser)); + } else if ("title".equals(name)) { + entry.setTitle(XmlUtils.extractChildText(parser)); + } else if ("link".equals(name)) { + String rel = parser.getAttributeValue(null /* ns */, "rel"); + String type = parser.getAttributeValue(null /* ns */, "type"); + String href = parser.getAttributeValue(null /* ns */, "href"); + if ("edit".equals(rel)) { + entry.setEditUri(href); + } else if ("alternate".equals(rel) && "text/html".equals(type)) { + entry.setHtmlUri(href); + } else { + handleExtraLinkInEntry(rel, type, href, entry); + } + } else if ("summary".equals(name)) { + entry.setSummary(XmlUtils.extractChildText(parser)); + } else if ("content".equals(name)) { + StringBuilder contentBuilder = new StringBuilder(); + int parentDepth = parser.getDepth(); + while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { + int etype = parser.next(); + switch (etype) { + case XmlPullParser.START_TAG: + contentBuilder.append('<'); + contentBuilder.append(parser.getName()); + contentBuilder.append('>'); + break; + case XmlPullParser.TEXT: + contentBuilder.append(""); + break; + case XmlPullParser.END_TAG: + if (parser.getDepth() > parentDepth) { + contentBuilder.append("'); + } + break; + } + if (etype == XmlPullParser.END_TAG + && parser.getDepth() == parentDepth) { + break; + } + } + entry.setContent(contentBuilder.toString()); + } else if ("category".equals(name)) { + String category = parser.getAttributeValue(null /* ns */, "term"); + if (category != null && category.length() > 0) { + entry.setCategory(category); + } + String categoryScheme = + parser.getAttributeValue(null /* ns */, "scheme"); + if (categoryScheme != null && category.length() > 0) { + entry.setCategoryScheme(categoryScheme); + } + } else if ("published".equals(name)) { + entry.setPublicationDate(XmlUtils.extractChildText(parser)); + } else if ("updated".equals(name)) { + entry.setUpdateDate(XmlUtils.extractChildText(parser)); + } else if ("deleted".equals(name)) { + entry.setDeleted(true); + } else if ("draft".equals(name)) { + String draft = XmlUtils.extractChildText(parser); + entry.setPrivacy("yes".equals(draft) ? "unlisted" : "public"); + } else if ("customProperty".equals(name)) { + String attrName = parser.getAttributeValue(null, "name"); + String attrValue = XmlUtils.extractChildText(parser); + entry.setAttribute(attrName, attrValue); + } else if ("deleted".equals(name)) { + entry.setDeleted(true); + } else { + handleExtraElementInEntry(entry); + } + break; + default: + break; + } + + eventType = parser.next(); + } + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/XmlMapsGDataParserFactory.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/XmlMapsGDataParserFactory.java new file mode 100644 index 000000000..15c0a884e --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/XmlMapsGDataParserFactory.java @@ -0,0 +1,94 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +import com.google.wireless.gdata.client.GDataParserFactory; +import com.google.wireless.gdata.data.Entry; +import com.google.wireless.gdata.parser.GDataParser; +import com.google.wireless.gdata.parser.ParseException; +import com.google.wireless.gdata.parser.xml.XmlGDataParser; +import com.google.wireless.gdata.parser.xml.XmlParserFactory; +import com.google.wireless.gdata.serializer.GDataSerializer; +import com.google.wireless.gdata.serializer.xml.XmlEntryGDataSerializer; + +import android.util.Log; + +import org.xmlpull.v1.XmlPullParserException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Factory of Xml parsers for gdata maps data. + */ +class XmlMapsGDataParserFactory implements GDataParserFactory { + private XmlParserFactory xmlFactory; + + public XmlMapsGDataParserFactory(XmlParserFactory xmlFactory) { + this.xmlFactory = xmlFactory; + } + + @Override + public GDataParser createParser(InputStream is) throws ParseException { + is = maybeLogCommunication(is); + try { + return new XmlGDataParser(is, xmlFactory.createParser()); + } catch (XmlPullParserException e) { + e.printStackTrace(); + return null; + } + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public GDataParser createParser(Class cls, InputStream is) + throws ParseException { + is = maybeLogCommunication(is); + try { + return createParserForClass(cls, is); + } catch (XmlPullParserException e) { + e.printStackTrace(); + return null; + } + } + + private InputStream maybeLogCommunication(InputStream is) + throws ParseException { + if (MapsClient.LOG_COMMUNICATION) { + StringBuilder builder = new StringBuilder(); + byte[] buffer = new byte[2048]; + try { + for (int n = is.read(buffer); n >= 0; n = is.read(buffer)) { + String part = new String(buffer, 0, n); + builder.append(part); + Log.d("Response part", part); + } + } catch (IOException e) { + throw new ParseException("Could not read stream", e); + } + String whole = builder.toString(); + Log.d("Response", whole); + is = new ByteArrayInputStream(whole.getBytes()); + } + return is; + } + + private GDataParser createParserForClass( + Class cls, InputStream is) + throws ParseException, XmlPullParserException { + if (cls == MapFeatureEntry.class) { + return new XmlMapsGDataParser(is, xmlFactory.createParser()); + } else { + return new XmlGDataParser(is, xmlFactory.createParser()); + } + } + + @Override + public GDataSerializer createSerializer(Entry en) { + if (en.getClass() == MapFeatureEntry.class) { + return new XmlMapsGDataSerializer(xmlFactory, en); + } else { + return new XmlEntryGDataSerializer(xmlFactory, en); + } + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/XmlMapsGDataSerializer.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/XmlMapsGDataSerializer.java new file mode 100644 index 000000000..80598788d --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/XmlMapsGDataSerializer.java @@ -0,0 +1,259 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.mymaps; + +import com.google.wireless.gdata.data.Entry; +import com.google.wireless.gdata.data.StringUtils; +import com.google.wireless.gdata.parser.ParseException; +import com.google.wireless.gdata.parser.xml.XmlGDataParser; +import com.google.wireless.gdata.parser.xml.XmlParserFactory; +import com.google.wireless.gdata.serializer.xml.XmlEntryGDataSerializer; + +import android.util.Log; + +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; + +/** + * Serializer of maps data for GData. + */ +class XmlMapsGDataSerializer extends XmlEntryGDataSerializer { + + private static final String APP_NAMESPACE = "http://www.w3.org/2007/app"; + + private MapFeatureEntry entry; + private XmlParserFactory factory; + private OutputStream stream; + + public XmlMapsGDataSerializer(XmlParserFactory factory, Entry entry) { + super(factory, entry); + + this.factory = factory; + this.entry = (MapFeatureEntry) entry; + } + + @Override + public void serialize(OutputStream out, int format) + throws IOException, ParseException { + XmlSerializer serializer = null; + try { + serializer = factory.createSerializer(); + } catch (XmlPullParserException e) { + throw new ParseException("Unable to create XmlSerializer.", e); + } + + ByteArrayOutputStream printStream; + + if (MapsClient.LOG_COMMUNICATION) { + printStream = new ByteArrayOutputStream(); + + serializer.setOutput(printStream, "UTF-8"); + } else { + serializer.setOutput(out, "UTF-8"); + } + + serializer.startDocument("UTF-8", Boolean.FALSE); + + declareEntryNamespaces(serializer); + serializer.startTag(XmlGDataParser.NAMESPACE_ATOM_URI, "entry"); + + stream = MapsClient.LOG_COMMUNICATION ? printStream : out; + serializeEntryContents(serializer, format); + + serializer.endTag(XmlGDataParser.NAMESPACE_ATOM_URI, "entry"); + serializer.endDocument(); + serializer.flush(); + + if (MapsClient.LOG_COMMUNICATION) { + Log.d("Request", printStream.toString()); + out.write(printStream.toByteArray()); + stream = out; + } + } + + private final void declareEntryNamespaces(XmlSerializer serializer) + throws IOException { + serializer.setPrefix( + "" /* default ns */, XmlGDataParser.NAMESPACE_ATOM_URI); + serializer.setPrefix( + XmlGDataParser.NAMESPACE_GD, XmlGDataParser.NAMESPACE_GD_URI); + declareExtraEntryNamespaces(serializer); + } + + private final void serializeEntryContents(XmlSerializer serializer, + int format) throws IOException { + if (format != FORMAT_CREATE) { + serializeId(serializer, entry.getId()); + } + + serializeTitle(serializer, entry.getTitle()); + + if (format != FORMAT_CREATE) { + serializeLink(serializer, + "edit" /* rel */, entry.getEditUri(), null /* type */); + serializeLink(serializer, + "alternate" /* rel */, entry.getHtmlUri(), "text/html" /* type */); + } + + serializeSummary(serializer, entry.getSummary()); + serializeContent(serializer, entry.getContent()); + serializeAuthor(serializer, entry.getAuthor(), entry.getEmail()); + serializeCategory(serializer, + entry.getCategory(), entry.getCategoryScheme()); + + if (format == FORMAT_FULL) { + serializePublicationDate(serializer, entry.getPublicationDate()); + } + + if (format != FORMAT_CREATE) { + serializeUpdateDate(serializer, entry.getUpdateDate()); + } + + serializeExtraEntryContents(serializer, format); + } + + private static void serializeId(XmlSerializer serializer, String id) + throws IOException { + if (StringUtils.isEmpty(id)) { + return; + } + serializer.startTag(null /* ns */, "id"); + serializer.text(id); + serializer.endTag(null /* ns */, "id"); + } + + private static void serializeTitle(XmlSerializer serializer, String title) + throws IOException { + if (StringUtils.isEmpty(title)) { + return; + } + serializer.startTag(null /* ns */, "title"); + serializer.text(title); + serializer.endTag(null /* ns */, "title"); + } + + public static void serializeLink(XmlSerializer serializer, String rel, + String href, String type) throws IOException { + if (StringUtils.isEmpty(href)) { + return; + } + serializer.startTag(null /* ns */, "link"); + serializer.attribute(null /* ns */, "rel", rel); + serializer.attribute(null /* ns */, "href", href); + if (!StringUtils.isEmpty(type)) { + serializer.attribute(null /* ns */, "type", type); + } + serializer.endTag(null /* ns */, "link"); + } + + private static void serializeSummary(XmlSerializer serializer, String summary) + throws IOException { + if (StringUtils.isEmpty(summary)) { + return; + } + serializer.startTag(null /* ns */, "summary"); + serializer.text(summary); + serializer.endTag(null /* ns */, "summary"); + } + + private void serializeContent(XmlSerializer serializer, String content) + throws IOException { + if (content == null) { + return; + } + serializer.startTag(null /* ns */, "content"); + if (content.contains("")) { + serializer.attribute( + null /* ns */, "type", "application/vnd.google-earth.kml+xml"); + serializer.flush(); + stream.write(content.getBytes()); + } else { + serializer.text(content); + } + serializer.endTag(null /* ns */, "content"); + } + + private static void serializeAuthor(XmlSerializer serializer, String author, + String email) throws IOException { + if (StringUtils.isEmpty(author) || StringUtils.isEmpty(email)) { + return; + } + serializer.startTag(null /* ns */, "author"); + serializer.startTag(null /* ns */, "name"); + serializer.text(author); + serializer.endTag(null /* ns */, "name"); + serializer.startTag(null /* ns */, "email"); + serializer.text(email); + serializer.endTag(null /* ns */, "email"); + serializer.endTag(null /* ns */, "author"); + } + + private static void serializeCategory(XmlSerializer serializer, + String category, String categoryScheme) throws IOException { + if (StringUtils.isEmpty(category) && StringUtils.isEmpty(categoryScheme)) { + return; + } + serializer.startTag(null /* ns */, "category"); + if (!StringUtils.isEmpty(category)) { + serializer.attribute(null /* ns */, "term", category); + } + if (!StringUtils.isEmpty(categoryScheme)) { + serializer.attribute(null /* ns */, "scheme", categoryScheme); + } + serializer.endTag(null /* ns */, "category"); + } + + private static void serializePublicationDate(XmlSerializer serializer, + String publicationDate) throws IOException { + if (StringUtils.isEmpty(publicationDate)) { + return; + } + serializer.startTag(null /* ns */, "published"); + serializer.text(publicationDate); + serializer.endTag(null /* ns */, "published"); + } + + private static void serializeUpdateDate(XmlSerializer serializer, + String updateDate) throws IOException { + if (StringUtils.isEmpty(updateDate)) { + return; + } + serializer.startTag(null /* ns */, "updated"); + serializer.text(updateDate); + serializer.endTag(null /* ns */, "updated"); + } + + @Override + protected void serializeExtraEntryContents(XmlSerializer serializer, + int format) throws IOException { + Map attrs = entry.getAllAttributes(); + for (Map.Entry attr : attrs.entrySet()) { + serializer.startTag("http://schemas.google.com/g/2005", "customProperty"); + serializer.attribute(null, "name", attr.getKey()); + serializer.text(attr.getValue()); + serializer.endTag("http://schemas.google.com/g/2005", "customProperty"); + } + String privacy = entry.getPrivacy(); + if (!StringUtils.isEmpty(privacy)) { + serializer.setPrefix("app", APP_NAMESPACE); + if ("public".equals(privacy)) { + serializer.startTag(APP_NAMESPACE, "control"); + serializer.startTag(APP_NAMESPACE, "draft"); + serializer.text("no"); + serializer.endTag(APP_NAMESPACE, "draft"); + serializer.endTag(APP_NAMESPACE, "control"); + } + if ("unlisted".equals(privacy)) { + serializer.startTag(APP_NAMESPACE, "control"); + serializer.startTag(APP_NAMESPACE, "draft"); + serializer.text("yes"); + serializer.endTag(APP_NAMESPACE, "draft"); + serializer.endTag(APP_NAMESPACE, "control"); + } + } + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/FroyoStatusAnnouncerTask.java b/MyTracks/src/com/google/android/apps/mytracks/services/FroyoStatusAnnouncerTask.java index 102cb2078..06050a2c6 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/FroyoStatusAnnouncerTask.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/FroyoStatusAnnouncerTask.java @@ -16,7 +16,7 @@ package com.google.android.apps.mytracks.services; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +import static com.google.android.apps.mytracks.Constants.TAG; import android.content.Context; import android.media.AudioManager; diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/PeriodicTaskExecuter.java b/MyTracks/src/com/google/android/apps/mytracks/services/PeriodicTaskExecuter.java index e7af61c2d..955db49e1 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/PeriodicTaskExecuter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/PeriodicTaskExecuter.java @@ -16,7 +16,7 @@ package com.google.android.apps.mytracks.services; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import android.util.Log; @@ -77,7 +77,7 @@ public class PeriodicTaskExecuter { } Date start = new Date(next); - Log.i(MyTracksConstants.TAG, + Log.i(Constants.TAG, task.getClass().getSimpleName() + " scheduled to start at " + start + " every " + interval + " milliseconds."); timer.scheduleAtFixedRate(new PeriodicTimerTask(), start, interval); @@ -87,7 +87,7 @@ public class PeriodicTaskExecuter { * Cleans up this object. */ public void shutdown() { - Log.i(MyTracksConstants.TAG, + Log.i(Constants.TAG, task.getClass().getSimpleName() + " shutting down."); if (timer != null) { timer.cancel(); diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/PreferenceManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/PreferenceManager.java index fee208d54..2d03b2afb 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/PreferenceManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/PreferenceManager.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.services; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.maps.mytracks.R; @@ -47,7 +47,7 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener { this.sharedPreferences = service.getSharedPreferences( MyTracksSettings.SETTINGS_NAME, 0); if (sharedPreferences == null) { - Log.w(MyTracksConstants.TAG, + Log.w(Constants.TAG, "TrackRecordingService: Couldn't get shared preferences."); throw new IllegalStateException("Couldn't get shared preferences"); } @@ -88,7 +88,7 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (service == null) { - Log.w(MyTracksConstants.TAG, + Log.w(Constants.TAG, "onSharedPreferenceChanged: a preference change (key = " + key + ") after a call to shutdown()"); return; @@ -98,7 +98,7 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener { sharedPreferences.getInt( minRecordingDistanceKey, MyTracksSettings.DEFAULT_MIN_RECORDING_DISTANCE)); - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "TrackRecordingService: minRecordingDistance = " + service.getMinRecordingDistance()); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/SplitManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/SplitManager.java index f63e87531..2edd56b58 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/SplitManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/SplitManager.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.services; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.WaypointCreationRequest; import com.google.android.apps.mytracks.util.UnitConversions; @@ -81,7 +81,7 @@ public class SplitManager { if (splitFrequency >= 0) { nextSplitDistance = Double.MAX_VALUE; - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "SplitManager: Distance splits disabled."); return; } @@ -94,7 +94,7 @@ public class SplitManager { int index = (int) (dist / splitFrequency); index -= 1; nextSplitDistance = splitFrequency * index; - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "SplitManager: Next split distance: " + nextSplitDistance); } @@ -126,7 +126,7 @@ public class SplitManager { * @param splitFrequency The frequency in time or distance */ public void setSplitFrequency(int splitFrequency) { - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "setSplitFrequency: splitFrequency = " + splitFrequency); this.splitFrequency = splitFrequency; diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/StatusAnnouncerTask.java b/MyTracks/src/com/google/android/apps/mytracks/services/StatusAnnouncerTask.java index bed0e1185..8f7f1cc52 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/StatusAnnouncerTask.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/StatusAnnouncerTask.java @@ -1,12 +1,12 @@ /* * Copyright 2009 Google Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -16,7 +16,9 @@ package com.google.android.apps.mytracks.services; -import com.google.android.apps.mytracks.MyTracksConstants; +import static com.google.android.apps.mytracks.Constants.TAG; + +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.util.StringUtils; @@ -99,7 +101,7 @@ public class StatusAnnouncerTask implements PeriodicTask { * Called when the TTS engine is initialized. */ protected void onTtsInit(int status) { - Log.i(MyTracksConstants.TAG, "TrackRecordingService.TTS init: " + status); + Log.i(TAG, "TrackRecordingService.TTS init: " + status); this.ready = status == TextToSpeech.SUCCESS; if (ready) { @@ -111,7 +113,7 @@ public class StatusAnnouncerTask implements PeriodicTask { languageAvailability == TextToSpeech.LANG_NOT_SUPPORTED) { // English is probably supported. // TODO: Somehow use announcement strings from English too. - Log.w(MyTracksConstants.TAG, "Default language not available, using English."); + Log.w(TAG, "Default language not available, using English."); speechLanguage = Locale.ENGLISH; } tts.setLanguage(speechLanguage); @@ -129,7 +131,7 @@ public class StatusAnnouncerTask implements PeriodicTask { @Override public void run(TrackRecordingService service) { if (service == null) { - Log.e(MyTracksConstants.TAG, "StatusAnnouncer TrackRecordingService not initialized"); + Log.e(TAG, "StatusAnnouncer TrackRecordingService not initialized"); return; } @@ -143,23 +145,22 @@ public class StatusAnnouncerTask implements PeriodicTask { */ protected void runWithStatistics(TripStatistics statistics) { if (statistics == null) { - Log.e(MyTracksConstants.TAG, "StatusAnnouncer stats not initialized."); + Log.e(TAG, "StatusAnnouncer stats not initialized."); return; } - if (!ready || tts == null) { - Log.e(MyTracksConstants.TAG, "StatusAnnouncer Tts not ready."); + Log.e(TAG, "StatusAnnouncer Tts not ready."); return; } if (!speechAllowed) { - Log.i(MyTracksConstants.TAG, + Log.i(Constants.TAG, "Not making announcement - not allowed at this time"); return; } String announcement = getAnnouncement(statistics); - Log.d(MyTracksConstants.TAG, "Announcement: " + announcement); + Log.d(Constants.TAG, "Announcement: " + announcement); speakAnnouncment(announcement); } @@ -179,7 +180,7 @@ public class StatusAnnouncerTask implements PeriodicTask { boolean metricUnits = true; boolean reportSpeed = true; if (preferences != null) { - metricUnits = + metricUnits = preferences.getBoolean(context.getString(R.string.metric_units_key), true); reportSpeed = @@ -218,7 +219,7 @@ public class StatusAnnouncerTask implements PeriodicTask { speed = String.format("%.1f", s); } else { double pace = 3600000.0 / s; - Log.w(MyTracksConstants.TAG, + Log.w(Constants.TAG, "Converted speed: " + s + " to pace: " + pace); speed = stringUtils.formatTimeLong((long) pace); } @@ -237,7 +238,7 @@ public class StatusAnnouncerTask implements PeriodicTask { @Override public void start() { - Log.i(MyTracksConstants.TAG, "Starting TTS"); + Log.i(Constants.TAG, "Starting TTS"); if (tts == null) { // We can't have this class also be the listener, otherwise it's unsafe to // reference it in Cupcake (even if we don't instantiate it). @@ -264,7 +265,7 @@ public class StatusAnnouncerTask implements PeriodicTask { tts = null; } - Log.i(MyTracksConstants.TAG, "TTS shut down"); + Log.i(Constants.TAG, "TTS shut down"); } /** diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/TaskExecuterManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/TaskExecuterManager.java index dc28c69f6..ec3b47d82 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/TaskExecuterManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/TaskExecuterManager.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.services; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import android.util.Log; @@ -49,14 +49,14 @@ public class TaskExecuterManager { */ public void setFrequency(int frequency, TrackRecordingService service) { this.frequency = frequency; - Log.i(MyTracksConstants.TAG, "Frequency set to " + frequency + Log.i(Constants.TAG, "Frequency set to " + frequency + " for task " + task.getClass().getSimpleName()); if (frequency == -1) { if (executer != null) { executer.shutdown(); executer = null; - Log.i(MyTracksConstants.TAG, + Log.i(Constants.TAG, "Shut down service: " + task.getClass().getSimpleName()); } } else { diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java b/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java index 5079e4dce..57815d323 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java @@ -15,20 +15,21 @@ */ package com.google.android.apps.mytracks.services; -import static com.google.android.apps.mytracks.MyTracksConstants.RESUME_TRACK_EXTRA_NAME; +import static com.google.android.apps.mytracks.Constants.TAG; +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.MyTracksConstants; +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.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.Sensor; -import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.WaypointCreationRequest; import com.google.android.apps.mytracks.content.WaypointsColumns; +import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; import com.google.android.apps.mytracks.services.sensors.SensorManager; import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory; import com.google.android.apps.mytracks.stats.TripStatistics; @@ -86,8 +87,8 @@ public class TrackRecordingService extends Service implements LocationListener { private int minRequiredAccuracy = MyTracksSettings.DEFAULT_MIN_REQUIRED_ACCURACY; private int autoResumeTrackTimeout = - MyTracksSettings.DEFAULT_AUTO_RESUME_TRACK_TIMEOUT; - + MyTracksSettings.DEFAULT_AUTO_RESUME_TRACK_TIMEOUT; + private long recordingTrackId = -1; private long currentWaypointId = -1; @@ -117,9 +118,9 @@ public class TrackRecordingService extends Service implements LocationListener { private SplitManager splitManager; private SensorManager sensorManager; - + private PreferenceManager prefManager; - + /** * The interval in milliseconds that we have requested to be notified of gps * readings. @@ -144,7 +145,7 @@ public class TrackRecordingService extends Service implements LocationListener { if (isRecording()) { handler.post(new Runnable() { public void run() { - Log.d(MyTracksConstants.TAG, + Log.d(Constants.TAG, "Re-registering location listener with TrackRecordingService."); unregisterLocationListener(); registerLocationListener(); @@ -168,7 +169,7 @@ public class TrackRecordingService extends Service implements LocationListener { * The most recent recording track. */ private Track recordingTrack; - + /** * Is the service currently recording a track? */ @@ -269,7 +270,7 @@ public class TrackRecordingService extends Service implements LocationListener { // Insert failed, most likely because of SqlLite error code 5 // (SQLite_BUSY). This is expected to happen extremely rarely (if our // listener gets invoked twice at about the same time). - Log.w(MyTracksConstants.TAG, + Log.w(TAG, "Caught SQLiteException: " + e.getMessage(), e); return false; } @@ -314,15 +315,15 @@ public class TrackRecordingService extends Service implements LocationListener { try { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); if (pm == null) { - Log.e(MyTracksConstants.TAG, + Log.e(TAG, "TrackRecordingService: Power manager not found!"); return; } if (wakeLock == null) { wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - MyTracksConstants.TAG); + TAG); if (wakeLock == null) { - Log.e(MyTracksConstants.TAG, + Log.e(TAG, "TrackRecordingService: Could not create wake lock (null)."); return; } @@ -330,12 +331,12 @@ public class TrackRecordingService extends Service implements LocationListener { if (!wakeLock.isHeld()) { wakeLock.acquire(); if (!wakeLock.isHeld()) { - Log.e(MyTracksConstants.TAG, + Log.e(TAG, "TrackRecordingService: Could not acquire wake lock."); } } } catch (RuntimeException e) { - Log.e(MyTracksConstants.TAG, + Log.e(TAG, "TrackRecordingService: Caught unexpected exception: " + e.getMessage(), e); } @@ -376,40 +377,40 @@ public class TrackRecordingService extends Service implements LocationListener { public void registerLocationListener() { if (locationManager == null) { - Log.e(MyTracksConstants.TAG, + Log.e(TAG, "TrackRecordingService: Do not have any location manager."); return; } - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "Preparing to register location listener w/ TrackRecordingService..."); try { long desiredInterval = locationListenerPolicy.getDesiredPollingInterval(); locationManager.requestLocationUpdates( - MyTracksConstants.GPS_PROVIDER, desiredInterval, + Constants.GPS_PROVIDER, desiredInterval, locationListenerPolicy.getMinDistance(), // , 0 /* minDistance, get all updates to properly time pauses */ TrackRecordingService.this); currentRecordingInterval = desiredInterval; - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "...location listener now registered w/ TrackRecordingService @ " + currentRecordingInterval); } catch (RuntimeException e) { - Log.e(MyTracksConstants.TAG, + Log.e(TAG, "Could not register location listener: " + e.getMessage(), e); } } public void unregisterLocationListener() { if (locationManager == null) { - Log.e(MyTracksConstants.TAG, + Log.e(TAG, "TrackRecordingService: Do not have any location manager."); return; } locationManager.removeUpdates(this); - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "Location listener now unregistered w/ TrackRecordingService."); } - + private Track getRecordingTrack() { if (recordingTrackId < 0) { return null; @@ -419,9 +420,9 @@ public class TrackRecordingService extends Service implements LocationListener { } private void restoreStats(Track track) { - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "Restoring stats of track with ID: " + track.getId()); - + TripStatistics stats = track.getStatistics(); statsBuilder = new TripStatisticsBuilder(stats.getStartTime()); statsBuilder.setMinRecordingDistance(minRecordingDistance); @@ -446,7 +447,7 @@ public class TrackRecordingService extends Service implements LocationListener { Cursor cursor = null; try { cursor = providerUtils.getLocationsCursor( - recordingTrackId, -1, MyTracksConstants.MAX_LOADED_TRACK_POINTS, + recordingTrackId, -1, Constants.MAX_LOADED_TRACK_POINTS, true); if (cursor != null) { if (cursor.moveToLast()) { @@ -465,10 +466,10 @@ public class TrackRecordingService extends Service implements LocationListener { statsBuilder.pauseAt(stats.getStopTime()); statsBuilder.resumeAt(System.currentTimeMillis()); } else { - Log.e(MyTracksConstants.TAG, "Could not get track points cursor."); + Log.e(TAG, "Could not get track points cursor."); } } catch (RuntimeException e) { - Log.e(MyTracksConstants.TAG, "Error while restoring track.", e); + Log.e(TAG, "Error while restoring track.", e); } finally { if (cursor != null) { cursor.close(); @@ -493,12 +494,12 @@ public class TrackRecordingService extends Service implements LocationListener { } private void onLocationChangedAsync(Location location) { - Log.d(MyTracksConstants.TAG, "TrackRecordingService.onLocationChanged"); + Log.d(TAG, "TrackRecordingService.onLocationChanged"); try { // Don't record if the service has been asked to pause recording: if (!isRecording) { - Log.w(MyTracksConstants.TAG, + Log.w(TAG, "Not recording because recording has been paused."); return; } @@ -506,14 +507,14 @@ public class TrackRecordingService extends Service implements LocationListener { // This should never happen, but just in case (we really don't want the // service to crash): if (location == null) { - Log.w(MyTracksConstants.TAG, + Log.w(TAG, "Location changed, but location is null."); return; } // Don't record if the accuracy is too bad: if (location.getAccuracy() > minRequiredAccuracy) { - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "Not recording. Bad accuracy."); return; } @@ -521,7 +522,7 @@ public class TrackRecordingService extends Service implements LocationListener { // At least one track must be available for appending points: recordingTrack = getRecordingTrack(); if (recordingTrack == null) { - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "Not recording. No track to append to available."); return; } @@ -555,7 +556,7 @@ public class TrackRecordingService extends Service implements LocationListener { // maxRecordingDistance = 0 if (distanceToLast == 0 && !hasSensorData) { if (isMoving) { - Log.d(MyTracksConstants.TAG, "Found two identical locations."); + Log.d(TAG, "Found two identical locations."); isMoving = false; if (lastLocation != null && lastRecordedLocation != null && !lastRecordedLocation.equals(lastLocation)) { @@ -570,7 +571,7 @@ public class TrackRecordingService extends Service implements LocationListener { lastRecordedLocationId++; } } else { - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "Not recording. More than two identical locations."); } } else if (distanceToLastRecorded > minRecordingDistance @@ -595,8 +596,8 @@ public class TrackRecordingService extends Service implements LocationListener { && recordingTrack.getStartId() >= 0; if (startNewSegment) { // Insert a separator point to indicate start of new track: - Log.d(MyTracksConstants.TAG, "Inserting a separator."); - Location separator = new Location(MyTracksConstants.GPS_PROVIDER); + Log.d(TAG, "Inserting a separator."); + Location separator = new Location(Constants.GPS_PROVIDER); separator.setLongitude(0); separator.setLatitude(100); separator.setTime(lastRecordedLocation.getTime()); @@ -608,7 +609,7 @@ public class TrackRecordingService extends Service implements LocationListener { return; } } else { - Log.d(MyTracksConstants.TAG, String.format( + Log.d(TAG, String.format( "Not recording. Distance to last recorded point (%f m) is less than" + " %d m.", distanceToLastRecorded, minRecordingDistance)); // Return here so that the location is NOT recorded as the last location. @@ -616,11 +617,11 @@ public class TrackRecordingService extends Service implements LocationListener { } } catch (Error e) { // Probably important enough to rethrow. - Log.e(MyTracksConstants.TAG, "Error in onLocationChanged", e); + Log.e(TAG, "Error in onLocationChanged", e); throw e; } catch (RuntimeException e) { // Safe usually to trap exceptions. - Log.e(MyTracksConstants.TAG, + Log.e(TAG, "Trapping exception in onLocationChanged", e); throw e; } @@ -657,7 +658,7 @@ public class TrackRecordingService extends Service implements LocationListener { @Override public void onCreate() { super.onCreate(); - Log.d(MyTracksConstants.TAG, "TrackRecordingService.onCreate"); + Log.d(TAG, "TrackRecordingService.onCreate"); providerUtils = MyTracksProviderUtils.Factory.get(this); notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); @@ -682,7 +683,7 @@ public class TrackRecordingService extends Service implements LocationListener { } else { if (recordingTrackId != -1) { // Make sure we have consistent state in shared preferences. - Log.w(MyTracksConstants.TAG, "TrackRecordingService.onCreate: " + Log.w(TAG, "TrackRecordingService.onCreate: " + "Resetting an orphaned recording track = " + recordingTrackId); } prefManager.setRecordingTrack(recordingTrackId = -1); @@ -697,7 +698,7 @@ public class TrackRecordingService extends Service implements LocationListener { * the announcements, otherwise this method is no-op. */ private void setUpAnnouncer() { - Log.d(MyTracksConstants.TAG, "TrackRecordingService.setUpAnnouncer: " + Log.d(TAG, "TrackRecordingService.setUpAnnouncer: " + announcementExecuter); if (announcementFrequency != -1 && recordingTrackId != -1) { handler.post(new Runnable() { @@ -721,9 +722,9 @@ public class TrackRecordingService extends Service implements LocationListener { }); } } - + private void shutdownAnnouncer() { - Log.d(MyTracksConstants.TAG, "TrackRecordingService.shutdownAnnouncer: " + Log.d(TAG, "TrackRecordingService.shutdownAnnouncer: " + announcementExecuter); if (announcementExecuter != null) { try { @@ -736,7 +737,7 @@ public class TrackRecordingService extends Service implements LocationListener { @Override public void onDestroy() { - Log.d(MyTracksConstants.TAG, "TrackRecordingService.onDestroy"); + Log.d(TAG, "TrackRecordingService.onDestroy"); isRecording = false; showNotification(); @@ -764,29 +765,29 @@ public class TrackRecordingService extends Service implements LocationListener { // This should be the last operation. releaseWakeLock(); - + super.onDestroy(); } @Override public IBinder onBind(Intent intent) { - Log.d(MyTracksConstants.TAG, "TrackRecordingService.onBind"); + Log.d(TAG, "TrackRecordingService.onBind"); return binder; } @Override public boolean onUnbind(Intent intent) { - Log.d(MyTracksConstants.TAG, "TrackRecordingService.onUnbind"); + Log.d(TAG, "TrackRecordingService.onUnbind"); return super.onUnbind(intent); } @Override public boolean stopService(Intent name) { - Log.d(MyTracksConstants.TAG, "TrackRecordingService.stopService"); + Log.d(TAG, "TrackRecordingService.stopService"); unregisterLocationListener(); return super.stopService(name); } - + @Override public void onStart(Intent intent, int startId) { handleStartCommand(intent, startId); @@ -799,50 +800,50 @@ public class TrackRecordingService extends Service implements LocationListener { } private void handleStartCommand(Intent intent, int startId) { - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "TrackRecordingService.handleStartCommand: " + startId); // Check if called on phone reboot with resume intent. if (intent != null && intent.getBooleanExtra(RESUME_TRACK_EXTRA_NAME, false)) { - Log.d(MyTracksConstants.TAG, "TrackRecordingService: requested resume"); - + Log.d(TAG, "TrackRecordingService: requested resume"); + // Make sure that the current track exists and is fresh enough. if (recordingTrack == null || !shouldResumeTrack(recordingTrack)) { - Log.i(MyTracksConstants.TAG, + Log.i(TAG, "TrackRecordingService: Not resuming, because the previous track (" + recordingTrack + ") doesn't exist or is too old"); isRecording = false; - prefManager.setRecordingTrack(recordingTrackId = -1); + prefManager.setRecordingTrack(recordingTrackId = -1); stopSelfResult(startId); return; } - - Log.i(MyTracksConstants.TAG, "TrackRecordingService: resuming"); + + Log.i(TAG, "TrackRecordingService: resuming"); } } - + private void setAutoResumeTrackRetries( SharedPreferences sharedPreferences, int retryAttempts) { - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "Updating auto-resume retry attempts to: " + retryAttempts); prefManager.setAutoResumeTrackCurrentRetry(retryAttempts); } - + private boolean shouldResumeTrack(Track track) { - Log.d(MyTracksConstants.TAG, "shouldResumeTrack: autoResumeTrackTimeout = " + Log.d(TAG, "shouldResumeTrack: autoResumeTrackTimeout = " + autoResumeTrackTimeout); // Check if we haven't exceeded the maximum number of retry attempts. SharedPreferences sharedPreferences = - getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); + getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); int retries = sharedPreferences.getInt( getString(R.string.auto_resume_track_current_retry_key), 0); - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "shouldResumeTrack: Attempting to auto-resume the track (" + (retries + 1) + "/" + MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS + ")"); if (retries >= MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS) { - Log.i(MyTracksConstants.TAG, + Log.i(TAG, "shouldResumeTrack: Not resuming because exceeded the maximum " + "number of auto-resume retries"); return false; @@ -853,13 +854,13 @@ public class TrackRecordingService extends Service implements LocationListener { // Check for special cases. if (autoResumeTrackTimeout == 0) { - // Never resume. - Log.d(MyTracksConstants.TAG, + // Never resume. + Log.d(TAG, "shouldResumeTrack: Auto-resume disabled (never resume)"); return false; } else if (autoResumeTrackTimeout == -1) { // Always resume. - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "shouldResumeTrack: Auto-resume forced (always resume)"); return true; } @@ -867,11 +868,11 @@ public class TrackRecordingService extends Service implements LocationListener { // Check if the last modified time is within the acceptable range. long lastModified = track.getStatistics() != null ? track.getStatistics().getStopTime() : 0; - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "shouldResumeTrack: lastModified = " + lastModified + ", autoResumeTrackTimeout: " + autoResumeTrackTimeout); return lastModified > 0 && System.currentTimeMillis() - lastModified <= - autoResumeTrackTimeout * 60 * 1000; + autoResumeTrackTimeout * 60 * 1000; } public boolean isRecording() { @@ -897,7 +898,8 @@ public class TrackRecordingService extends Service implements LocationListener { } wpt.setTrackId(recordingTrackId); wpt.setLength(length); - if (lastValidLocation == null) { + if (lastLocation == null + || statsBuilder == null || statsBuilder.getStatistics() == null) { // A null location is ok, and expected on track start. // Make it an impossible location. Location l = new Location(""); @@ -905,11 +907,9 @@ public class TrackRecordingService extends Service implements LocationListener { l.setLongitude(180); wpt.setLocation(l); } else { - // A null location is ok, and expected on track start. wpt.setLocation(lastLocation); - if (lastLocation != null) { - wpt.setDuration(lastLocation.getTime() - statsBuilder.getStatistics().getStartTime()); - } + wpt.setDuration(lastLocation.getTime() + - statsBuilder.getStatistics().getStartTime()); } Uri uri = providerUtils.insertWaypoint(wpt); return Long.parseLong(uri.getLastPathSegment()); @@ -962,27 +962,27 @@ public class TrackRecordingService extends Service implements LocationListener { // Create a new stats keeper for the next marker. waypointStatsBuilder = new TripStatisticsBuilder(time); } - + private ServiceBinder binder = new ServiceBinder(this); - + /** * TODO: There is a bug in Android that leaks Binder instances. This bug is * especially visible if we have a non-static class, as there is no way to * nullify reference to the outer class (the service). * A workaround is to use a static class and explicitly clear service * and detach it from the underlying Binder. With this approach, we minimize - * the leak to 24 bytes per each service instance. + * the leak to 24 bytes per each service instance. * * For more details, see the following bug: * http://code.google.com/p/android/issues/detail?id=6426. */ private static class ServiceBinder extends ITrackRecordingService.Stub { private TrackRecordingService service; - + public ServiceBinder(TrackRecordingService service) { this.service = service; } - + /** * Clears the reference to the outer class to minimize the leak. */ @@ -990,7 +990,7 @@ public class TrackRecordingService extends Service implements LocationListener { this.service = null; attachInterface(null, null); } - + @Override public boolean isRecording() { checkService(); @@ -1005,13 +1005,13 @@ public class TrackRecordingService extends Service implements LocationListener { @Override public long getRecordingTrackId() { - checkService(); + checkService(); return service.recordingTrackId; } @Override public boolean hasRecorded() { - checkService(); + checkService(); return service.providerUtils.getLastTrackId() >= 0; } @@ -1049,19 +1049,19 @@ public class TrackRecordingService extends Service implements LocationListener { @Override public void recordLocation(Location loc) { - checkService(); + checkService(); service.onLocationChanged(loc); } @Override public byte[] getSensorData() { - checkService(); + checkService(); if (service.sensorManager == null) { - Log.d(MyTracksConstants.TAG, "No sensor manager for data."); + Log.d(TAG, "No sensor manager for data."); return null; } if (service.sensorManager.getSensorDataSet() == null) { - Log.d(MyTracksConstants.TAG, "Sensor data set is null."); + Log.d(TAG, "Sensor data set is null."); return null; } return service.sensorManager.getSensorDataSet().toByteArray(); @@ -1069,9 +1069,9 @@ public class TrackRecordingService extends Service implements LocationListener { @Override public int getSensorState() { - checkService(); + checkService(); if (service.sensorManager == null) { - Log.d(MyTracksConstants.TAG, "No sensor manager for data."); + Log.d(TAG, "No sensor manager for data."); return Sensor.SensorState.NONE.getNumber(); } return service.sensorManager.getSensorState().getNumber(); @@ -1079,7 +1079,7 @@ public class TrackRecordingService extends Service implements LocationListener { } public long startNewTrack() { - Log.d(MyTracksConstants.TAG, "TrackRecordingService.startNewTrack"); + Log.d(TAG, "TrackRecordingService.startNewTrack"); if (recordingTrackId != -1 || isRecording) { throw new IllegalStateException("A track is already in progress!"); } @@ -1129,7 +1129,7 @@ public class TrackRecordingService extends Service implements LocationListener { } private void endCurrentTrack() { - Log.d(MyTracksConstants.TAG, "TrackRecordingService.endCurrentTrack"); + Log.d(TAG, "TrackRecordingService.endCurrentTrack"); if (recordingTrackId == -1 || !isRecording) { throw new IllegalStateException("No recording track in progress!"); } @@ -1156,12 +1156,12 @@ public class TrackRecordingService extends Service implements LocationListener { showNotification(); long recordedTrackId = recordingTrackId; prefManager.setRecordingTrack(recordingTrackId = -1); - + if (sensorManager != null) { sensorManager.shutdown(); sensorManager = null; } - + releaseWakeLock(); // Notify the world that we're no longer recording. @@ -1243,11 +1243,11 @@ public class TrackRecordingService extends Service implements LocationListener { LocationListenerPolicy locationListenerPolicy) { this.locationListenerPolicy = locationListenerPolicy; } - + public int getAutoResumeTrackTimeout() { return autoResumeTrackTimeout; } - + public void setAutoResumeTrackTimeout(int autoResumeTrackTimeout) { this.autoResumeTrackTimeout = autoResumeTrackTimeout; } diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntDirectSensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntDirectSensorManager.java index cd033c59e..b18c9137c 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntDirectSensorManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntDirectSensorManager.java @@ -15,17 +15,17 @@ */ package com.google.android.apps.mytracks.services.sensors; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; - -import com.dsi.ant.AntDefine; -import com.dsi.ant.AntMesg; -import com.dsi.ant.exception.AntInterfaceException; +import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.MyTracksSettings; 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.AntChannelResponseMessage; import com.google.android.maps.mytracks.R; +import com.dsi.ant.AntDefine; +import com.dsi.ant.AntMesg; +import com.dsi.ant.exception.AntInterfaceException; + import android.content.Context; import android.content.SharedPreferences; import android.util.Log; diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntSRMSensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntSRMSensorManager.java index 9d177339f..ea4ceb818 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntSRMSensorManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntSRMSensorManager.java @@ -15,14 +15,14 @@ */ package com.google.android.apps.mytracks.services.sensors; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +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.maps.mytracks.R; import com.dsi.ant.AntDefine; import com.dsi.ant.AntMesg; import com.dsi.ant.exception.AntInterfaceException; -import com.google.android.apps.mytracks.MyTracksSettings; -import com.google.android.apps.mytracks.content.Sensor; -import com.google.android.maps.mytracks.R; import android.content.Context; import android.content.SharedPreferences; @@ -82,10 +82,10 @@ public class AntSRMSensorManager extends AntSensorManager { @Override public void handleMessage(byte[] antMessage) { // Parse channel number - byte receivedChannel = (byte) (antMessage[AntMesg.MESG_DATA_OFFSET] + byte recievedChannel = (byte) (antMessage[AntMesg.MESG_DATA_OFFSET] & AntDefine.CHANNEL_NUMBER_MASK); - if (receivedChannel != channel) { - Log.d(TAG, "Unexpected channel: " + receivedChannel); + if (recievedChannel != channel) { + Log.d(Constants.TAG, "Unexpected channel: " + recievedChannel); return; } switch (antMessage[AntMesg.MESG_ID_OFFSET]) { @@ -99,17 +99,18 @@ public class AntSRMSensorManager extends AntSensorManager { handleChannelId(antMessage); break; default: - Log.e(TAG, "Unexpected message id: " + antMessage[3]); + Log.e(Constants.TAG, + "Unexpected message id: " + antMessage[3]); } } private void handleBroadcastData(byte[] antMessage) { if (deviceId == WILDCARD) { try { - Log.d(TAG, "Requesting channel id id."); + Log.d(Constants.TAG, "Requesting channel id id."); getAntReceiver().ANTRequestMessage(channel, AntMesg.MESG_CHANNEL_ID_ID); } catch (AntInterfaceException e) { - Log.e(TAG, "Failed to request channel id id", e); + Log.e(Constants.TAG, "Failed to request channel id id", e); } } setSensorState(Sensor.SensorState.CONNECTED); @@ -121,14 +122,15 @@ public class AntSRMSensorManager extends AntSensorManager { parseSensorData(antMessage); break; default: - Log.e(TAG, "Unexpected message type: " + antMessage[MESSAGE_TYPE_INDEX]); + Log.e(Constants.TAG, + "Unexpected message type: " + antMessage[MESSAGE_TYPE_INDEX]); } } private void handleChannelId(byte[] antMessage) { // Store the device id. deviceId = antMessage[3]; - Log.i(TAG, "Found device id: " + deviceId); + Log.i(Constants.TAG, "Found device id: " + deviceId); SharedPreferences prefs = context.getSharedPreferences( MyTracksSettings.SETTINGS_NAME, Context.MODE_PRIVATE); @@ -141,34 +143,38 @@ public class AntSRMSensorManager extends AntSensorManager { if (antMessage[3] == AntMesg.MESG_EVENT_ID && antMessage[4] == AntDefine.EVENT_RX_SEARCH_TIMEOUT) { // Search timeout - Log.w(TAG, "Search timed out. Unassigning channel."); + Log.w(Constants.TAG, "Search timed out. Unassigning channel."); try { getAntReceiver().ANTUnassignChannel(channel); } catch (AntInterfaceException e) { - Log.e(TAG, "Failed to unassign ANT channel", e); + Log.e(Constants.TAG, "Failed to unassign ANT channel", e); } setSensorState(Sensor.SensorState.DISCONNECTED); } else if (antMessage[3] == AntMesg.MESG_UNASSIGN_CHANNEL_ID) { setSensorState(Sensor.SensorState.DISCONNECTED); - Log.i(TAG, "Disconnected from the sensor: " + getSensorState()); + Log.i(Constants.TAG, + "Disconnected from the sensor: " + getSensorState()); } } private void parseSensorData(byte[] antMessage) { if (antMessage.length != 11) { - Log.e(TAG, "Unexpected ant message length: " + antMessage.length); + Log.e(Constants.TAG, + "Unexpected ant message length: " + antMessage.length); return; } int newMessageId = antMessage[MESSAGE_ID_INDEX] & 0xFF; if (lastMessageId == newMessageId) { // Repeated message. - Log.i(TAG, String.format("SRM ignoring repeat: 0x%X", newMessageId)); + Log.i(Constants.TAG, + String.format("SRM ignoring repeat: 0x%X", newMessageId)); return; } if (newMessageId < lastMessageId) { if (!(newMessageId < 20 && lastMessageId > 200)) { - Log.i(TAG, String.format("SRM ignoring repeat: 0x%X", newMessageId)); + Log.i(Constants.TAG, + String.format("SRM ignoring repeat: 0x%X", newMessageId)); return; } // else assume the byte overflowed to 0. } diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntSensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntSensorManager.java index d7f206726..5e83a8a4a 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntSensorManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/AntSensorManager.java @@ -15,16 +15,16 @@ */ package com.google.android.apps.mytracks.services.sensors; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.content.Sensor; +import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; +import com.google.android.apps.mytracks.services.sensors.ant.AntStartupMessage; import com.dsi.ant.AntDefine; import com.dsi.ant.AntInterface; import com.dsi.ant.AntInterfaceIntent; import com.dsi.ant.AntMesg; import com.dsi.ant.exception.AntInterfaceException; -import com.google.android.apps.mytracks.content.Sensor; -import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; -import com.google.android.apps.mytracks.services.sensors.ant.AntStartupMessage; import android.content.BroadcastReceiver; import android.content.Context; @@ -84,7 +84,7 @@ public abstract class AntSensorManager extends SensorManager { @Override public void onReceive(Context context, Intent intent) { String antAction = intent.getAction(); - Log.i(TAG, "enter status onReceive" + antAction); + Log.i(Constants.TAG, "enter status onReceive" + antAction); } }; @@ -93,12 +93,12 @@ public abstract class AntSensorManager extends SensorManager { @Override public void onReceive(Context context, Intent intent) { String antAction = intent.getAction(); - Log.i(TAG, "enter data onReceive" + antAction); + Log.i(Constants.TAG, "enter data onReceive" + antAction); if (antAction.equals(AntInterfaceIntent.ANT_RX_MESSAGE_ACTION)) { byte[] antMessage = intent.getByteArrayExtra(AntInterfaceIntent.ANT_MESSAGE); if (DEBUGGING) { - Log.d(TAG, "Received RX message " + messageToString(antMessage)); + Log.d(Constants.TAG, "Received RX message " + messageToString(antMessage)); } handleMessage(antMessage); @@ -119,7 +119,7 @@ public abstract class AntSensorManager extends SensorManager { @Override public void onServiceDisconnected() { - Log.d(TAG, "ANT interface reports disconnection"); + Log.d(Constants.TAG, "ANT interface reports disconnection"); } }; @@ -129,14 +129,14 @@ public abstract class AntSensorManager extends SensorManager { @Override public void onDestroy() { - Log.i(TAG, "destroying AntSensorManager"); + Log.i(Constants.TAG, "destroying AntSensorManager"); context.unregisterReceiver(statusReceiver); context.unregisterReceiver(dataReceiver); try { antReceiver.releaseInterface(); } catch (AntInterfaceException e) { - Log.e(TAG, "failed to release ANT interface", e); + Log.e(Constants.TAG, "failed to release ANT interface", e); } antReceiver.destroy(); @@ -177,7 +177,7 @@ public abstract class AntSensorManager extends SensorManager { antReceiver = AntInterface.getInstance(context, antServiceListener); if (antReceiver == null) { - Log.e(TAG, "Failed to get ANT Receiver"); + Log.e(Constants.TAG, "Failed to get ANT Receiver"); return; } @@ -190,11 +190,11 @@ public abstract class AntSensorManager extends SensorManager { * to initiate any ANT commands. */ private synchronized void serviceConnected() { - Log.d(TAG, "ANT service connected"); + Log.d(Constants.TAG, "ANT service connected"); try { if (!antReceiver.claimInterface()) { - Log.e(TAG, "failed to claim ANT interface"); + Log.e(Constants.TAG, "failed to claim ANT interface"); return; } @@ -202,14 +202,14 @@ public abstract class AntSensorManager extends SensorManager { // Make sure not to call AntInterface.enable() again, if it has been // already called before if (antInterrupted == false) { - Log.i(TAG, "Powering on Radio"); + Log.i(Constants.TAG, "Powering on Radio"); antReceiver.enable(); } } else { - Log.i(TAG, "Radio already enabled"); + Log.i(Constants.TAG, "Radio already enabled"); } } catch (AntInterfaceException e) { - Log.e(TAG, "failed to enable ANT", e); + Log.e(Constants.TAG, "failed to enable ANT", e); } try { @@ -220,7 +220,7 @@ public abstract class AntSensorManager extends SensorManager { // that message. antReceiver.ANTResetSystem(); } catch (AntInterfaceException e) { - Log.e(TAG, "failed to reset ANT (expected exception)", e); + Log.e(Constants.TAG, "failed to reset ANT (expected exception)", e); } } @@ -232,7 +232,7 @@ public abstract class AntSensorManager extends SensorManager { protected void handleMessage(byte[] antMessage) { int len = antMessage[0]; if (len != antMessage.length - 2 || antMessage.length <= 2) { - Log.e(TAG, "Invalid message: " + messageToString(antMessage)); + Log.e(Constants.TAG, "Invalid message: " + messageToString(antMessage)); return; } @@ -253,7 +253,8 @@ public abstract class AntSensorManager extends SensorManager { */ protected boolean handleMessage(byte messageId, byte[] messageData) { if (messageId == AntMesg.MESG_STARTUP_MESG_ID) { - Log.d(TAG, String.format("Received startup message (reason %02x); initializing channel", + Log.d(Constants.TAG, String.format( + "Received startup message (reason %02x); initializing channel", new AntStartupMessage(messageData).getMessage())); setupAntSensorChannels(); return true; @@ -304,13 +305,13 @@ public abstract class AntSensorManager extends SensorManager { return true; } catch (AntInterfaceException e) { - Log.e(TAG, "failed to setup ANT channel", e); + Log.e(Constants.TAG, "failed to setup ANT channel", e); return false; } } private void registerForAntIntents() { - Log.i(TAG, "Registering for ant intents."); + Log.i(Constants.TAG, "Registering for ant intents."); // Register for ANT intent broadcasts. IntentFilter statusIntentFilter = new IntentFilter(); statusIntentFilter.addAction(AntInterfaceIntent.ANT_ENABLED_ACTION); diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothConnectionManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothConnectionManager.java index 035dd5960..3f95db95f 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothConnectionManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothConnectionManager.java @@ -16,8 +16,7 @@ package com.google.android.apps.mytracks.services.sensors; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; - +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.Sensor; import android.bluetooth.BluetoothAdapter; @@ -86,7 +85,7 @@ public class BluetoothConnectionManager { */ private synchronized void setState(Sensor.SensorState state) { // TODO pretty print this. - Log.d(TAG, "setState(" + state + ")"); + Log.d(Constants.TAG, "setState(" + state + ")"); this.state = state; // Give the new state to the Handler so the UI Activity can update @@ -105,7 +104,7 @@ public class BluetoothConnectionManager { * in listening (server) mode. Called by the Activity onResume() */ public synchronized void start() { - Log.d(TAG, "BluetoothConnectionManager.start()"); + Log.d(Constants.TAG, "BluetoothConnectionManager.start()"); // Cancel any thread attempting to make a connection if (connectThread != null) { @@ -128,7 +127,7 @@ public class BluetoothConnectionManager { * @param device The BluetoothDevice to connect */ public synchronized void connect(BluetoothDevice device) { - Log.d(TAG, "connect to: " + device); + Log.d(Constants.TAG, "connect to: " + device); // Cancel any thread attempting to make a connection if (state == Sensor.SensorState.CONNECTING) { @@ -158,7 +157,7 @@ public class BluetoothConnectionManager { */ public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { - Log.d(TAG, "connected"); + Log.d(Constants.TAG, "connected"); // Cancel the thread that completed the connection if (connectThread != null) { @@ -190,7 +189,7 @@ public class BluetoothConnectionManager { * Stop all threads */ public synchronized void stop() { - Log.d(TAG, "stop()"); + Log.d(Constants.TAG, "stop()"); if (connectThread != null) { connectThread.cancel(); connectThread = null; @@ -227,7 +226,7 @@ public class BluetoothConnectionManager { */ private void connectionFailed() { setState(Sensor.SensorState.DISCONNECTED); - Log.i(TAG, "Bluetooth connection failed."); + Log.i(Constants.TAG, "Bluetooth connection failed."); } /** @@ -235,7 +234,7 @@ public class BluetoothConnectionManager { */ private void connectionLost() { setState(Sensor.SensorState.DISCONNECTED); - Log.i(TAG, "Bluetooth connection lost."); + Log.i(Constants.TAG, "Bluetooth connection lost."); } /** @@ -256,7 +255,7 @@ public class BluetoothConnectionManager { try { tmp = getSocket(); } catch (IOException e) { - Log.e(TAG, "create() failed", e); + Log.e(Constants.TAG, "create() failed", e); } socket = tmp; } @@ -269,22 +268,22 @@ public class BluetoothConnectionManager { insecure.setAccessible(true); return (BluetoothSocket) insecure.invoke(device, 1); } catch (SecurityException e) { - Log.e(TAG, "Unable to get insecure connect.", e); + Log.e(Constants.TAG, "Unable to get insecure connect.", e); } catch (NoSuchMethodException e) { - Log.e(TAG, "Unable to get insecure connect.", e); + Log.e(Constants.TAG, "Unable to get insecure connect.", e); } catch (IllegalArgumentException e) { - Log.e(TAG, "Unable to get insecure connect.", e); + Log.e(Constants.TAG, "Unable to get insecure connect.", e); } catch (IllegalAccessException e) { - Log.e(TAG, "Unable to get insecure connect.", e); + Log.e(Constants.TAG, "Unable to get insecure connect.", e); } catch (InvocationTargetException e) { - Log.e(TAG, "Unable to get insecure connect.", e); + Log.e(Constants.TAG, "Unable to get insecure connect.", e); } return device.createRfcommSocketToServiceRecord(SPP_UUID); } @Override public void run() { - Log.d(TAG, "BEGIN mConnectThread"); + Log.d(Constants.TAG, "BEGIN mConnectThread"); // Always cancel discovery because it will slow down a connection adapter.cancelDiscovery(); @@ -300,7 +299,8 @@ public class BluetoothConnectionManager { try { socket.close(); } catch (IOException e2) { - Log.e(TAG, "unable to close() socket during connection failure", e2); + Log.e(Constants.TAG, + "unable to close() socket during connection failure", e2); } // Start the service over to restart listening mode BluetoothConnectionManager.this.start(); @@ -320,7 +320,7 @@ public class BluetoothConnectionManager { try { socket.close(); } catch (IOException e) { - Log.e(TAG, "close() of connect socket failed", e); + Log.e(Constants.TAG, "close() of connect socket failed", e); } } } @@ -335,7 +335,7 @@ public class BluetoothConnectionManager { private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) { - Log.d(TAG, "create ConnectedThread"); + Log.d(Constants.TAG, "create ConnectedThread"); btSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; @@ -345,7 +345,7 @@ public class BluetoothConnectionManager { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { - Log.e(TAG, "temp sockets not created", e); + Log.e(Constants.TAG, "temp sockets not created", e); } mmInStream = tmpIn; @@ -354,7 +354,7 @@ public class BluetoothConnectionManager { @Override public void run() { - Log.i(TAG, "BEGIN mConnectedThread"); + Log.i(Constants.TAG, "BEGIN mConnectedThread"); byte[] buffer = new byte[parser.getFrameSize()]; int bytes; int offset = 0; @@ -383,10 +383,11 @@ public class BluetoothConnectionManager { // re-align offset = parser.getFrameSize() - index; System.arraycopy(buffer, index, buffer, 0, offset); - Log.w(TAG, "Misaligned data, found new message at " + index + " recovering..."); + Log.w(Constants.TAG, "Misaligned data, found new message at " + + index + " recovering..."); continue; } - Log.w(TAG, "Could not find valid data, dropping data"); + Log.w(Constants.TAG, "Could not find valid data, dropping data"); offset = 0; continue; } @@ -397,7 +398,7 @@ public class BluetoothConnectionManager { handler.obtainMessage(MESSAGE_READ, bytes, -1, buffer) .sendToTarget(); } catch (IOException e) { - Log.e(TAG, "disconnected", e); + Log.e(Constants.TAG, "disconnected", e); connectionLost(); break; } @@ -416,7 +417,7 @@ public class BluetoothConnectionManager { // Share the sent message back to the UI Activity handler.obtainMessage(MESSAGE_WRITE, -1, -1, buffer).sendToTarget(); } catch (IOException e) { - Log.e(TAG, "Exception during write", e); + Log.e(Constants.TAG, "Exception during write", e); } } @@ -424,7 +425,7 @@ public class BluetoothConnectionManager { try { btSocket.close(); } catch (IOException e) { - Log.e(TAG, "close() of connect socket failed", e); + Log.e(Constants.TAG, "close() of connect socket failed", e); } } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothSensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothSensorManager.java index 233b792e6..a19013a2e 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothSensorManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothSensorManager.java @@ -15,8 +15,7 @@ */ package com.google.android.apps.mytracks.services.sensors; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; - +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.maps.mytracks.R; @@ -51,7 +50,7 @@ public class BluetoothSensorManager extends SensorManager { private Sensor.SensorDataSet sensorDataSet = null; private MessageParser parser; - + public BluetoothSensorManager( Context context, MessageParser parser) { this.context = context; @@ -67,7 +66,7 @@ public class BluetoothSensorManager extends SensorManager { } private void setupSensor() { - Log.d(TAG, "setupSensor()"); + Log.d(Constants.TAG, "setupSensor()"); // Initialize the BluetoothSensorAdapter to perform bluetooth connections. connectionManager = new BluetoothConnectionManager(messageHandler, parser); @@ -79,7 +78,7 @@ public class BluetoothSensorManager extends SensorManager { public void setupChannel() { if (!isEnabled() || connectionManager == null) { - Log.w(TAG, "Disabled manager onStartTrack"); + Log.w(Constants.TAG, "Disabled manager onStartTrack"); return; } SharedPreferences prefs = @@ -89,7 +88,7 @@ public class BluetoothSensorManager extends SensorManager { if (address == null) { return; } - Log.w(TAG, "Connecting to bluetooth sensor: " + address); + Log.w(Constants.TAG, "Connecting to bluetooth sensor: " + address); // Get the BluetoothDevice object BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); // Attempt to connect to the device @@ -103,7 +102,7 @@ public class BluetoothSensorManager extends SensorManager { // already if (connectionManager.getState() == Sensor.SensorState.NONE) { // Start the Bluetooth sensor services - Log.w(TAG, "Disabled manager onStartTrack"); + Log.w(Constants.TAG, "Disabled manager onStartTrack"); connectionManager.start(); } } @@ -133,7 +132,7 @@ public class BluetoothSensorManager extends SensorManager { switch (msg.what) { case BluetoothConnectionManager.MESSAGE_STATE_CHANGE: // TODO should we update the SensorManager state var? - Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1); + Log.i(Constants.TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1); break; case BluetoothConnectionManager.MESSAGE_WRITE: break; @@ -142,14 +141,15 @@ public class BluetoothSensorManager extends SensorManager { try { readBuf = (byte[]) msg.obj; sensorDataSet = parser.parseBuffer(readBuf); - Log.d(TAG, "MESSAGE_READ: " + sensorDataSet.toString()); + Log.d(Constants.TAG, "MESSAGE_READ: " + sensorDataSet.toString()); } catch (IllegalArgumentException iae) { sensorDataSet = null; - Log.i(TAG, "Got bad sensor data: " + new String(readBuf, 0, readBuf.length), + Log.i(Constants.TAG, + "Got bad sensor data: " + new String(readBuf, 0, readBuf.length), iae); } catch (RuntimeException re) { sensorDataSet = null; - Log.i(TAG, "Unexpected exception on read.", re); + Log.i(Constants.TAG, "Unexpected exception on read.", re); } break; case BluetoothConnectionManager.MESSAGE_DEVICE_NAME: diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManager.java index 6f55257ec..cb217e590 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManager.java @@ -15,14 +15,13 @@ */ package com.google.android.apps.mytracks.services.sensors; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; - -import com.google.android.apps.mytracks.content.Sensor; +import java.util.Timer; +import java.util.TimerTask; import android.util.Log; -import java.util.Timer; -import java.util.TimerTask; +import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.content.Sensor; /** * Manage the connection to a sensor. @@ -51,17 +50,19 @@ public abstract class SensorManager { private TimerTask checkSensorManager = new TimerTask() { @Override public void run() { - Log.i(TAG, "SensorManager state: " + getSensorState()); + Log.i(Constants.TAG, + "SensorManager state: " + getSensorState()); switch (getSensorState()) { case CONNECTING: long age = System.currentTimeMillis() - getSensorStateTimestamp(); if (age > 2 * RETRY_PERIOD) { - Log.i(TAG, "Retrying connecting SensorManager."); + Log.i(Constants.TAG, "Retrying connecting SensorManager."); setupChannel(); } break; case DISCONNECTED: - Log.i(TAG, "Re-registering disconnected SensorManager."); + Log.i(Constants.TAG, + "Re-registering disconnected SensoManager."); setupChannel(); break; } diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManagerFactory.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManagerFactory.java index f501fc8be..cf0d3a458 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManagerFactory.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManagerFactory.java @@ -1,12 +1,12 @@ /* * Copyright 2009 Google Inc. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -15,8 +15,7 @@ */ package com.google.android.apps.mytracks.services.sensors; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; - +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.maps.mytracks.R; @@ -30,7 +29,9 @@ import android.util.Log; * @author Sandor Dornbush */ public class SensorManagerFactory { - private SensorManagerFactory() {} + + private SensorManagerFactory() { + } /** * Get a new sensor manager. @@ -43,9 +44,9 @@ public class SensorManagerFactory { if (prefs == null) { return null; } - + String sensor = prefs.getString(context.getString(R.string.sensor_type_key), null); - Log.i(TAG, "Creating sensor of type: " + sensor); + Log.i(Constants.TAG, "Creating sensor of type: " + sensor); if (sensor == null) { return null; @@ -56,7 +57,7 @@ public class SensorManagerFactory { } else if (sensor.equals(context.getString(R.string.zephyr_sensor_type))) { return new ZephyrSensorManager(context); } else { - Log.w(TAG, "Unable to find sensor type: " + sensor); + Log.w(Constants.TAG, "Unable to find sensor type: " + sensor); return null; } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java index 6e5bf225d..da7a3672e 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java @@ -15,12 +15,11 @@ */ package com.google.android.apps.mytracks.services.sensors; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; - -import com.google.android.apps.mytracks.content.Sensor; - import android.util.Log; +import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.content.Sensor; + /** * An implementation of a SensorData parser for Zephyr HRM. * @@ -34,7 +33,7 @@ public class ZephyrMessageParser implements MessageParser { for (int i = 0; i < buffer.length; i++) { sb.append(String.format("%02X", buffer[i])); } - Log.w(TAG, "Got zephyr data: " + sb); + Log.w(Constants.TAG, "Got zephyr data: " + sb); // The provided units are 1/16 strides per minute. // TODO: Fix the cadence calculation. // int cadence = SensorUtils.unsignedShortToInt(buffer, 56); @@ -50,7 +49,7 @@ public class ZephyrMessageParser implements MessageParser { .setCreationTime(System.currentTimeMillis()) .setHeartRate(b) .build(); - + return sds; } diff --git a/MyTracks/src/com/google/android/apps/mytracks/stats/TripStatisticsBuilder.java b/MyTracks/src/com/google/android/apps/mytracks/stats/TripStatisticsBuilder.java index 0fdbd0ff8..5ca4c3d4f 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/stats/TripStatisticsBuilder.java +++ b/MyTracks/src/com/google/android/apps/mytracks/stats/TripStatisticsBuilder.java @@ -16,7 +16,9 @@ package com.google.android.apps.mytracks.stats; -import com.google.android.apps.mytracks.MyTracksConstants; +import static com.google.android.apps.mytracks.Constants.TAG; + +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.MyTracksSettings; import android.location.Location; @@ -65,25 +67,25 @@ public class TripStatisticsBuilder { * A buffer of the last speed readings in meters/second. */ private final DoubleBuffer speedBuffer = - new DoubleBuffer(MyTracksConstants.SPEED_SMOOTHING_FACTOR); + new DoubleBuffer(Constants.SPEED_SMOOTHING_FACTOR); /** * A buffer of the recent elevation readings in meters. */ private final DoubleBuffer elevationBuffer = - new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); + new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR); /** * A buffer of the distance between recent gps readings in meters. */ private final DoubleBuffer distanceBuffer = - new DoubleBuffer(MyTracksConstants.DISTANCE_SMOOTHING_FACTOR); + new DoubleBuffer(Constants.DISTANCE_SMOOTHING_FACTOR); /** * A buffer of the recent grade calculations. */ private final DoubleBuffer gradeBuffer = - new DoubleBuffer(MyTracksConstants.GRADE_SMOOTHING_FACTOR); + new DoubleBuffer(Constants.GRADE_SMOOTHING_FACTOR); /** * The total number of locations in this trip. @@ -126,7 +128,7 @@ public class TripStatisticsBuilder { */ public boolean addLocation(Location currentLocation, long systemTime) { if (paused) { - Log.w(MyTracksConstants.TAG, + Log.w(TAG, "Tried to account for location while track is paused"); return false; } @@ -151,7 +153,7 @@ public class TripStatisticsBuilder { // Don't do anything if we didn't move since last fix: double distance = lastLocation.distanceTo(currentLocation); if (distance < minRecordingDistance && - currentSpeed < MyTracksConstants.MAX_NO_MOVEMENT_SPEED) { + currentSpeed < Constants.MAX_NO_MOVEMENT_SPEED) { lastLocation = currentLocation; return false; } @@ -208,7 +210,7 @@ public class TripStatisticsBuilder { // We are now sure the user is moving. long timeDifference = updateTime - lastLocationTime; if (timeDifference < 0) { - Log.e(MyTracksConstants.TAG, + Log.e(TAG, "Found negative time change: " + timeDifference); } data.addMovingTime(timeDifference); @@ -224,7 +226,7 @@ public class TripStatisticsBuilder { data.setMaxSpeed(movingSpeed); } } else { - Log.d(MyTracksConstants.TAG, + Log.d(TAG, "TripStatistics ignoring big change: Raw Speed: " + speed + " old: " + lastLocationSpeed + " [" + toString() + "]"); } @@ -263,7 +265,7 @@ public class TripStatisticsBuilder { // likely. Ignore any speeds that imply accelaration greater than 2g's // Really who can accelerate faster? double speedDifference = Math.abs(lastLocationSpeed - speed); - if (speedDifference > MyTracksConstants.MAX_ACCELERATION * timeDifference) { + if (speedDifference > Constants.MAX_ACCELERATION * timeDifference) { return false; } @@ -275,7 +277,7 @@ public class TripStatisticsBuilder { double smoothedDiff = Math.abs(smoothedSpeed - speed); return !speedBuffer.isFull() || (speed < smoothedSpeed * 10 - && smoothedDiff < MyTracksConstants.MAX_ACCELERATION * timeDifference); + && smoothedDiff < Constants.MAX_ACCELERATION * timeDifference); } /** diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java b/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java index cb89e5cb7..26fb3a31c 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/ApiFeatures.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.util; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import android.os.Build; import android.util.Log; @@ -72,7 +72,7 @@ public class ApiFeatures { apiPlatformAdapter = new CupcakePlatformAdapter(); } - Log.i(MyTracksConstants.TAG, "Using platform adapter " + apiPlatformAdapter.getClass()); + Log.i(Constants.TAG, "Using platform adapter " + apiPlatformAdapter.getClass()); } public ApiPlatformAdapter getApiPlatformAdapter() { diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/BluetoothDeviceUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/BluetoothDeviceUtils.java index a819a8473..96e8bd878 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/BluetoothDeviceUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/BluetoothDeviceUtils.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.util; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; @@ -158,14 +158,14 @@ public abstract class BluetoothDeviceUtils { public static BluetoothDeviceUtils getInstance() { if (instance == null) { if (!isBluetoothMethodSupported()) { - Log.d(MyTracksConstants.TAG, "Using dummy bluetooth utils"); + Log.d(Constants.TAG, "Using dummy bluetooth utils"); instance = new DummyImpl(); } else { - Log.d(MyTracksConstants.TAG, "Using real bluetooth utils"); + Log.d(Constants.TAG, "Using real bluetooth utils"); try { instance = new RealImpl(); } catch (IllegalStateException ise) { - Log.w(MyTracksConstants.TAG, "Oops, I mean, using dummy bluetooth utils", ise); + Log.w(Constants.TAG, "Oops, I mean, using dummy bluetooth utils", ise); instance = new DummyImpl(); } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/CupcakePlatformAdapter.java b/MyTracks/src/com/google/android/apps/mytracks/util/CupcakePlatformAdapter.java index c7704959e..abdd9dfb7 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/CupcakePlatformAdapter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/CupcakePlatformAdapter.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.util; -import static com.google.android.apps.mytracks.MyTracksConstants.TAG; +import static com.google.android.apps.mytracks.Constants.TAG; import android.app.Notification; import android.app.NotificationManager; import android.app.Service; diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/FileUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/FileUtils.java index 6c6ca7af0..ac63cbba5 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/FileUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/FileUtils.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.util; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import android.os.Environment; @@ -49,7 +49,7 @@ public class FileUtils { StringBuilder dirNameBuilder = new StringBuilder(); dirNameBuilder.append(Environment.getExternalStorageDirectory()); dirNameBuilder.append(File.separatorChar); - dirNameBuilder.append(MyTracksConstants.SDCARD_TOP_DIR); + dirNameBuilder.append(Constants.SDCARD_TOP_DIR); for (String component : components) { dirNameBuilder.append(File.separatorChar); dirNameBuilder.append(component); diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/GingerbreadPlatformAdapter.java b/MyTracks/src/com/google/android/apps/mytracks/util/GingerbreadPlatformAdapter.java index 129ac1451..35d7eb3d6 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/GingerbreadPlatformAdapter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/GingerbreadPlatformAdapter.java @@ -1,6 +1,6 @@ package com.google.android.apps.mytracks.util; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import android.content.SharedPreferences.Editor; import android.os.StrictMode; @@ -21,7 +21,7 @@ public class GingerbreadPlatformAdapter extends EclairPlatformAdapter { @Override public void enableStrictMode() { - Log.d(MyTracksConstants.TAG, "Enabling strict mode"); + Log.d(Constants.TAG, "Enabling strict mode"); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskWrites() .detectNetwork() diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/MyTracksUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/MyTracksUtils.java index 59ba09b3d..4cadca845 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/MyTracksUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/MyTracksUtils.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.util; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.stats.TripStatistics; @@ -146,7 +146,7 @@ public class MyTracksUtils { } idx++; } - Log.d(MyTracksConstants.TAG, "Decimating " + n + " points to " + i + Log.d(Constants.TAG, "Decimating " + n + " points to " + i + " w/ tolerance = " + tolerance); } @@ -268,7 +268,7 @@ public class MyTracksUtils { } } } catch (NameNotFoundException e) { - Log.e(MyTracksConstants.TAG, "Unable to get signatures", e); + Log.e(Constants.TAG, "Unable to get signatures", e); } return false; } @@ -285,7 +285,7 @@ public class MyTracksUtils { PackageManager.GET_META_DATA); return pi.versionName; } catch (NameNotFoundException e) { - Log.w(MyTracksConstants.TAG, "Failed to get version info.", e); + Log.w(Constants.TAG, "Failed to get version info.", e); return ""; } } @@ -295,19 +295,19 @@ public class MyTracksUtils { * and gives up trying in case the wake lock cannot be acquired. */ public static WakeLock acquireWakeLock(Activity activity, WakeLock wakeLock) { - Log.i(MyTracksConstants.TAG, "MyTracksUtils: Acquiring wake lock."); + Log.i(Constants.TAG, "MyTracksUtils: Acquiring wake lock."); try { PowerManager pm = (PowerManager) activity .getSystemService(Context.POWER_SERVICE); if (pm == null) { - Log.e(MyTracksConstants.TAG, "MyTracksUtils: Power manager not found!"); + Log.e(Constants.TAG, "MyTracksUtils: Power manager not found!"); return wakeLock; } if (wakeLock == null) { wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - MyTracksConstants.TAG); + Constants.TAG); if (wakeLock == null) { - Log.e(MyTracksConstants.TAG, + Log.e(Constants.TAG, "MyTracksUtils: Could not create wake lock (null)."); } return wakeLock; @@ -315,12 +315,12 @@ public class MyTracksUtils { if (!wakeLock.isHeld()) { wakeLock.acquire(); if (!wakeLock.isHeld()) { - Log.e(MyTracksConstants.TAG, + Log.e(Constants.TAG, "MyTracksUtils: Could not acquire wake lock."); } } } catch (RuntimeException e) { - Log.e(MyTracksConstants.TAG, + Log.e(Constants.TAG, "MyTracksUtils: Caught unexpected exception: " + e.getMessage(), e); } return wakeLock; diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/MyTracksTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/MyTracksTest.java index 545c09450..7c5151944 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/MyTracksTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/MyTracksTest.java @@ -165,7 +165,7 @@ public class MyTracksTest extends ActivityInstrumentationTestCase2{ // Watch for MyTracksDetails activity. ActivityMonitor monitor = getInstrumentation().addMonitor( - MyTracksDetails.class.getName(), null, false); + TrackDetails.class.getName(), null, false); // Now, stop the track and make sure that it is still selected, but // no longer recording. @@ -173,7 +173,7 @@ public class MyTracksTest extends ActivityInstrumentationTestCase2{ // Check if we got back MyTracksDetails activity. Activity activity = getInstrumentation().waitForMonitor(monitor); - assertTrue(activity instanceof MyTracksDetails); + assertTrue(activity instanceof TrackDetails); // TODO: Update track name and other properties and test if they were // properly saved. diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/TcxTrackWriterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/TcxTrackWriterTest.java index 897df2792..e07f1ae55 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/TcxTrackWriterTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/TcxTrackWriterTest.java @@ -4,21 +4,32 @@ package com.google.android.apps.mytracks.io; import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.Sensor; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.TimeZone; + import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.util.Date; -import java.util.List; - /** * Tests for the GPX track exporter. * * @author Sandor Dornbush */ public class TcxTrackWriterTest extends TrackFormatWriterTest { + private DateFormat timestampFormatter; + + @Override + public void setUp() throws Exception { + super.setUp(); + + timestampFormatter = new SimpleDateFormat(TcxTrackWriter.TIMESTAMP_FORMAT); + timestampFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); + } public void testXmlOutput() throws Exception { - TrackFormatWriter writer = new TcxTrackWriter(); + TrackFormatWriter writer = new TcxTrackWriter(getContext()); String result = writeTrack(writer); Document doc = parseXmlDocument(result); @@ -58,8 +69,8 @@ public class TcxTrackWriterTest extends TrackFormatWriterTest { getChildTextValue(posTag, "LatitudeDegrees")); assertEquals(Double.toString(loc.getLongitude()), getChildTextValue(posTag, "LongitudeDegrees")); - assertEquals( - TcxTrackWriter.TIMESTAMP_FORMAT.format(new Date(loc.getTime())), + + assertEquals(timestampFormatter.format(loc.getTime()), getChildTextValue(tag, "Time")); assertEquals(Double.toString(loc.getAltitude()), getChildTextValue(tag, "AltitudeMeters")); diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/backup/PreferenceBackupHelperTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/backup/PreferenceBackupHelperTest.java index 22561507c..25a6c2504 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/backup/PreferenceBackupHelperTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/backup/PreferenceBackupHelperTest.java @@ -82,7 +82,6 @@ public class PreferenceBackupHelperTest extends TestCase { return put(key, value); } - @Override public Editor putStringSet(String key, Set value) { return put(key, value); } @@ -143,7 +142,6 @@ public class PreferenceBackupHelperTest extends TestCase { return get(key, defValue); } - @Override public Set getStringSet(String key, Set defValue) { return get(key, defValue); } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java index db0236aa2..b2d2f21f8 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.services; -import static com.google.android.apps.mytracks.MyTracksConstants.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.content.MyTracksProvider; diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/stats/TripStatisticsBuilderTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/stats/TripStatisticsBuilderTest.java index ccb3fa858..750bc31de 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/stats/TripStatisticsBuilderTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/stats/TripStatisticsBuilderTest.java @@ -2,7 +2,7 @@ package com.google.android.apps.mytracks.stats; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import android.location.Location; @@ -56,18 +56,18 @@ public class TripStatisticsBuilderTest extends TestCase { assertEquals(10000 * i, stats.getTotalTime()); assertEquals(10000 * i, stats.getMovingTime()); assertEquals(i, builder.getSmoothedElevation(), - MyTracksConstants.ELEVATION_SMOOTHING_FACTOR / 2); + Constants.ELEVATION_SMOOTHING_FACTOR / 2); assertEquals(0.0, stats.getMinElevation()); assertEquals(i, stats.getMaxElevation(), - MyTracksConstants.ELEVATION_SMOOTHING_FACTOR / 2); + Constants.ELEVATION_SMOOTHING_FACTOR / 2); assertEquals(i, stats.getTotalElevationGain(), - MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); + Constants.ELEVATION_SMOOTHING_FACTOR); - if (i > MyTracksConstants.SPEED_SMOOTHING_FACTOR) { + if (i > Constants.SPEED_SMOOTHING_FACTOR) { assertEquals(11.1f, stats.getMaxSpeed(), 0.1); } - if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR) - && (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) { + if ((i > Constants.GRADE_SMOOTHING_FACTOR) + && (i > Constants.ELEVATION_SMOOTHING_FACTOR)) { assertEquals(0.009, stats.getMinGrade(), 0.0001); assertEquals(0.009, stats.getMaxGrade(), 0.0001); } @@ -97,9 +97,9 @@ public class TripStatisticsBuilderTest extends TestCase { public void testElevationGain() throws Exception { for (double i = 0; i < 1000; i++) { double expectedGain; - if (i < (MyTracksConstants.ELEVATION_SMOOTHING_FACTOR - 1)) { + if (i < (Constants.ELEVATION_SMOOTHING_FACTOR - 1)) { expectedGain = 0; - } else if (i < MyTracksConstants.ELEVATION_SMOOTHING_FACTOR) { + } else if (i < Constants.ELEVATION_SMOOTHING_FACTOR) { expectedGain = 0.5; } else { expectedGain = 1.0; @@ -110,9 +110,9 @@ public class TripStatisticsBuilderTest extends TestCase { TripStatistics data = builder.getStatistics(); assertEquals(0.0, data.getMinElevation(), 0.0); assertEquals(i, data.getMaxElevation(), - MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); + Constants.ELEVATION_SMOOTHING_FACTOR); assertEquals(i, data.getTotalElevationGain(), - MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); + Constants.ELEVATION_SMOOTHING_FACTOR); } } @@ -122,8 +122,8 @@ public class TripStatisticsBuilderTest extends TestCase { // buffer. builder.updateElevation(i); builder.updateGrade(100, 100); - if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR) - && (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) { + if ((i > Constants.GRADE_SMOOTHING_FACTOR) + && (i > Constants.ELEVATION_SMOOTHING_FACTOR)) { assertEquals(1.0, builder.getStatistics().getMaxGrade()); assertEquals(1.0, builder.getStatistics().getMinGrade()); } @@ -133,8 +133,8 @@ public class TripStatisticsBuilderTest extends TestCase { // buffer. builder.updateElevation(i); builder.updateGrade(100, -100); - if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR) - && (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) { + if ((i > Constants.GRADE_SMOOTHING_FACTOR) + && (i > Constants.ELEVATION_SMOOTHING_FACTOR)) { assertEquals(1.0, builder.getStatistics().getMaxGrade()); assertEquals(-1.0, builder.getStatistics().getMinGrade()); } @@ -176,7 +176,7 @@ public class TripStatisticsBuilderTest extends TestCase { for (int i = 0; i < 1000; i++) { builder.updateSpeed(i + 1000, 4.0, i, 4.0); assertEquals((i + 1) * 1000, builder.getStatistics().getMovingTime()); - if (i > MyTracksConstants.SPEED_SMOOTHING_FACTOR) { + if (i > Constants.SPEED_SMOOTHING_FACTOR) { assertEquals(4.0, builder.getStatistics().getMaxSpeed()); } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/util/FileUtilsTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/util/FileUtilsTest.java index 01b44c6b6..9cd32f498 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/util/FileUtilsTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/util/FileUtilsTest.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks.util; -import com.google.android.apps.mytracks.MyTracksConstants; +import com.google.android.apps.mytracks.Constants; import android.os.Environment; @@ -53,7 +53,7 @@ public class FileUtilsTest extends TestCase { public void testBuildExternalDirectoryPath() { String expectedName = Environment.getExternalStorageDirectory() + File.separator - + MyTracksConstants.SDCARD_TOP_DIR + + Constants.SDCARD_TOP_DIR + File.separator + "a" + File.separator diff --git a/scripts/cat_message b/scripts/cat_message new file mode 100755 index 000000000..a99e19627 --- /dev/null +++ b/scripts/cat_message @@ -0,0 +1,56 @@ +#!/bin/bash +# +# Copyright 2010 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. + +# This script retrieves the value of a given named string from all indicated +# strings.xml files. If invoked in a project directory (a directory with a +# 'res' subdirectory), and if no strings.xml files are provided, the script +# will automatically analyze res/values*/strings.xml + +PROGNAME=$(basename "$0") + +function usage() { + echo "Usage: ${PROGNAME} string_name [file file..]" >&2 + exit 2 +} + +function die() { + echo "${PROGNAME}: $@" >&2 + exit 1 +} + +if [[ "$#" -lt 1 ]] ; then + usage +fi + +name=$1 +shift + +files= +if [[ $# -eq 0 ]] ; then + if [[ -d res ]] ; then + files=res/values*/strings.xml + else + die "invoked outside of project root with no file arguments" + fi +else + files="$@" +fi + +for file in $files ; do + echo === $file + xmllint --xpath /resources/string[@name=\"$name\"] $file + echo +done