Merging to Sandor's renaming.

This commit is contained in:
Rodrigo Damazio
2011-03-21 01:10:26 -07:00
89 changed files with 2720 additions and 849 deletions
-1
View File
@@ -5,4 +5,3 @@ syntax:glob
*/proguard/** */proguard/**
.metadata .metadata
MyTracksTest/annotations.log MyTracksTest/annotations.log
MyTracks/src/com/google/android/apps/mytracks/io/mymaps
-1
View File
@@ -8,7 +8,6 @@
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/> <classpathentry kind="src" path="gen"/>
<classpathentry exported="true" kind="lib" path="/MyTracksLib/libs/protobuf-java-2.3.0-lite.jar"/> <classpathentry exported="true" kind="lib" path="/MyTracksLib/libs/protobuf-java-2.3.0-lite.jar"/>
<classpathentry kind="lib" path="libs/libmymaps.jar"/>
<classpathentry kind="src" path="MyTracksLib_src"/> <classpathentry kind="src" path="MyTracksLib_src"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>
+6 -6
View File
@@ -17,8 +17,8 @@ limitations under the License.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.maps.mytracks" package="com.google.android.maps.mytracks"
android:installLocation="auto" android:installLocation="auto"
android:versionCode="25" android:versionCode="26"
android:versionName="1.1.3rc1"> android:versionName="1.1.4rc1">
<application android:icon="@drawable/arrow_icon" <application android:icon="@drawable/arrow_icon"
android:label="@string/app_name" android:label="@string/app_name"
android:backupAgent="com.google.android.apps.mytracks.io.backup.MyTracksBackupAgent"> android:backupAgent="com.google.android.apps.mytracks.io.backup.MyTracksBackupAgent">
@@ -61,16 +61,16 @@ limitations under the License.
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|fontScale" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|fontScale"
android:exported="false" /> android:exported="false" />
<activity android:name="com.google.android.apps.mytracks.MyTracksList" <activity android:name="com.google.android.apps.mytracks.TrackList"
android:label="Recorded Tracks" /> android:label="Recorded Tracks" />
<activity android:name="com.google.android.apps.mytracks.MyTracksWaypointsList" <activity android:name="com.google.android.apps.mytracks.WaypointsList"
android:label="Recorded Waypoints" /> android:label="Recorded Waypoints" />
<activity android:name="com.google.android.apps.mytracks.MyTracksDetails" <activity android:name="com.google.android.apps.mytracks.TrackDetails"
android:label="@string/trackdetails_title" /> android:label="@string/trackdetails_title" />
<activity android:name="com.google.android.apps.mytracks.MyTracksWaypointDetails" <activity android:name="com.google.android.apps.mytracks.WaypointDetails"
android:label="@string/waypointdetails_title" /> android:label="@string/waypointdetails_title" />
<activity android:name="com.google.android.apps.mytracks.MyTracksSettings" <activity android:name="com.google.android.apps.mytracks.MyTracksSettings"
Binary file not shown.
+1 -1
View File
@@ -253,7 +253,7 @@ limitations under the License.
<string name="send_track_subject">Ich möchte einen GPS-Track mit Dir teilen</string> <string name="send_track_subject">Ich möchte einen GPS-Track mit Dir teilen</string>
<string name="send_track_body_format">Vielleicht interessierst Du Dich für diese Track: <string name="send_track_body_format">Vielleicht interessierst Du Dich für diese Track:
%s.</string> Der Track kann mit Google Earth oder anderer Karten-Software visualisiert werden.</string>
<string name="share_track">Track mit Freunden teilen</string> <string name="share_track">Track mit Freunden teilen</string>
<!-- Visibility --> <!-- Visibility -->
@@ -59,7 +59,7 @@ public class AccountChooser {
public void chooseAccount(final Activity activity, public void chooseAccount(final Activity activity,
final AccountHandler handler) { final AccountHandler handler) {
final Account[] accounts = AccountManager.get(activity) final Account[] accounts = AccountManager.get(activity)
.getAccountsByType(MyTracksConstants.ACCOUNT_TYPE); .getAccountsByType(Constants.ACCOUNT_TYPE);
if (accounts.length < 1) { if (accounts.length < 1) {
alertNoAccounts(activity, handler); alertNoAccounts(activity, handler);
return; return;
@@ -76,7 +76,7 @@ public class AccountChooser {
} }
// Let the user choose. // 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); final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.choose_account_title); builder.setTitle(R.string.choose_account_title);
builder.setCancelable(false); builder.setCancelable(false);
@@ -112,7 +112,7 @@ public class AccountChooser {
*/ */
private void alertNoAccounts(final Activity activity, private void alertNoAccounts(final Activity activity,
final AccountHandler handler) { 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); final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.no_account_found_title); builder.setTitle(R.string.no_account_found_title);
builder.setMessage(R.string.no_account_found); builder.setMessage(R.string.no_account_found);
@@ -40,7 +40,7 @@ public class AggregatedStatsActivity extends Activity implements
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) { String key) {
Log.d(MyTracksConstants.TAG, "StatsActivity: onSharedPreferences changed " Log.d(Constants.TAG, "StatsActivity: onSharedPreferences changed "
+ key); + key);
if (key != null) { if (key != null) {
if (key.equals(R.string.metric_units_key)) { if (key.equals(R.string.metric_units_key)) {
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks; 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.ChartView.Mode;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
@@ -55,9 +55,9 @@ import java.util.ArrayList;
public class ChartActivity extends Activity implements TrackDataListener { public class ChartActivity extends Activity implements TrackDataListener {
private final DoubleBuffer elevationBuffer = private final DoubleBuffer elevationBuffer =
new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
private final DoubleBuffer speedBuffer = private final DoubleBuffer speedBuffer =
new DoubleBuffer(MyTracksConstants.SPEED_SMOOTHING_FACTOR); new DoubleBuffer(Constants.SPEED_SMOOTHING_FACTOR);
private final ArrayList<double[]> pendingPoints = new ArrayList<double[]>(); private final ArrayList<double[]> pendingPoints = new ArrayList<double[]>();
private TrackDataHub dataHub; private TrackDataHub dataHub;
@@ -186,7 +186,7 @@ public class ChartActivity extends Activity implements TrackDataListener {
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu); super.onCreateOptionsMenu(menu);
chartSettingsMenuItem = chartSettingsMenuItem =
menu.add(0, MyTracksConstants.MENU_CHART_SETTINGS, 0, menu.add(0, Constants.MENU_CHART_SETTINGS, 0,
R.string.chart_settings); R.string.chart_settings);
chartSettingsMenuItem.setIcon(R.drawable.chart_settings); chartSettingsMenuItem.setIcon(R.drawable.chart_settings);
return true; return true;
@@ -195,7 +195,7 @@ public class ChartActivity extends Activity implements TrackDataListener {
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case MyTracksConstants.MENU_CHART_SETTINGS: case Constants.MENU_CHART_SETTINGS:
MyTracks.getInstance().getDialogManager().showDialogSafely( MyTracks.getInstance().getDialogManager().showDialogSafely(
DialogManager.DIALOG_CHART_SETTINGS); DialogManager.DIALOG_CHART_SETTINGS);
return true; return true;
@@ -527,7 +527,7 @@ public class ChartView extends View {
} }
if (nearestWaypoint != null && dmin < 100) { if (nearestWaypoint != null && dmin < 100) {
Intent intent = Intent intent =
new Intent(getContext(), MyTracksWaypointDetails.class); new Intent(getContext(), WaypointDetails.class);
intent.putExtra("waypointid", nearestWaypoint.getId()); intent.putExtra("waypointid", nearestWaypoint.getId());
getContext().startActivity(intent); getContext().startActivity(intent);
return true; return true;
@@ -20,7 +20,7 @@ package com.google.android.apps.mytracks;
* *
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
*/ */
public abstract class MyTracksConstants { public abstract class Constants {
/** /**
* Should be used by all log statements * Should be used by all log statements
@@ -188,32 +188,32 @@ public abstract class MyTracksConstants {
public static int getActionFromMenuId(int menuId) { public static int getActionFromMenuId(int menuId) {
switch (menuId) { switch (menuId) {
case MyTracksConstants.MENU_SEND_TO_GOOGLE: case Constants.MENU_SEND_TO_GOOGLE:
return MyTracksConstants.SEND_TO_GOOGLE_DIALOG; return Constants.SEND_TO_GOOGLE_DIALOG;
case MyTracksConstants.MENU_EDIT: case Constants.MENU_EDIT:
return MyTracksConstants.EDIT_DETAILS; return Constants.EDIT_DETAILS;
case MyTracksConstants.MENU_DELETE: case Constants.MENU_DELETE:
return MyTracksConstants.DELETE_TRACK; return Constants.DELETE_TRACK;
case MyTracksConstants.MENU_SHARE_LINK: case Constants.MENU_SHARE_LINK:
return MyTracksConstants.SHARE_LINK; return Constants.SHARE_LINK;
case MyTracksConstants.MENU_SHARE_KML_FILE: case Constants.MENU_SHARE_KML_FILE:
return MyTracksConstants.SHARE_KML_FILE; return Constants.SHARE_KML_FILE;
case MyTracksConstants.MENU_SHARE_GPX_FILE: case Constants.MENU_SHARE_GPX_FILE:
return MyTracksConstants.SHARE_GPX_FILE; return Constants.SHARE_GPX_FILE;
case MyTracksConstants.MENU_SHARE_CSV_FILE: case Constants.MENU_SHARE_CSV_FILE:
return MyTracksConstants.SHARE_CSV_FILE; return Constants.SHARE_CSV_FILE;
case MyTracksConstants.MENU_SHARE_TCX_FILE: case Constants.MENU_SHARE_TCX_FILE:
return MyTracksConstants.SHARE_TCX_FILE; return Constants.SHARE_TCX_FILE;
case MyTracksConstants.MENU_SAVE_GPX_FILE: case Constants.MENU_SAVE_GPX_FILE:
return MyTracksConstants.SAVE_GPX_FILE; return Constants.SAVE_GPX_FILE;
case MyTracksConstants.MENU_SAVE_KML_FILE: case Constants.MENU_SAVE_KML_FILE:
return MyTracksConstants.SAVE_KML_FILE; return Constants.SAVE_KML_FILE;
case MyTracksConstants.MENU_SAVE_CSV_FILE: case Constants.MENU_SAVE_CSV_FILE:
return MyTracksConstants.SAVE_CSV_FILE; return Constants.SAVE_CSV_FILE;
case MyTracksConstants.MENU_SAVE_TCX_FILE: case Constants.MENU_SAVE_TCX_FILE:
return MyTracksConstants.SAVE_TCX_FILE; return Constants.SAVE_TCX_FILE;
case MyTracksConstants.MENU_CLEAR_MAP: case Constants.MENU_CLEAR_MAP:
return MyTracksConstants.CLEAR_MAP; return Constants.CLEAR_MAP;
default: default:
return -1; return -1;
} }
@@ -225,5 +225,5 @@ public abstract class MyTracksConstants {
/** /**
* This is an abstract utility class. * This is an abstract utility class.
*/ */
protected MyTracksConstants() { } protected Constants() { }
} }
@@ -34,12 +34,12 @@ import android.util.Log;
* *
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
*/ */
public class MyTracksDeleteAllTracks extends Handler { public class DeleteAllTracks extends Handler {
private final Context context; private final Context context;
private final Runnable done; private final Runnable done;
public MyTracksDeleteAllTracks(Context context, Runnable done) { public DeleteAllTracks(Context context, Runnable done) {
this.context = context; this.context = context;
this.done = done; this.done = done;
} }
@@ -58,7 +58,7 @@ public class MyTracksDeleteAllTracks extends Handler {
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int i) { public void onClick(DialogInterface dialog, int i) {
dialog.dismiss(); dialog.dismiss();
Log.w(MyTracksConstants.TAG, "deleting all!"); Log.w(Constants.TAG, "deleting all!");
MyTracksProviderUtils.Factory.get(context).deleteAllTracks(); MyTracksProviderUtils.Factory.get(context).deleteAllTracks();
SharedPreferences prefs = SharedPreferences prefs =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
@@ -15,6 +15,8 @@
*/ */
package com.google.android.apps.mytracks; 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.apps.mytracks.io.sendtogoogle.SendDialog;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -96,7 +98,7 @@ public class DialogManager {
activity.resetSendToGoogleStatus(); activity.resetSendToGoogleStatus();
break; break;
case DIALOG_CHART_SETTINGS: case DIALOG_CHART_SETTINGS:
Log.d(MyTracksConstants.TAG, "MyTracks.onPrepare chart dialog"); Log.d(TAG, "MyTracks.onPrepare chart dialog");
chartSettingsDialog.setup(activity.getChartActivity()); chartSettingsDialog.setup(activity.getChartActivity());
break; break;
} }
@@ -170,11 +172,9 @@ public class DialogManager {
try { try {
activity.showDialog(id); activity.showDialog(id);
} catch (BadTokenException e) { } catch (BadTokenException e) {
Log.w(MyTracksConstants.TAG, Log.w(TAG, "Could not display dialog with id " + id, e);
"Could not display dialog with id " + id, e);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
Log.w(MyTracksConstants.TAG, Log.w(TAG, "Could not display dialog with id " + id, e);
"Could not display dialog with id " + id, e);
} }
} }
}); });
@@ -190,9 +190,9 @@ public class DialogManager {
try { try {
dialog.show(); dialog.show();
} catch (BadTokenException e) { } catch (BadTokenException e) {
Log.w(MyTracksConstants.TAG, "Could not display dialog", e); Log.w(TAG, "Could not display dialog", e);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
Log.w(MyTracksConstants.TAG, "Could not display dialog", e); Log.w(TAG, "Could not display dialog", e);
} }
} }
}); });
@@ -98,7 +98,7 @@ class Eula {
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges( ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(
preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true)); preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true));
Intent startIntent = new Intent(activity, WelcomeActivity.class); Intent startIntent = new Intent(activity, WelcomeActivity.class);
activity.startActivityForResult(startIntent, MyTracksConstants.WELCOME); activity.startActivityForResult(startIntent, Constants.WELCOME);
} }
private static void refuse(Activity activity) { private static void refuse(Activity activity) {
@@ -71,14 +71,14 @@ public class ExportAllTracks {
format = TrackFileFormat.TCX; format = TrackFileFormat.TCX;
break; break;
default: default:
Log.w(MyTracksConstants.TAG, "Unknown export format: " + which); Log.w(Constants.TAG, "Unknown export format: " + which);
} }
} }
}; };
public ExportAllTracks(Activity activity) { public ExportAllTracks(Activity activity) {
this.activity = activity; this.activity = activity;
Log.i(MyTracksConstants.TAG, "ExportAllTracks: Starting"); Log.i(Constants.TAG, "ExportAllTracks: Starting");
AlertDialog.Builder builder = new AlertDialog.Builder(activity); AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setSingleChoiceItems(R.array.export_formats, 0, itemClick); 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. // TODO check what happens if we started recording after getting this lock.
if (wakeLock != null && wakeLock.isHeld()) { if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release(); 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(); Toast.makeText(activity, R.string.export_done, Toast.LENGTH_SHORT).show();
} }
@@ -163,7 +163,7 @@ public class ExportAllTracks {
} }
final int trackCount = cursor.getCount(); final int trackCount = cursor.getCount();
Log.i(MyTracksConstants.TAG, Log.i(Constants.TAG,
"ExportAllTracks: Exporting: " + cursor.getCount() + " tracks."); "ExportAllTracks: Exporting: " + cursor.getCount() + " tracks.");
int idxTrackId = cursor.getColumnIndexOrThrow(TracksColumns._ID); int idxTrackId = cursor.getColumnIndexOrThrow(TracksColumns._ID);
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@@ -186,7 +186,7 @@ public class ExportAllTracks {
}); });
long id = cursor.getLong(idxTrackId); long id = cursor.getLong(idxTrackId);
Log.i(MyTracksConstants.TAG, "ExportAllTracks: exporting: " + id); Log.i(Constants.TAG, "ExportAllTracks: exporting: " + id);
TrackWriter writer = TrackWriter writer =
TrackWriterFactory.newWriter(activity, providerUtils, id, format); TrackWriterFactory.newWriter(activity, providerUtils, id, format);
writer.writeTrack(); writer.writeTrack();
@@ -60,7 +60,7 @@ public class ImportAllTracks {
public ImportAllTracks(Activity activity) { public ImportAllTracks(Activity activity) {
this.activity = activity; this.activity = activity;
Log.i(MyTracksConstants.TAG, "ImportAllTracks: Starting"); Log.i(Constants.TAG, "ImportAllTracks: Starting");
fileUtils = new FileUtils(); fileUtils = new FileUtils();
gpxPath = fileUtils.buildExternalDirectoryPath("gpx"); gpxPath = fileUtils.buildExternalDirectoryPath("gpx");
HandlerThread handlerThread; HandlerThread handlerThread;
@@ -98,10 +98,10 @@ public class ImportAllTracks {
// TODO check what happens if we started recording after getting this lock. // TODO check what happens if we started recording after getting this lock.
if (wakeLock != null && wakeLock.isHeld()) { if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release(); 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); AlertDialog.Builder builder = new AlertDialog.Builder(activity);
if (gpxFileCount == 0) { if (gpxFileCount == 0) {
builder.setMessage(activity.getString(R.string.import_empty, gpxPath + "/")); builder.setMessage(activity.getString(R.string.import_empty, gpxPath + "/"));
@@ -141,7 +141,7 @@ public class ImportAllTracks {
return; return;
} }
Log.i(MyTracksConstants.TAG, "ImportAllTracks: Importing: " + gpxFileCount + " tracks."); Log.i(Constants.TAG, "ImportAllTracks: Importing: " + gpxFileCount + " tracks.");
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
public void run() { public void run() {
makeProgressDialog(gpxFileCount); makeProgressDialog(gpxFileCount);
@@ -180,19 +180,19 @@ public class ImportAllTracks {
* notifications and returns false on failure. * notifications and returns false on failure.
*/ */
private boolean importFile(File gpxFile, MyTracksProviderUtils providerUtils) { private boolean importFile(File gpxFile, MyTracksProviderUtils providerUtils) {
Log.i(MyTracksConstants.TAG, "ImportAllTracks: importing: " + gpxFile.getName()); Log.i(Constants.TAG, "ImportAllTracks: importing: " + gpxFile.getName());
try { try {
GpxImporter.importGPXFile(new FileInputStream(gpxFile), providerUtils); GpxImporter.importGPXFile(new FileInputStream(gpxFile), providerUtils);
return true; return true;
} catch (FileNotFoundException e) { } 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); + gpxFile.getAbsolutePath(), e);
} catch (ParserConfigurationException 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) { } 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) { } 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.makeText(activity, activity.getString(R.string.import_error, gpxFile.getName()),
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();
@@ -64,14 +64,14 @@ class MenuManager {
return true; return true;
} }
case R.id.menu_list_tracks: { case R.id.menu_list_tracks: {
activity.startActivityForResult(new Intent(activity, MyTracksList.class), activity.startActivityForResult(new Intent(activity, TrackList.class),
MyTracksConstants.SHOW_TRACK); Constants.SHOW_TRACK);
return true; return true;
} }
case R.id.menu_list_markers: { 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()); startIntent.putExtra("trackid", activity.getSelectedTrackId());
activity.startActivityForResult(startIntent, MyTracksConstants.SHOW_WAYPOINT); activity.startActivityForResult(startIntent, Constants.SHOW_WAYPOINT);
return true; return true;
} }
case R.id.menu_sensor_state: { case R.id.menu_sensor_state: {
@@ -86,7 +86,7 @@ class MenuManager {
case R.id.menu_help: { case R.id.menu_help: {
return startActivity(WelcomeActivity.class); return startActivity(WelcomeActivity.class);
} }
case MyTracksConstants.MENU_CLEAR_MAP: { case Constants.MENU_CLEAR_MAP: {
activity.clearSelectedTrack(); activity.clearSelectedTrack();
return true; return true;
} }
@@ -18,9 +18,8 @@ package com.google.android.apps.mytracks;
import com.google.android.accounts.Account; import com.google.android.accounts.Account;
import com.google.android.apps.mytracks.io.AuthManager; import com.google.android.apps.mytracks.io.AuthManager;
import com.google.android.apps.mytracks.io.AuthManagerFactory; import com.google.android.apps.mytracks.io.AuthManagerFactory;
import com.google.android.apps.mytracks.io.MyMapsFactory;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade; import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
import com.google.android.apps.mytracks.io.mymaps.MapsService; import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Activity; import android.app.Activity;
@@ -84,7 +83,7 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
super.onCreate(icicle); super.onCreate(icicle);
auth = AuthManagerFactory.getAuthManager(this, GET_LOGIN, null, true, auth = AuthManagerFactory.getAuthManager(this, GET_LOGIN, null, true,
MapsService.getServiceName()); MyMapsConstants.SERVICE_NAME);
setContentView(R.layout.list); setContentView(R.layout.list);
@@ -125,7 +124,7 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
auth.doLogin(new Runnable() { auth.doLogin(new Runnable() {
public void run() { public void run() {
// Runs in UI thread. // Runs in UI thread.
mapsClient = MyMapsFactory.newMapsClient(MyMapsList.this, auth); mapsClient = new MapsFacade(MyMapsList.this, auth);
startLookup(); startLookup();
} }
@@ -200,7 +199,7 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
shareIntent.putExtra(Intent.EXTRA_TEXT, String.format( shareIntent.putExtra(Intent.EXTRA_TEXT, String.format(
getText(R.string.share_map_body_format).toString(), getText(R.string.share_map_body_format).toString(),
listItem[1], listItem[1],
MapsService.buildMapUrl(listItem[0]))); MapsFacade.buildMapUrl(listItem[0])));
startActivity(Intent.createChooser(shareIntent, startActivity(Intent.createChooser(shareIntent,
getText(R.string.share_map).toString())); getText(R.string.share_map).toString()));
return true; return true;
@@ -15,6 +15,7 @@
*/ */
package com.google.android.apps.mytracks; 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_IMPORT_PROGRESS;
import static com.google.android.apps.mytracks.DialogManager.DIALOG_PROGRESS; import static com.google.android.apps.mytracks.DialogManager.DIALOG_PROGRESS;
import static com.google.android.apps.mytracks.DialogManager.DIALOG_SEND_TO_GOOGLE; 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.TrackWriter;
import com.google.android.apps.mytracks.io.TrackWriterFactory; import com.google.android.apps.mytracks.io.TrackWriterFactory;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat; 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.ResultDialogFactory;
import com.google.android.apps.mytracks.io.sendtogoogle.SendDialog; import com.google.android.apps.mytracks.io.sendtogoogle.SendDialog;
import com.google.android.apps.mytracks.io.sendtogoogle.SendResult; 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() { private final ServiceConnection serviceConnection = new ServiceConnection() {
@Override @Override
public void onServiceConnected(ComponentName className, IBinder service) { 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. // Delay setting the service until we are done with initialization.
ITrackRecordingService trackRecordingService = ITrackRecordingService trackRecordingService =
ITrackRecordingService.Stub.asInterface(service); ITrackRecordingService.Stub.asInterface(service);
@@ -181,7 +183,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
@Override @Override
public void onServiceDisconnected(ComponentName className) { public void onServiceDisconnected(ComponentName className) {
Log.d(MyTracksConstants.TAG, "MyTracks: Service now disconnected."); Log.d(TAG, "MyTracks: Service now disconnected.");
trackRecordingService = null; trackRecordingService = null;
} }
}; };
@@ -226,7 +228,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
// TODO: We catch Exception, because after eliminating the service process // TODO: We catch Exception, because after eliminating the service process
// all exceptions it may throw are no longer wrapped in a RemoteException. // all exceptions it may throw are no longer wrapped in a RemoteException.
} catch (Exception e) { } catch (Exception e) {
Log.e(MyTracksConstants.TAG, "MyTracks: Remote exception.", e); Log.e(TAG, "MyTracks: Remote exception.", e);
// Fall back to alternative check method. // Fall back to alternative check method.
return dataHub.isRecording(); return dataHub.isRecording();
@@ -240,7 +242,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
Log.d(MyTracksConstants.TAG, "MyTracks.onCreate"); Log.d(TAG, "MyTracks.onCreate");
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
instance = this; instance = this;
ApiFeatures apiFeatures = ApiFeatures.getInstance(); ApiFeatures apiFeatures = ApiFeatures.getInstance();
@@ -303,34 +305,32 @@ public class MyTracks extends TabActivity implements OnTouchListener,
// Do nothing. // Do nothing.
} else if (action.equals(Intent.ACTION_VIEW)) { } else if (action.equals(Intent.ACTION_VIEW)) {
if (intent.getScheme() != null && intent.getScheme().equals("file")) { if (intent.getScheme() != null && intent.getScheme().equals("file")) {
Log.w(MyTracksConstants.TAG, Log.w(TAG, "Received a VIEW intent with file scheme. Importing.");
"Received a VIEW intent with file scheme. Importing.");
importGpxFile(intent.getData().getPath()); importGpxFile(intent.getData().getPath());
} else { } else {
Log.w(MyTracksConstants.TAG, Log.w(TAG, "Received a VIEW intent with unsupported scheme " + intent.getScheme());
"Received a VIEW intent with unsupported scheme "
+ intent.getScheme());
} }
} else { } else {
Log.w(MyTracksConstants.TAG, Log.w(TAG, "Received an intent with unsupported action " + action);
"Received an intent with unsupported action " + action);
} }
} else { } else {
Log.d(MyTracksConstants.TAG, "Received an intent with no action."); Log.d(TAG, "Received an intent with no action.");
} }
} }
@Override @Override
protected void onDestroy() { protected void onDestroy() {
Log.d(MyTracksConstants.TAG, "MyTracks.onDestroy"); Log.d(TAG, "MyTracks.onDestroy");
dataHub.destroy(); dataHub.destroy();
tryUnbindTrackRecordingService(); tryUnbindTrackRecordingService();
super.onDestroy(); super.onDestroy();
} }
@Override @Override
protected void onStop() { protected void onStop() {
Log.d(MyTracksConstants.TAG, "MyTracks.onStop"); Log.d(TAG, "MyTracks.onStop");
dataHub.stop(); dataHub.stop();
@@ -343,7 +343,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
protected void onPause() { protected void onPause() {
// Called when activity is going into the background, but has not (yet) been // Called when activity is going into the background, but has not (yet) been
// killed. Shouldn't block longer than approx. 2 seconds. // killed. Shouldn't block longer than approx. 2 seconds.
Log.d(MyTracksConstants.TAG, "MyTracks.onPause"); Log.d(TAG, "MyTracks.onPause");
tryUnbindTrackRecordingService(); tryUnbindTrackRecordingService();
super.onPause(); super.onPause();
} }
@@ -352,14 +352,14 @@ public class MyTracks extends TabActivity implements OnTouchListener,
protected void onResume() { protected void onResume() {
// Called when the current activity is being displayed or re-displayed // Called when the current activity is being displayed or re-displayed
// to the user. // to the user.
Log.d(MyTracksConstants.TAG, "MyTracks.onResume"); Log.d(TAG, "MyTracks.onResume");
tryBindTrackRecordingService(); tryBindTrackRecordingService();
super.onResume(); super.onResume();
} }
@Override @Override
protected void onStart() { protected void onStart() {
Log.d(MyTracksConstants.TAG, "MyTracks.onStart"); Log.d(TAG, "MyTracks.onStart");
super.onStart(); super.onStart();
dataHub.start(); dataHub.start();
} }
@@ -422,9 +422,9 @@ public class MyTracks extends TabActivity implements OnTouchListener,
try { try {
insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS); insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(MyTracksConstants.TAG, "Cannot insert statistics marker.", e); Log.e(TAG, "Cannot insert statistics marker.", e);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
Log.e(MyTracksConstants.TAG, "Cannot insert statistics marker.", e); Log.e(TAG, "Cannot insert statistics marker.", e);
} }
return true; return true;
} }
@@ -437,13 +437,13 @@ public class MyTracks extends TabActivity implements OnTouchListener,
final Intent results) { final Intent results) {
TrackFileFormat exportFormat = null; TrackFileFormat exportFormat = null;
switch (requestCode) { switch (requestCode) {
case MyTracksConstants.GET_LOGIN: { case Constants.GET_LOGIN: {
if (resultCode != RESULT_OK || auth == null || !auth.authResult(resultCode, results)) { if (resultCode != RESULT_OK || auth == null || !auth.authResult(resultCode, results)) {
dialogManager.dismissDialogSafely(DIALOG_PROGRESS); dialogManager.dismissDialogSafely(DIALOG_PROGRESS);
} }
break; break;
} }
case MyTracksConstants.SHOW_TRACK: { case Constants.SHOW_TRACK: {
if (results != null) { if (results != null) {
final long trackId = results.getLongExtra("trackid", -1); final long trackId = results.getLongExtra("trackid", -1);
if (trackId >= 0) { 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 // The track list passed the requested action as result code. Hand
// it off to the onAcitivtyResult for further processing: // it off to the onAcitivtyResult for further processing:
if (resultCode != MyTracksConstants.SHOW_TRACK) { if (resultCode != Constants.SHOW_TRACK) {
onActivityResult(resultCode, Activity.RESULT_OK, results); onActivityResult(resultCode, Activity.RESULT_OK, results);
} }
} }
} }
break; break;
} }
case MyTracksConstants.SHOW_WAYPOINT: { case Constants.SHOW_WAYPOINT: {
if (results != null) { if (results != null) {
final long waypointId = results.getLongExtra("waypointid", -1); final long waypointId = results.getLongExtra("waypointid", -1);
if (waypointId >= 0) { if (waypointId >= 0) {
@@ -472,28 +472,28 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
break; break;
} }
case MyTracksConstants.DELETE_TRACK: { case Constants.DELETE_TRACK: {
if (results != null && resultCode == RESULT_OK) { if (results != null && resultCode == RESULT_OK) {
final long trackId = results.getLongExtra("trackid", dataHub.getSelectedTrackId()); final long trackId = results.getLongExtra("trackid", dataHub.getSelectedTrackId());
deleteTrack(trackId); deleteTrack(trackId);
} }
break; break;
} }
case MyTracksConstants.EDIT_DETAILS: { case Constants.EDIT_DETAILS: {
if (results != null && resultCode == RESULT_OK) { if (results != null && resultCode == RESULT_OK) {
final long trackId = results.getLongExtra("trackid", dataHub.getSelectedTrackId()); 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); intent.putExtra("trackid", trackId);
startActivity(intent); startActivity(intent);
} }
break; break;
} }
case MyTracksConstants.SEND_TO_GOOGLE_DIALOG: { case Constants.SEND_TO_GOOGLE_DIALOG: {
shareRequested = false; shareRequested = false;
dialogManager.showDialogSafely(DIALOG_SEND_TO_GOOGLE); dialogManager.showDialogSafely(DIALOG_SEND_TO_GOOGLE);
break; break;
} }
case MyTracksConstants.GET_MAP: { case Constants.GET_MAP: {
// User picked a map to upload to // User picked a map to upload to
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
results.putExtra("trackid", dataHub.getSelectedTrackId()); results.putExtra("trackid", dataHub.getSelectedTrackId());
@@ -506,7 +506,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
break; break;
} }
case MyTracksConstants.AUTHENTICATE_TO_MY_MAPS: { case Constants.AUTHENTICATE_TO_MY_MAPS: {
// Authenticated with Google My Maps // Authenticated with Google My Maps
if (results != null && resultCode == RESULT_OK) { if (results != null && resultCode == RESULT_OK) {
final String mapId; final String mapId;
@@ -528,7 +528,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
break; break;
} }
case MyTracksConstants.AUTHENTICATE_TO_FUSION_TABLES: { case Constants.AUTHENTICATE_TO_FUSION_TABLES: {
// Authenticated with Google Fusion Tables // Authenticated with Google Fusion Tables
if (results != null && resultCode == RESULT_OK) { if (results != null && resultCode == RESULT_OK) {
final long trackId; final long trackId;
@@ -544,7 +544,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
break; break;
} }
case MyTracksConstants.AUTHENTICATE_TO_DOCLIST: { case Constants.AUTHENTICATE_TO_DOCLIST: {
// Authenticated with Google Docs // Authenticated with Google Docs
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
authenticateToGoogleTrix(); authenticateToGoogleTrix();
@@ -553,7 +553,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
break; break;
} }
case MyTracksConstants.AUTHENTICATE_TO_TRIX: { case Constants.AUTHENTICATE_TO_TRIX: {
// Authenticated with Trix // Authenticated with Trix
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
final long trackId = results.getLongExtra("trackid", dataHub.getSelectedTrackId()); final long trackId = results.getLongExtra("trackid", dataHub.getSelectedTrackId());
@@ -563,16 +563,16 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
break; break;
} }
case MyTracksConstants.SAVE_GPX_FILE: case Constants.SAVE_GPX_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.GPX; } if (exportFormat == null) { exportFormat = TrackFileFormat.GPX; }
//$FALL-THROUGH$ //$FALL-THROUGH$
case MyTracksConstants.SAVE_KML_FILE: case Constants.SAVE_KML_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.KML; } if (exportFormat == null) { exportFormat = TrackFileFormat.KML; }
//$FALL-THROUGH$ //$FALL-THROUGH$
case MyTracksConstants.SAVE_CSV_FILE: case Constants.SAVE_CSV_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.CSV; } if (exportFormat == null) { exportFormat = TrackFileFormat.CSV; }
//$FALL-THROUGH$ //$FALL-THROUGH$
case MyTracksConstants.SAVE_TCX_FILE: case Constants.SAVE_TCX_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; } if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; }
if (results != null && resultCode == Activity.RESULT_OK) { if (results != null && resultCode == Activity.RESULT_OK) {
@@ -582,11 +582,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
} }
break; break;
case MyTracksConstants.SHARE_LINK: { case Constants.SHARE_LINK: {
Track selectedTrack = providerUtils.getTrack(dataHub.getSelectedTrackId()); Track selectedTrack = providerUtils.getTrack(dataHub.getSelectedTrackId());
if (selectedTrack != null) { if (selectedTrack != null) {
if (!TextUtils.isEmpty(selectedTrack.getMapId())) { if (!TextUtils.isEmpty(selectedTrack.getMapId())) {
shareLinkToMap(MapsService.buildMapUrl(selectedTrack.getMapId())); shareLinkToMap(MapsFacade.buildMapUrl(selectedTrack.getMapId()));
} else if (!TextUtils.isEmpty(selectedTrack.getTableId())) { } else if (!TextUtils.isEmpty(selectedTrack.getTableId())) {
shareLinkToMap(getFusionTablesUrl(dataHub.getSelectedTrackId())); shareLinkToMap(getFusionTablesUrl(dataHub.getSelectedTrackId()));
} else { } else {
@@ -596,16 +596,16 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
break; break;
} }
case MyTracksConstants.SHARE_GPX_FILE: case Constants.SHARE_GPX_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.GPX; } if (exportFormat == null) { exportFormat = TrackFileFormat.GPX; }
//$FALL-THROUGH$ //$FALL-THROUGH$
case MyTracksConstants.SHARE_KML_FILE: case Constants.SHARE_KML_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.KML; } if (exportFormat == null) { exportFormat = TrackFileFormat.KML; }
//$FALL-THROUGH$ //$FALL-THROUGH$
case MyTracksConstants.SHARE_CSV_FILE: case Constants.SHARE_CSV_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.CSV; } if (exportFormat == null) { exportFormat = TrackFileFormat.CSV; }
//$FALL-THROUGH$ //$FALL-THROUGH$
case MyTracksConstants.SHARE_TCX_FILE: { case Constants.SHARE_TCX_FILE: {
if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; } if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; }
if (results != null && resultCode == Activity.RESULT_OK) { if (results != null && resultCode == Activity.RESULT_OK) {
@@ -616,18 +616,17 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
break; break;
} }
case MyTracksConstants.CLEAR_MAP: { case Constants.CLEAR_MAP: {
dataHub.unloadCurrentTrack(); dataHub.unloadCurrentTrack();
break; break;
} }
case MyTracksConstants.WELCOME: { case Constants.WELCOME: {
CheckUnits.check(this); CheckUnits.check(this);
break; break;
} }
default: { default: {
Log.w(MyTracksConstants.TAG, Log.w(TAG, "Warning unhandled request code: " + requestCode);
"Warning unhandled request code: " + requestCode);
} }
} }
} }
@@ -668,19 +667,19 @@ public class MyTracks extends TabActivity implements OnTouchListener,
InputStream is = new FileInputStream(fileName); InputStream is = new FileInputStream(fileName);
trackIdsImported = GpxImporter.importGPXFile(is, providerUtils); trackIdsImported = GpxImporter.importGPXFile(is, providerUtils);
} catch (SAXException e) { } 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; message = R.string.error_generic;
} catch (ParserConfigurationException e) { } 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; message = R.string.error_generic;
} catch (IOException e) { } 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; message = R.string.error_unable_to_read_file;
} catch (NullPointerException e) { } 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; message = R.string.error_invalid_gpx_format;
} catch (OutOfMemoryError e) { } 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; message = R.string.error_out_of_memory;
} }
if (trackIdsImported != null && trackIdsImported.length > 0) { if (trackIdsImported != null && trackIdsImported.length > 0) {
@@ -803,16 +802,15 @@ public class MyTracks extends TabActivity implements OnTouchListener,
final String service) { final String service) {
auth = authMap.get(service); auth = authMap.get(service);
if (auth == null) { if (auth == null) {
Log.i(MyTracksConstants.TAG, Log.i(TAG, "Creating a new authentication for service: " + service);
"Creating a new authentication for service: " + service);
auth = AuthManagerFactory.getAuthManager(this, auth = AuthManagerFactory.getAuthManager(this,
MyTracksConstants.GET_LOGIN, Constants.GET_LOGIN,
null, null,
true, true,
service); service);
authMap.put(service, auth); authMap.put(service, auth);
} }
Log.d(MyTracksConstants.TAG, "Logging in to " + service + "..."); Log.d(TAG, "Logging in to " + service + "...");
if (AuthManagerFactory.useModernAuthManager()) { if (AuthManagerFactory.useModernAuthManager()) {
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
@Override @Override
@@ -839,7 +837,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
final String service, final Account account) { final String service, final Account account) {
auth.doLogin(new Runnable() { auth.doLogin(new Runnable() {
public void run() { public void run() {
Log.d(MyTracksConstants.TAG, "Loggin success for " + service + "!"); Log.d(TAG, "Loggin success for " + service + "!");
onActivityResult(requestCode, RESULT_OK, results); onActivityResult(requestCode, RESULT_OK, results);
} }
}, account); }, account);
@@ -859,7 +857,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
Toast.makeText(this, Toast.makeText(this,
getString(R.string.error_unable_to_start_recording), getString(R.string.error_unable_to_start_recording),
Toast.LENGTH_SHORT).show(); 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 // TODO: We catch Exception, because after eliminating the service process
// all exceptions it may throw are no longer wrapped in a RemoteException. // all exceptions it may throw are no longer wrapped in a RemoteException.
} catch (Exception e) { } catch (Exception e) {
Log.e(MyTracksConstants.TAG, "Unable to stop recording.", e); Log.e(TAG, "Unable to stop recording.", e);
} }
if (currentTrackId > 0) { 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("trackid", currentTrackId);
intent.putExtra("hasCancelButton", false); intent.putExtra("hasCancelButton", false);
startActivity(intent); startActivity(intent);
@@ -905,8 +903,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
try { try {
stopService(new Intent(MyTracks.this, TrackRecordingService.class)); stopService(new Intent(MyTracks.this, TrackRecordingService.class));
} catch (SecurityException e) { } catch (SecurityException e) {
Log.e(MyTracksConstants.TAG, Log.e(TAG, "Encountered a security exception when trying to stop service.", e);
"Encountered a security exception when trying to stop service.", e);
} }
trackRecordingService = null; trackRecordingService = null;
} }
@@ -935,7 +932,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} else if (sendToGoogleDialog.getSendToDocs()) { } else if (sendToGoogleDialog.getSendToDocs()) {
authenticateToGoogleDocs(); authenticateToGoogleDocs();
} else { } else {
Log.w(MyTracksConstants.TAG, "Nowhere to upload to"); Log.w(TAG, "Nowhere to upload to");
onSendToGoogleDone(); onSendToGoogleDone();
} }
} }
@@ -944,7 +941,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
if (!sendToGoogleDialog.getCreateNewMap()) { if (!sendToGoogleDialog.getCreateNewMap()) {
// Ask the user to choose a map to upload into // Ask the user to choose a map to upload into
Intent listIntent = new Intent(this, MyMapsList.class); Intent listIntent = new Intent(this, MyMapsList.class);
startActivityForResult(listIntent, MyTracksConstants.GET_MAP); startActivityForResult(listIntent, Constants.GET_MAP);
// The callback for GET_MAP calls authenticateToGoogleMaps // The callback for GET_MAP calls authenticateToGoogleMaps
} else { } else {
authenticateToGoogleMaps(null); authenticateToGoogleMaps(null);
@@ -957,8 +954,8 @@ public class MyTracks extends TabActivity implements OnTouchListener,
setProgressValue(0); setProgressValue(0);
setProgressMessage( setProgressMessage(
R.string.progress_message_authenticating_mymaps); R.string.progress_message_authenticating_mymaps);
authenticate(results, MyTracksConstants.AUTHENTICATE_TO_MY_MAPS, authenticate(results, Constants.AUTHENTICATE_TO_MY_MAPS,
MapsService.getServiceName()); MyMapsConstants.SERVICE_NAME);
// AUTHENTICATE_TO_MY_MAPS callback calls sendToGoogleMaps // AUTHENTICATE_TO_MY_MAPS callback calls sendToGoogleMaps
} }
@@ -978,7 +975,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} catch (RuntimeException e) { } catch (RuntimeException e) {
// If that fails whatever reasons we'll just log an error, but // If that fails whatever reasons we'll just log an error, but
// continue. // 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); setProgressValue(0);
setProgressMessage(R.string.progress_message_authenticating_fusiontables); setProgressMessage(R.string.progress_message_authenticating_fusiontables);
authenticate(results, MyTracksConstants.AUTHENTICATE_TO_FUSION_TABLES, authenticate(results, Constants.AUTHENTICATE_TO_FUSION_TABLES,
SendToFusionTables.SERVICE_ID); SendToFusionTables.SERVICE_ID);
// AUTHENTICATE_TO_FUSION_TABLES callback calls sendToFusionTables // AUTHENTICATE_TO_FUSION_TABLES callback calls sendToFusionTables
} }
@@ -1032,7 +1029,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} catch (RuntimeException e) { } catch (RuntimeException e) {
// If that fails whatever reasons we'll just log an error, but // If that fails whatever reasons we'll just log an error, but
// continue. // continue.
Log.w(MyTracksConstants.TAG, "Updating table id failed.", e); Log.w(TAG, "Updating table id failed.", e);
} }
} }
@@ -1063,7 +1060,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
setProgressMessage( setProgressMessage(
R.string.progress_message_authenticating_docs); R.string.progress_message_authenticating_docs);
authenticate(new Intent(), authenticate(new Intent(),
MyTracksConstants.AUTHENTICATE_TO_DOCLIST, Constants.AUTHENTICATE_TO_DOCLIST,
SendToDocs.GDATA_SERVICE_NAME_DOCLIST); SendToDocs.GDATA_SERVICE_NAME_DOCLIST);
// AUTHENTICATE_TO_DOCLIST callback calls authenticateToGoogleTrix // AUTHENTICATE_TO_DOCLIST callback calls authenticateToGoogleTrix
} }
@@ -1073,13 +1070,13 @@ public class MyTracks extends TabActivity implements OnTouchListener,
setProgressMessage( setProgressMessage(
R.string.progress_message_authenticating_docs); R.string.progress_message_authenticating_docs);
authenticate(new Intent(), authenticate(new Intent(),
MyTracksConstants.AUTHENTICATE_TO_TRIX, Constants.AUTHENTICATE_TO_TRIX,
SendToDocs.GDATA_SERVICE_NAME_TRIX); SendToDocs.GDATA_SERVICE_NAME_TRIX);
// AUTHENTICATE_TO_TRIX callback calls sendToGoogleDocs // AUTHENTICATE_TO_TRIX callback calls sendToGoogleDocs
} }
private void sendToGoogleDocs(final long trackId) { private void sendToGoogleDocs(final long trackId) {
Log.d(MyTracksConstants.TAG, "Sending to Docs...."); Log.d(TAG, "Sending to Docs....");
setProgressValue(50); setProgressValue(50);
setProgressMessage(R.string.progress_message_sending_docs); setProgressMessage(R.string.progress_message_sending_docs);
final SendToDocs sender = new SendToDocs(this, final SendToDocs sender = new SendToDocs(this,
@@ -1151,11 +1148,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
DialogManager.showDialogSafely(this, sendToGoogleResultDialog); DialogManager.showDialogSafely(this, sendToGoogleResultDialog);
} }
private boolean shareLinkToMap(boolean sentToMyMaps, boolean sentToFusionTables) { boolean shareLinkToMap(boolean sentToMyMaps, boolean sentToFusionTables) {
String url = null; String url = null;
if (sentToMyMaps && sendToMyMapsSuccess) { if (sentToMyMaps && sendToMyMapsSuccess) {
// Prefer a link to My Maps // Prefer a link to My Maps
url = MapsService.buildMapUrl(sendToMyMapsMapId); url = MapsFacade.buildMapUrl(sendToMyMapsMapId);
} else if (sentToFusionTables && sendToFusionTablesSuccess) { } else if (sentToFusionTables && sendToFusionTablesSuccess) {
// Otherwise try using the link to fusion tables // Otherwise try using the link to fusion tables
url = getFusionTablesUrl(sendToTrackId); url = getFusionTablesUrl(sendToTrackId);
@@ -1206,11 +1203,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
* Binds to track recording service if it is running. * Binds to track recording service if it is running.
*/ */
private void tryBindTrackRecordingService() { private void tryBindTrackRecordingService() {
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"MyTracks: Trying to bind to track recording service..."); "MyTracks: Trying to bind to track recording service...");
bindService(new Intent(this, TrackRecordingService.class), bindService(new Intent(this, TrackRecordingService.class),
serviceConnection, 0); serviceConnection, 0);
Log.d(MyTracksConstants.TAG, "MyTracks: ...bind finished!"); Log.d(TAG, "MyTracks: ...bind finished!");
isBound = true; isBound = true;
} }
@@ -1220,14 +1217,12 @@ public class MyTracks extends TabActivity implements OnTouchListener,
*/ */
private void tryUnbindTrackRecordingService() { private void tryUnbindTrackRecordingService() {
if (isBound) { if (isBound) {
Log.d(MyTracksConstants.TAG, Log.d(TAG, "MyTracks: Trying to unbind from track recording service...");
"MyTracks: Trying to unbind from track recording service...");
try { try {
unbindService(serviceConnection); unbindService(serviceConnection);
Log.d(MyTracksConstants.TAG, "MyTracks: ...unbind finished!"); Log.d(TAG, "MyTracks: ...unbind finished!");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Log.d(MyTracksConstants.TAG, Log.d(TAG, "MyTracks: Tried unbinding, but service was not registered.", e);
"MyTracks: Tried unbinding, but service was not registered.", e);
} }
isBound = false; isBound = false;
} }
@@ -1319,7 +1314,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
public boolean getSendToGoogleSuccess() { public boolean getSendToGoogleSuccess() {
return sendToMyMapsSuccess && sendToFusionTablesSuccess && sendToDocsSuccess; return sendToFusionTablesSuccess && sendToDocsSuccess;
} }
// @VisibleForTesting // @VisibleForTesting
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks; 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.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
@@ -343,37 +343,37 @@ public class MyTracksMap extends MapActivity
public void onCreateContextMenu(ContextMenu menu, View v, public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) { ContextMenuInfo menuInfo) {
menu.setHeaderTitle(R.string.tracklist_this_track); 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); R.string.tracklist_edit_track);
if (!dataHub.isRecordingSelected()) { 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); 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); 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); 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); 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); 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); 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); R.string.tracklist_share_tcx_file);
SubMenu save = menu.addSubMenu(0, 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); 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); 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); 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); 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); 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); R.string.tracklist_clear_map);
menu.add(0, MyTracksConstants.MENU_DELETE, 0, menu.add(0, Constants.MENU_DELETE, 0,
R.string.tracklist_delete_track); R.string.tracklist_delete_track);
} }
} }
@@ -383,7 +383,7 @@ public class MyTracksMap extends MapActivity
public boolean onMenuItemSelected(int featureId, MenuItem item) { public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (!super.onMenuItemSelected(featureId, item)) { if (!super.onMenuItemSelected(featureId, item)) {
MyTracks.getInstance().onActivityResult( MyTracks.getInstance().onActivityResult(
MyTracksConstants.getActionFromMenuId(item.getItemId()), RESULT_OK, Constants.getActionFromMenuId(item.getItemId()), RESULT_OK,
new Intent()); new Intent());
return true; return true;
} }
@@ -393,10 +393,10 @@ public class MyTracksMap extends MapActivity
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(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); R.string.mylocation);
myLocation.setIcon(android.R.drawable.ic_menu_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); R.string.switch_to_sat);
toggleLayers.setIcon(android.R.drawable.ic_menu_mapmode); toggleLayers.setIcon(android.R.drawable.ic_menu_mapmode);
return true; return true;
@@ -412,7 +412,7 @@ public class MyTracksMap extends MapActivity
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case MyTracksConstants.MENU_MY_LOCATION: { case Constants.MENU_MY_LOCATION: {
dataHub.forceUpdateLocation(); dataHub.forceUpdateLocation();
keepMyLocationVisible = true; keepMyLocationVisible = true;
if (mapView.getZoomLevel() < 18) { if (mapView.getZoomLevel() < 18) {
@@ -420,7 +420,7 @@ public class MyTracksMap extends MapActivity
} }
return true; return true;
} }
case MyTracksConstants.MENU_TOGGLE_LAYERS: { case Constants.MENU_TOGGLE_LAYERS: {
mapView.setSatellite(!mapView.isSatellite()); mapView.setSatellite(!mapView.isSatellite());
return true; return true;
} }
@@ -497,7 +497,7 @@ public class MyTracksMap extends MapActivity
@Override @Override
public void onCurrentLocationChanged(Location location) { public void onCurrentLocationChanged(Location location) {
if (!location.getProvider().equals(MyTracksConstants.GPS_PROVIDER)) { if (!location.getProvider().equals(Constants.GPS_PROVIDER)) {
Log.d(TAG, Log.d(TAG,
"MyTracksMap: Network location update received (provider '" + location.getProvider() + "'."); "MyTracksMap: Network location update received (provider '" + location.getProvider() + "'.");
} }
@@ -103,7 +103,7 @@ public class MyTracksOverlay extends Overlay {
this.waypoints = new ArrayList<Waypoint>(); this.waypoints = new ArrayList<Waypoint>();
this.points = new ArrayList<CachedLocation>(1024); this.points = new ArrayList<CachedLocation>(1024);
this.pendingPoints = new ArrayBlockingQueue<CachedLocation>( this.pendingPoints = new ArrayBlockingQueue<CachedLocation>(
MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS, true); Constants.MAX_DISPLAYED_TRACK_POINTS, true);
// TODO: Can we use a FrameAnimation or similar here rather // TODO: Can we use a FrameAnimation or similar here rather
// than individual resources for each arrow direction? // than individual resources for each arrow direction?
@@ -460,7 +460,7 @@ public class MyTracksOverlay extends Overlay {
if (waypoint != null && if (waypoint != null &&
dmin < 15000000 / Math.pow(2, mapView.getZoomLevel())) { 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()); intent.putExtra("waypointid", waypoint.getId());
context.startActivity(intent); context.startActivity(intent);
return true; return true;
@@ -16,8 +16,8 @@
package com.google.android.apps.mytracks; package com.google.android.apps.mytracks;
import static android.content.Intent.ACTION_BOOT_COMPLETED; 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.Constants.RESUME_TRACK_EXTRA_NAME;
import static com.google.android.apps.mytracks.MyTracksConstants.TAG; import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.services.TrackRecordingService; import com.google.android.apps.mytracks.services.TrackRecordingService;
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks; 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.BackupActivityHelper;
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener; import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener;
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks; 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.content.Sensor;
import com.google.android.apps.mytracks.services.ITrackRecordingService; import com.google.android.apps.mytracks.services.ITrackRecordingService;
import com.google.android.apps.mytracks.services.sensors.SensorUtils; import com.google.android.apps.mytracks.services.sensors.SensorUtils;
@@ -103,7 +103,7 @@ public class SensorStateActivity extends Activity {
ITrackRecordingService service = ITrackRecordingService service =
mt == null ? null : mt.getTrackRecordingService(); mt == null ? null : mt.getTrackRecordingService();
if (service == null) { 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); updateSensorState(Sensor.SensorState.NONE);
updateSensorData(null); updateSensorData(null);
return; return;
@@ -116,9 +116,9 @@ public class SensorStateActivity extends Activity {
updateSensorData(sds); updateSensorData(sds);
} }
} catch (RemoteException e) { } 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) { } 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); updateSensorData(sds);
@@ -126,7 +126,7 @@ public class SensorStateActivity extends Activity {
int i = service.getSensorState(); int i = service.getSensorState();
updateSensorState(Sensor.SensorState.valueOf(i)); updateSensorState(Sensor.SensorState.valueOf(i));
} catch (RemoteException e) { } 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); updateSensorState(Sensor.SensorState.NONE);
} }
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks; 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.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
@@ -175,14 +175,14 @@ public class StatsActivity extends Activity implements TrackDataListener {
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu); super.onCreateOptionsMenu(menu);
MenuItem currentSegment = menu.add(0, 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); currentSegment.setIcon(R.drawable.ic_menu_lastsegment);
return true; return true;
} }
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(MyTracksConstants.MENU_CURRENT_SEGMENT); MenuItem item = menu.findItem(Constants.MENU_CURRENT_SEGMENT);
if (item != null) { if (item != null) {
item.setTitle(showCurrentSegment item.setTitle(showCurrentSegment
? getString(R.string.current_track) ? getString(R.string.current_track)
@@ -194,7 +194,7 @@ public class StatsActivity extends Activity implements TrackDataListener {
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case MyTracksConstants.MENU_CURRENT_SEGMENT: case Constants.MENU_CURRENT_SEGMENT:
showCurrentSegment = !showCurrentSegment; showCurrentSegment = !showCurrentSegment;
// TODO: Re-read only the data that interests us // TODO: Re-read only the data that interests us
return true; return true;
@@ -235,7 +235,7 @@ public class StatsUtilities {
} }
public void setSpeedLabel(int id, int speedString, int paceString) { 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 + " to " + reportSpeed +
" speed: " + speedString + " speed: " + speedString +
" pace: " + paceString); " pace: " + paceString);
@@ -243,7 +243,7 @@ public class StatsUtilities {
if (tv != null) { if (tv != null) {
tv.setText(reportSpeed ? speedString : paceString); tv.setText(reportSpeed ? speedString : paceString);
} else { } else {
Log.w(MyTracksConstants.TAG, "Could not find id: " + id); Log.w(Constants.TAG, "Could not find id: " + id);
} }
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks; 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.TrackDataListener.ProviderState;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
@@ -359,7 +359,7 @@ public class TrackDataHub {
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
Location loc = locationManager.getLastKnownLocation( Location loc = locationManager.getLastKnownLocation(
MyTracksConstants.GPS_PROVIDER); Constants.GPS_PROVIDER);
if (loc == null || loc.getTime() < now - MAX_LOCATION_AGE_MS) { if (loc == null || loc.getTime() < now - MAX_LOCATION_AGE_MS) {
// We don't have a recent GPS fix, just use cell towers if available // We don't have a recent GPS fix, just use cell towers if available
loc = locationManager.getLastKnownLocation( loc = locationManager.getLastKnownLocation(
@@ -502,25 +502,25 @@ public class TrackDataHub {
// Listen to compass // Listen to compass
Sensor compass = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); Sensor compass = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (compass != null) { if (compass != null) {
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"TrackDataHub: Now registering sensor listeners."); "TrackDataHub: Now registering sensor listeners.");
sensorManager.registerListener(compassListener, compass, SensorManager.SENSOR_DELAY_UI); sensorManager.registerListener(compassListener, compass, SensorManager.SENSOR_DELAY_UI);
} }
// Listen to GPS // Listen to GPS
LocationProvider gpsProvider = LocationProvider gpsProvider =
locationManager.getProvider(MyTracksConstants.GPS_PROVIDER); locationManager.getProvider(Constants.GPS_PROVIDER);
if (gpsProvider == null) { if (gpsProvider == null) {
Toast.makeText(context, R.string.error_no_gps_location_provider, Toast.LENGTH_LONG).show(); Toast.makeText(context, R.string.error_no_gps_location_provider, Toast.LENGTH_LONG).show();
hasProviderEnabled = false; hasProviderEnabled = false;
return; return;
} else { } else {
Log.d(MyTracksConstants.TAG, "TrackDataHub: Using location provider " Log.d(Constants.TAG, "TrackDataHub: Using location provider "
+ gpsProvider.getName()); + gpsProvider.getName());
} }
locationManager.requestLocationUpdates(gpsProvider.getName(), locationManager.requestLocationUpdates(gpsProvider.getName(),
0 /*minTime*/, 0 /*minDist*/, locationListener); 0 /*minTime*/, 0 /*minDist*/, locationListener);
hasProviderEnabled = locationManager.isProviderEnabled(MyTracksConstants.GPS_PROVIDER); hasProviderEnabled = locationManager.isProviderEnabled(Constants.GPS_PROVIDER);
// Listen to network location // Listen to network location
try { try {
@@ -529,7 +529,7 @@ public class TrackDataHub {
} catch (RuntimeException e) { } catch (RuntimeException e) {
// If anything at all goes wrong with getting a cell location do not // If anything at all goes wrong with getting a cell location do not
// abort. Cell location is not essential to this app. // abort. Cell location is not essential to this app.
Log.w(MyTracksConstants.TAG, Log.w(Constants.TAG,
"Could not register network location listener."); "Could not register network location listener.");
} }
} }
@@ -777,7 +777,7 @@ public class TrackDataHub {
private void notifyWaypointUpdated(final TrackDataListener... listeners) { private void notifyWaypointUpdated(final TrackDataListener... listeners) {
// Always reload all the waypoints. // Always reload all the waypoints.
final Cursor cursor = providerUtils.getWaypointsCursor( final Cursor cursor = providerUtils.getWaypointsCursor(
selectedTrackId, 0, MyTracksConstants.MAX_DISPLAYED_WAYPOINTS_POINTS); selectedTrackId, 0, Constants.MAX_DISPLAYED_WAYPOINTS_POINTS);
listenerHandler.post(new Runnable() { listenerHandler.post(new Runnable() {
@Override @Override
@@ -857,7 +857,7 @@ public class TrackDataHub {
long minPointId = keepState ? lastSeenLocationId + 1 : 0; long minPointId = keepState ? lastSeenLocationId + 1 : 0;
long maxPointId = keepState ? -1 : lastSeenLocationId; 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 // We're about to exceed the maximum allowed number of points, so reload
// the whole track with fewer points (the sampling frequency will be // 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 // lower). We do this for every listener even if we were loading just for
@@ -931,7 +931,7 @@ public class TrackDataHub {
// frequency. // frequency.
long numTotalPoints = lastStoredLocationId - localFirstSeenLocationId; long numTotalPoints = lastStoredLocationId - localFirstSeenLocationId;
pointSamplingFrequency = 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: // Include a point if it fits one of the following criteria:
@@ -37,7 +37,7 @@ import android.widget.EditText;
* *
* @author Leif Hendrik Wilden * @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") * 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: // Required extra when launching this intent:
trackId = getIntent().getLongExtra("trackid", -1); trackId = getIntent().getLongExtra("trackid", -1);
if (trackId < 0) { if (trackId < 0) {
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"MyTracksDetails intent was launched w/o track id."); "MyTracksDetails intent was launched w/o track id.");
finish(); finish();
return; return;
@@ -45,7 +45,7 @@ import android.widget.TextView;
* *
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
*/ */
public class MyTracksList extends ListActivity public class TrackList extends ListActivity
implements SharedPreferences.OnSharedPreferenceChangeListener, implements SharedPreferences.OnSharedPreferenceChangeListener,
View.OnClickListener { View.OnClickListener {
@@ -70,40 +70,40 @@ public class MyTracksList extends ListActivity
AdapterView.AdapterContextMenuInfo info = AdapterView.AdapterContextMenuInfo info =
(AdapterView.AdapterContextMenuInfo) menuInfo; (AdapterView.AdapterContextMenuInfo) menuInfo;
contextPosition = info.position; contextPosition = info.position;
trackId = MyTracksList.this.listView.getAdapter().getItemId( trackId = TrackList.this.listView.getAdapter().getItemId(
contextPosition); contextPosition);
menu.add(0, MyTracksConstants.MENU_SHOW, 0, menu.add(0, Constants.MENU_SHOW, 0,
R.string.tracklist_show_track); R.string.tracklist_show_track);
menu.add(0, MyTracksConstants.MENU_EDIT, 0, menu.add(0, Constants.MENU_EDIT, 0,
R.string.tracklist_edit_track); R.string.tracklist_edit_track);
if (!MyTracks.getInstance().isRecording() if (!MyTracks.getInstance().isRecording()
|| trackId != recordingTrackId) { || 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); 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); 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); 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); 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); 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); 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); R.string.tracklist_share_tcx_file);
SubMenu save = menu.addSubMenu(0, 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); 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); 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); 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); 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); 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); 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) { protected void onListItemClick(ListView l, View v, int position, long id) {
Intent result = new Intent(); Intent result = new Intent();
result.putExtra("trackid", id); result.putExtra("trackid", id);
setResult(MyTracksConstants.SHOW_TRACK, result); setResult(Constants.SHOW_TRACK, result);
finish(); finish();
} }
@@ -140,24 +140,24 @@ public class MyTracksList extends ListActivity
public boolean onMenuItemSelected(int featureId, MenuItem item) { public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (!super.onMenuItemSelected(featureId, item)) { if (!super.onMenuItemSelected(featureId, item)) {
switch (item.getItemId()) { switch (item.getItemId()) {
case MyTracksConstants.MENU_SHOW: { case Constants.MENU_SHOW: {
onListItemClick(null, null, 0, trackId); onListItemClick(null, null, 0, trackId);
return true; return true;
} }
case MyTracksConstants.MENU_EDIT: { case Constants.MENU_EDIT: {
Intent intent = new Intent(this, MyTracksDetails.class); Intent intent = new Intent(this, TrackDetails.class);
intent.putExtra("trackid", trackId); intent.putExtra("trackid", trackId);
startActivity(intent); startActivity(intent);
return true; return true;
} }
case MyTracksConstants.MENU_SHARE: case Constants.MENU_SHARE:
case MyTracksConstants.MENU_WRITE_TO_SD_CARD: case Constants.MENU_WRITE_TO_SD_CARD:
return false; return false;
default: { default: {
Intent result = new Intent(); Intent result = new Intent();
result.putExtra("trackid", trackId); result.putExtra("trackid", trackId);
setResult( setResult(
MyTracksConstants.getActionFromMenuId(item.getItemId()), result); Constants.getActionFromMenuId(item.getItemId()), result);
finish(); finish();
return true; return true;
} }
@@ -170,7 +170,7 @@ public class MyTracksList extends ListActivity
public void onClick(View v) { public void onClick(View v) {
switch (v.getId()) { switch (v.getId()) {
case R.id.tracklist_btn_delete_all: { case R.id.tracklist_btn_delete_all: {
Handler h = new MyTracksDeleteAllTracks(this, null); Handler h = new DeleteAllTracks(this, null);
h.handleMessage(null); h.handleMessage(null);
break; break;
} }
@@ -39,7 +39,7 @@ import android.widget.ImageView;
* *
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
*/ */
public class MyTracksWaypointDetails extends Activity public class WaypointDetails extends Activity
implements OnClickListener { implements OnClickListener {
public static final String WAYPOINT_ID_EXTRA = "com.google.android.apps.mytracks.WAYPOINT_ID"; 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: // Required extra when launching this intent:
waypointId = getIntent().getLongExtra(WAYPOINT_ID_EXTRA, -1); waypointId = getIntent().getLongExtra(WAYPOINT_ID_EXTRA, -1);
if (waypointId < 0) { if (waypointId < 0) {
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"MyTracksWaypointsDetails intent was launched w/o waypoint id."); "MyTracksWaypointsDetails intent was launched w/o waypoint id.");
finish(); finish();
return; return;
@@ -49,7 +49,7 @@ import android.widget.TextView;
* *
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
*/ */
public class MyTracksWaypointsList extends ListActivity public class WaypointsList extends ListActivity
implements View.OnClickListener { implements View.OnClickListener {
private int contextPosition = -1; private int contextPosition = -1;
@@ -71,14 +71,14 @@ public class MyTracksWaypointsList extends ListActivity
AdapterView.AdapterContextMenuInfo info = AdapterView.AdapterContextMenuInfo info =
(AdapterView.AdapterContextMenuInfo) menuInfo; (AdapterView.AdapterContextMenuInfo) menuInfo;
contextPosition = info.position; contextPosition = info.position;
waypointId = MyTracksWaypointsList.this.listView.getAdapter() waypointId = WaypointsList.this.listView.getAdapter()
.getItemId(contextPosition); .getItemId(contextPosition);
int type = providerUtils.getWaypoint(info.id).getType(); 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); R.string.waypointslist_show_waypoint);
menu.add(0, MyTracksConstants.MENU_EDIT, 0, menu.add(0, Constants.MENU_EDIT, 0,
R.string.waypointslist_edit_waypoint); 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( R.string.waypointslist_delete_waypoint).setEnabled(
recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT || recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT ||
info.id != providerUtils.getLastWaypointId(recordingTrackId)); 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) { protected void onListItemClick(ListView l, View v, int position, long id) {
Intent result = new Intent(); Intent result = new Intent();
result.putExtra("trackid", trackId); result.putExtra("trackid", trackId);
result.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, id); result.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, id);
setResult(MyTracksConstants.EDIT_WAYPOINT, result); setResult(Constants.EDIT_WAYPOINT, result);
finish(); finish();
} }
@@ -98,18 +98,18 @@ public class MyTracksWaypointsList extends ListActivity
public boolean onMenuItemSelected(int featureId, MenuItem item) { public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (!super.onMenuItemSelected(featureId, item)) { if (!super.onMenuItemSelected(featureId, item)) {
switch (item.getItemId()) { switch (item.getItemId()) {
case MyTracksConstants.MENU_SHOW: { case Constants.MENU_SHOW: {
onListItemClick(null, null, 0, waypointId); onListItemClick(null, null, 0, waypointId);
return true; return true;
} }
case MyTracksConstants.MENU_EDIT: { case Constants.MENU_EDIT: {
Intent intent = new Intent(this, MyTracksWaypointDetails.class); Intent intent = new Intent(this, WaypointDetails.class);
intent.putExtra("trackid", trackId); intent.putExtra("trackid", trackId);
intent.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, waypointId); intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, waypointId);
startActivity(intent); startActivity(intent);
return true; return true;
} }
case MyTracksConstants.MENU_DELETE: { case Constants.MENU_DELETE: {
deleteWaypoint(waypointId); deleteWaypoint(waypointId);
} }
} }
@@ -185,18 +185,18 @@ public class MyTracksWaypointsList extends ListActivity
try { try {
id = MyTracks.getInstance().insertWaypoint(request); id = MyTracks.getInstance().insertWaypoint(request);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(MyTracksConstants.TAG, "Cannot insert marker.", e); Log.e(Constants.TAG, "Cannot insert marker.", e);
return; return;
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
Log.e(MyTracksConstants.TAG, "Cannot insert marker.", e); Log.e(Constants.TAG, "Cannot insert marker.", e);
return; return;
} }
if (id < 0) { if (id < 0) {
Log.e(MyTracksConstants.TAG, "Failed to insert marker."); Log.e(Constants.TAG, "Failed to insert marker.");
return; return;
} }
Intent intent = new Intent(this, MyTracksWaypointDetails.class); Intent intent = new Intent(this, WaypointDetails.class);
intent.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, id); intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, id);
startActivity(intent); startActivity(intent);
} }
@@ -261,7 +261,7 @@ public class MyTracksWaypointsList extends ListActivity
public void onClick(DialogInterface dialog, int i) { public void onClick(DialogInterface dialog, int i) {
dialog.dismiss(); dialog.dismiss();
providerUtils.deleteWaypoint(waypointId, providerUtils.deleteWaypoint(waypointId,
new StringUtils(MyTracksWaypointsList.this)); new StringUtils(WaypointsList.this));
} }
}); });
builder.setNegativeButton(getString(R.string.no), builder.setNegativeButton(getString(R.string.no),
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.content; 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 com.google.android.apps.mytracks.util.ApiFeatures;
import android.content.ContentProvider; import android.content.ContentProvider;
@@ -382,7 +382,7 @@ public class MyTracksProvider extends ContentProvider {
} }
if (ApiFeatures.getInstance().canReuseSQLiteQueryBuilder()) { if (ApiFeatures.getInstance().canReuseSQLiteQueryBuilder()) {
Log.i(MyTracksConstants.TAG, Log.i(Constants.TAG,
"Build query: " + qb.buildQuery(projection, selection, selectionArgs, "Build query: " + qb.buildQuery(projection, selection, selectionArgs,
null, null, sortOrder, null)); null, null, sortOrder, null));
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.io; 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.app.Activity;
import android.os.Build; import android.os.Build;
@@ -46,11 +46,11 @@ public class AuthManagerFactory {
public static AuthManager getAuthManager(Activity activity, int code, public static AuthManager getAuthManager(Activity activity, int code,
Bundle extras, boolean requireGoogle, String service) { Bundle extras, boolean requireGoogle, String service) {
if (useModernAuthManager()) { if (useModernAuthManager()) {
Log.i(MyTracksConstants.TAG, Log.i(Constants.TAG,
"Creating modern auth manager: " + service); "Creating modern auth manager: " + service);
return new ModernAuthManager(activity, code, extras, requireGoogle, service); return new ModernAuthManager(activity, code, extras, requireGoogle, service);
} else { } else {
Log.i(MyTracksConstants.TAG, Log.i(Constants.TAG,
"Creating legacy auth manager: " + service); "Creating legacy auth manager: " + service);
return new AuthManagerOld(activity, code, extras, requireGoogle, service); return new AuthManagerOld(activity, code, extras, requireGoogle, service);
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.io; 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.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder; import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
@@ -174,7 +174,7 @@ public class GpxImporter extends DefaultHandler {
parser.parse(is, handler); parser.parse(is, handler);
long end = System.currentTimeMillis(); 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(); trackIds = handler.getImportedTrackIds();
} finally { } finally {
@@ -462,7 +462,7 @@ public class GpxImporter extends DefaultHandler {
// check for negative time change // check for negative time change
if (timeDifference < 0) { if (timeDifference < 0) {
Log.w(MyTracksConstants.TAG, "Found negative time change."); Log.w(Constants.TAG, "Found negative time change.");
} else { } else {
// We don't have a speed and bearing in GPX, make something up from // We don't have a speed and bearing in GPX, make something up from
@@ -23,7 +23,7 @@ import com.google.android.accounts.AuthenticatorException;
import com.google.android.accounts.OperationCanceledException; import com.google.android.accounts.OperationCanceledException;
import com.google.android.apps.mytracks.AccountChooser; import com.google.android.apps.mytracks.AccountChooser;
import com.google.android.apps.mytracks.MyTracks; 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.app.Activity;
import android.content.Intent; import android.content.Intent;
@@ -104,20 +104,20 @@ public class ModernAuthManager implements AuthManager {
if (result.containsKey(AccountManager.KEY_INTENT)) { if (result.containsKey(AccountManager.KEY_INTENT)) {
Intent intent = (Intent) result.get(AccountManager.KEY_INTENT); Intent intent = (Intent) result.get(AccountManager.KEY_INTENT);
clearNewTaskFlag(intent); clearNewTaskFlag(intent);
activity.startActivityForResult(intent, MyTracksConstants.GET_LOGIN); activity.startActivityForResult(intent, Constants.GET_LOGIN);
return; return;
} }
authToken = result.getString( authToken = result.getString(
AccountManager.KEY_AUTHTOKEN); AccountManager.KEY_AUTHTOKEN);
Log.e(MyTracksConstants.TAG, "Got auth token."); Log.e(Constants.TAG, "Got auth token.");
runWhenFinished(); runWhenFinished();
} catch (OperationCanceledException e) { } catch (OperationCanceledException e) {
Log.e(MyTracksConstants.TAG, "Operation Canceled", e); Log.e(Constants.TAG, "Operation Canceled", e);
} catch (IOException e) { } catch (IOException e) {
Log.e(MyTracksConstants.TAG, "IOException", e); Log.e(Constants.TAG, "IOException", e);
} catch (AuthenticatorException e) { } catch (AuthenticatorException e) {
Log.e(MyTracksConstants.TAG, "Authentication Failed", e); Log.e(Constants.TAG, "Authentication Failed", e);
} }
} }
}, null /* handler */); }, null /* handler */);
@@ -149,9 +149,9 @@ public class ModernAuthManager implements AuthManager {
if (results != null) { if (results != null) {
authToken = results.getStringExtra( authToken = results.getStringExtra(
AccountManager.KEY_AUTHTOKEN); AccountManager.KEY_AUTHTOKEN);
Log.w(MyTracksConstants.TAG, "authResult: " + authToken); Log.w(Constants.TAG, "authResult: " + authToken);
} else { } else {
Log.e(MyTracksConstants.TAG, "No auth result results!!"); Log.e(Constants.TAG, "No auth result results!!");
} }
runWhenFinished(); runWhenFinished();
return authToken != null; return authToken != null;
@@ -181,7 +181,7 @@ public class ModernAuthManager implements AuthManager {
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
public void run() { public void run() {
accountManager.invalidateAuthToken(MyTracksConstants.ACCOUNT_TYPE, accountManager.invalidateAuthToken(Constants.ACCOUNT_TYPE,
authToken); authToken);
MyTracks.getInstance().getAccountChooser().chooseAccount(activity, MyTracks.getInstance().getAccountChooser().chooseAccount(activity,
new AccountChooser.AccountHandler() { new AccountChooser.AccountHandler() {
@@ -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() {}
}
@@ -16,7 +16,7 @@
package com.google.android.apps.mytracks.io; package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.MyTracks; import com.google.android.apps.mytracks.MyTracks;
import com.google.android.apps.mytracks.MyTracksConstants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.MyTracksSettings; import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
@@ -82,7 +82,7 @@ public class SendToDocs {
metricUnits = true; metricUnits = true;
} }
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"Sending to Google Docs: trackId = " + trackId); "Sending to Google Docs: trackId = " + trackId);
handlerThread = new HandlerThread("SendToGoogleDocs"); handlerThread = new HandlerThread("SendToGoogleDocs");
handlerThread.start(); handlerThread.start();
@@ -105,7 +105,7 @@ public class SendToDocs {
try { try {
if (trackId == -1) { if (trackId == -1) {
Log.w(MyTracksConstants.TAG, "Cannot get track id."); Log.w(Constants.TAG, "Cannot get track id.");
return; return;
} }
@@ -113,14 +113,14 @@ public class SendToDocs {
Track track = Track track =
MyTracksProviderUtils.Factory.get(activity).getTrack(trackId); MyTracksProviderUtils.Factory.get(activity).getTrack(trackId);
if (track == null) { if (track == null) {
Log.w(MyTracksConstants.TAG, "Cannot get track."); Log.w(Constants.TAG, "Cannot get track.");
return; return;
} }
// Transmit track stats via GData feed: // 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); success = uploadToDocs(track);
if (success) { if (success) {
if (createdNewSpreadSheet) { if (createdNewSpreadSheet) {
@@ -133,7 +133,7 @@ public class SendToDocs {
} else { } else {
statusMessage = activity.getString(R.string.error_sending_to_docs); statusMessage = activity.getString(R.string.error_sending_to_docs);
} }
Log.d(MyTracksConstants.TAG, "SendToDocs: Done."); Log.d(Constants.TAG, "SendToDocs: Done.");
} finally { } finally {
if (onCompletion != null) { if (onCompletion != null) {
activity.runOnUiThread(onCompletion); activity.runOnUiThread(onCompletion);
@@ -176,7 +176,7 @@ public class SendToDocs {
SpreadsheetsClient gdataClient = new SpreadsheetsClient(androidClient, SpreadsheetsClient gdataClient = new SpreadsheetsClient(androidClient,
new XmlDocsGDataParserFactory(new AndroidXmlParserFactory())); new XmlDocsGDataParserFactory(new AndroidXmlParserFactory()));
trixWrapper.setClient(gdataClient); trixWrapper.setClient(gdataClient);
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"GData connection prepared: " + this.docListAuth); "GData connection prepared: " + this.docListAuth);
String sheetTitle = "My Tracks"; String sheetTitle = "My Tracks";
@@ -194,7 +194,7 @@ public class SendToDocs {
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper, spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
sheetTitle); sheetTitle);
} catch (IOException e) { } catch (IOException e) {
Log.i(MyTracksConstants.TAG, "Spreadsheet lookup failed.", e); Log.i(Constants.TAG, "Spreadsheet lookup failed.", e);
return false; return false;
} }
@@ -205,14 +205,14 @@ public class SendToDocs {
try { try {
Thread.sleep(5000); Thread.sleep(5000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Log.e(MyTracksConstants.TAG, "Sleep interrupted", e); Log.e(Constants.TAG, "Sleep interrupted", e);
} }
try { try {
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper, spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
sheetTitle); sheetTitle);
} catch (IOException e) { } catch (IOException e) {
Log.i(MyTracksConstants.TAG, "2nd spreadsheet lookup failed.", e); Log.i(Constants.TAG, "2nd spreadsheet lookup failed.", e);
return false; return false;
} }
} }
@@ -220,13 +220,13 @@ public class SendToDocs {
// We were unable to find an existing spreadsheet, so create a new one. // We were unable to find an existing spreadsheet, so create a new one.
MyTracks.getInstance().setProgressValue(70); MyTracks.getInstance().setProgressValue(70);
if (spreadsheetId == null) { if (spreadsheetId == null) {
Log.i(MyTracksConstants.TAG, "Creating new spreadsheet: " + sheetTitle); Log.i(Constants.TAG, "Creating new spreadsheet: " + sheetTitle);
try { try {
spreadsheetId = docsHelper.createSpreadsheet(activity, docListWrapper, spreadsheetId = docsHelper.createSpreadsheet(activity, docListWrapper,
sheetTitle); sheetTitle);
} catch (IOException e) { } catch (IOException e) {
Log.i(MyTracksConstants.TAG, "Failed to create new spreadsheet " Log.i(Constants.TAG, "Failed to create new spreadsheet "
+ sheetTitle, e); + sheetTitle, e);
return false; return false;
} }
@@ -239,19 +239,19 @@ public class SendToDocs {
// reported an error. Seems to be a know bug, // reported an error. Seems to be a know bug,
// see http://code.google.com/p/gdata-issues/issues/detail?id=929 // see http://code.google.com/p/gdata-issues/issues/detail?id=929
// Try to find the created spreadsheet: // Try to find the created spreadsheet:
Log.w(MyTracksConstants.TAG, Log.w(Constants.TAG,
"Create might have failed. Trying to find created document."); "Create might have failed. Trying to find created document.");
try { try {
Thread.sleep(5000); Thread.sleep(5000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Log.e(MyTracksConstants.TAG, "Sleep interrupted", e); Log.e(Constants.TAG, "Sleep interrupted", e);
} }
try { try {
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper, spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
sheetTitle); sheetTitle);
} catch (IOException e) { } catch (IOException e) {
Log.i(MyTracksConstants.TAG, "Failed create-failed lookup", e); Log.i(Constants.TAG, "Failed create-failed lookup", e);
return false; return false;
} }
@@ -261,19 +261,19 @@ public class SendToDocs {
try { try {
Thread.sleep(5000); Thread.sleep(5000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Log.e(MyTracksConstants.TAG, "Sleep interrupted", e); Log.e(Constants.TAG, "Sleep interrupted", e);
} }
try { try {
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper, spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
sheetTitle); sheetTitle);
} catch (IOException e) { } catch (IOException e) {
Log.i(MyTracksConstants.TAG, "Failed create-failed relookup", e); Log.i(Constants.TAG, "Failed create-failed relookup", e);
return false; return false;
} }
} }
if (spreadsheetId == null) { if (spreadsheetId == null) {
Log.i(MyTracksConstants.TAG, Log.i(Constants.TAG,
"Creating new spreadsheet really failed."); "Creating new spreadsheet really failed.");
return false; return false;
} }
@@ -287,7 +287,7 @@ public class SendToDocs {
throw new IOException("Worksheet ID lookup returned empty"); throw new IOException("Worksheet ID lookup returned empty");
} }
} catch (IOException e) { } 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; return false;
} }
@@ -295,9 +295,9 @@ public class SendToDocs {
docsHelper.addTrackRow(activity, trixAuth, spreadsheetId, worksheetId, docsHelper.addTrackRow(activity, trixAuth, spreadsheetId, worksheetId,
track, metricUnits); track, metricUnits);
Log.i(MyTracksConstants.TAG, "Done uploading to docs."); Log.i(Constants.TAG, "Done uploading to docs.");
} catch (IOException e) { } catch (IOException e) {
Log.e(MyTracksConstants.TAG, "Unable to upload docs.", e); Log.e(Constants.TAG, "Unable to upload docs.", e);
return false; return false;
} finally { } finally {
if (androidClient != null) { if (androidClient != null) {
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.io; 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.MyTracksSettings;
import com.google.android.apps.mytracks.ProgressIndicator; import com.google.android.apps.mytracks.ProgressIndicator;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
@@ -151,7 +151,7 @@ public class SendToFusionTables implements Runnable {
@Override @Override
public void run() { public void run() {
Log.d(MyTracksConstants.TAG, "Sending to Fusion tables: trackId = " + trackId); Log.d(Constants.TAG, "Sending to Fusion tables: trackId = " + trackId);
doUpload(); doUpload();
} }
@@ -172,7 +172,7 @@ public class SendToFusionTables implements Runnable {
private void doUpload() { private void doUpload() {
((GoogleHeaders) transport.defaultHeaders).setGoogleLogin(auth.getAuthToken()); ((GoogleHeaders) transport.defaultHeaders).setGoogleLogin(auth.getAuthToken());
int statusMessageId = R.string.error_sending_to_fusiontables; int statusMessageId = R.string.error_sending_to_fusiontables;
boolean success = false; boolean success = true;
try { try {
progressIndicator.setProgressValue(PROGRESS_INITIALIZATION); progressIndicator.setProgressValue(PROGRESS_INITIALIZATION);
progressIndicator.setProgressMessage(R.string.progress_message_reading_track); 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; statusMessageId = R.string.status_new_fusiontable_has_been_created;
success = true; Log.d(Constants.TAG, "SendToFusionTables: Done: " + success);
Log.d(MyTracksConstants.TAG, "SendToFusionTables: Done: " + success);
progressIndicator.setProgressValue(PROGRESS_COMPLETE); progressIndicator.setProgressValue(PROGRESS_COMPLETE);
} finally { } finally {
final boolean finalSuccess = success; final boolean finalSuccess = success;
final int finalStatusMessageId = statusMessageId; final int finalStatusMessageId = statusMessageId;
context.runOnUiThread(new Runnable() { context.runOnUiThread(new Runnable() {
@@ -229,14 +228,14 @@ public class SendToFusionTables implements Runnable {
* @return true in case of success. * @return true in case of success.
*/ */
private boolean createNewTable(Track track) { 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()) + String query = "CREATE TABLE '" + sqlEscape(track.getName()) +
"' (name:STRING,description:STRING,geometry:LOCATION,marker:STRING)"; "' (name:STRING,description:STRING,geometry:LOCATION,marker:STRING)";
return runUpdate(query); return runUpdate(query);
} }
private boolean makeTableUnlisted(String tableId) { 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"; String query = "UPDATE TABLE " + tableId + " SET VISIBILITY = UNLISTED";
return runUpdate(query); return runUpdate(query);
} }
@@ -275,7 +274,7 @@ public class SendToFusionTables implements Runnable {
*/ */
private boolean createNewPoint(String name, String description, Location location, private boolean createNewPoint(String name, String description, Location location,
String marker) { 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 " String query = "INSERT INTO " + tableId + " (name,description,geometry,marker) VALUES "
+ values(name, description, getKmlPoint(location), marker); + values(name, description, getKmlPoint(location), marker);
return runUpdate(query); return runUpdate(query);
@@ -288,7 +287,7 @@ public class SendToFusionTables implements Runnable {
* @return true in case of success. * @return true in case of success.
*/ */
private boolean createNewLineString(Track track) { 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 String query = "INSERT INTO " + tableId
+ " (name,description,geometry) VALUES " + " (name,description,geometry) VALUES "
+ values(track.getName(), track.getDescription(), getKmlLineString(track)); + 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); Cursor locationsCursor = providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
try { try {
if (!locationsCursor.moveToFirst()) { 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; return false;
} }
@@ -319,14 +318,14 @@ public class SendToFusionTables implements Runnable {
// Limit the number of elevation readings. Ideally we would want around 250. // Limit the number of elevation readings. Ideally we would want around 250.
int elevationSamplingFrequency = int elevationSamplingFrequency =
Math.max(1, (int) (totalLocations / 250.0)); Math.max(1, (int) (totalLocations / 250.0));
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"Using elevation sampling factor: " + elevationSamplingFrequency "Using elevation sampling factor: " + elevationSamplingFrequency
+ " on " + totalLocations); + " on " + totalLocations);
double totalDistance = 0; double totalDistance = 0;
Vector<Double> distances = new Vector<Double>(); Vector<Double> distances = new Vector<Double>();
Vector<Double> elevations = new Vector<Double>(); Vector<Double> elevations = new Vector<Double>();
DoubleBuffer elevationBuffer = new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); DoubleBuffer elevationBuffer = new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD); List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
Location lastLocation = null; Location lastLocation = null;
@@ -448,7 +447,7 @@ public class SendToFusionTables implements Runnable {
int numLocations = locations.size(); int numLocations = locations.size();
if (numLocations < 2) { 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; totalLocationsUploaded += numLocations;
return true; return true;
} }
@@ -464,16 +463,16 @@ public class SendToFusionTables implements Runnable {
context.getString(R.string.part), totalSegmentsUploaded)); context.getString(R.string.part), totalSegmentsUploaded));
} }
totalSegmentsUploaded++; totalSegmentsUploaded++;
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"SendToFusionTables: Prepared feature for upload w/ " "SendToFusionTables: Prepared feature for upload w/ "
+ splitTrack.getLocations().size() + " points."); + splitTrack.getLocations().size() + " points.");
// Transmit tracks via GData feed: // Transmit tracks via GData feed:
// ------------------------------- // -------------------------------
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"SendToFusionTables: Uploading to table " + tableId + " w/ auth " + auth); "SendToFusionTables: Uploading to table " + tableId + " w/ auth " + auth);
if (!uploadTrackPoints(splitTrack)) { if (!uploadTrackPoints(splitTrack)) {
Log.e(MyTracksConstants.TAG, "Uploading failed"); Log.e(Constants.TAG, "Uploading failed");
return false; return false;
} }
} }
@@ -519,7 +518,7 @@ public class SendToFusionTables implements Runnable {
// Close up the last segment. // Close up the last segment.
prepareTrackSegment(segment, splitTracks); prepareTrackSegment(segment, splitTracks);
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"MyTracksSendToFusionTables: Starting new track segment..."); "MyTracksSendToFusionTables: Starting new track segment...");
startNewTrackSegment = false; startNewTrackSegment = false;
segment = new Track(); segment = new Track();
@@ -582,7 +581,7 @@ public class SendToFusionTables implements Runnable {
int numLocations = splitTrack.getLocations().size(); int numLocations = splitTrack.getLocations().size();
if (numLocations < 2) { if (numLocations < 2) {
// Need at least two points for a polyline: // 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 true;
} }
return createNewLineString(splitTrack); return createNewLineString(splitTrack);
@@ -605,14 +604,14 @@ public class SendToFusionTables implements Runnable {
try { try {
c = providerUtils.getWaypointsCursor( c = providerUtils.getWaypointsCursor(
track.getId(), 0, track.getId(), 0,
MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS); Constants.MAX_LOADED_WAYPOINTS_POINTS);
if (c != null) { if (c != null) {
if (c.moveToFirst()) { if (c.moveToFirst()) {
// This will skip the 1st waypoint (it carries the stats for the // This will skip the 1st waypoint (it carries the stats for the
// last segment). // last segment).
while (c.moveToNext()) { while (c.moveToNext()) {
Waypoint wpt = providerUtils.createWaypoint(c); 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(), success = createNewPoint(wpt.getName(), wpt.getDescription(), wpt.getLocation(),
MARKER_TYPE_WAYPOINT); MARKER_TYPE_WAYPOINT);
if (!success) { if (!success) {
@@ -622,7 +621,7 @@ public class SendToFusionTables implements Runnable {
} }
} }
if (!success) { if (!success) {
Log.w(MyTracksConstants.TAG, "SendToFusionTables: upload waypoints failed."); Log.w(Constants.TAG, "SendToFusionTables: upload waypoints failed.");
} }
return success; return success;
} finally { } finally {
@@ -657,7 +656,7 @@ public class SendToFusionTables implements Runnable {
wrapper.setAuthManager(auth); wrapper.setAuthManager(auth);
wrapper.setRetryOnAuthFailure(true); wrapper.setRetryOnAuthFailure(true);
wrapper.setClient(transport); 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<HttpTransport>() { wrapper.runQuery(new QueryFunction<HttpTransport>() {
@Override @Override
public void query(HttpTransport client) public void query(HttpTransport client)
@@ -672,7 +671,7 @@ public class SendToFusionTables implements Runnable {
isc.inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql)); isc.inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql));
request.content = isc; 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; HttpResponse response;
try { try {
response = request.execute(); response = request.execute();
@@ -687,12 +686,12 @@ public class SendToFusionTables implements Runnable {
String[] lines = s.split(Strings.LINE_SEPARATOR); String[] lines = s.split(Strings.LINE_SEPARATOR);
if (lines[0].equals("tableid")) { if (lines[0].equals("tableid")) {
tableId = lines[1]; tableId = lines[1];
Log.d(MyTracksConstants.TAG, "tableId = " + tableId); Log.d(Constants.TAG, "tableId = " + tableId);
} else { } else {
Log.w(MyTracksConstants.TAG, "Unrecognized response: " + lines[0]); Log.w(Constants.TAG, "Unrecognized response: " + lines[0]);
} }
} else { } else {
Log.d(MyTracksConstants.TAG, "Query failed: " + response.statusMessage + " (" + Log.d(Constants.TAG, "Query failed: " + response.statusMessage + " (" +
response.statusCode + ")"); response.statusCode + ")");
throw new GDataWrapper.HttpException(response.statusCode, response.statusMessage); throw new GDataWrapper.HttpException(response.statusCode, response.statusMessage);
} }
@@ -15,14 +15,14 @@
*/ */
package com.google.android.apps.mytracks.io; 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.MyTracksSettings;
import com.google.android.apps.mytracks.ProgressIndicator; import com.google.android.apps.mytracks.ProgressIndicator;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade; import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade.WaypointData;
import com.google.android.apps.mytracks.stats.DoubleBuffer; import com.google.android.apps.mytracks.stats.DoubleBuffer;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.MyTracksUtils; import com.google.android.apps.mytracks.util.MyTracksUtils;
@@ -93,7 +93,7 @@ public class SendToMyMaps implements Runnable {
@Override @Override
public void run() { public void run() {
Log.d(MyTracksConstants.TAG, "Sending to MyMaps: trackId = " + trackId); Log.d(TAG, "Sending to MyMaps: trackId = " + trackId);
doUpload(); doUpload();
} }
@@ -111,7 +111,7 @@ public class SendToMyMaps implements Runnable {
track.setDescription("<p>" + track.getDescription() + "</p><p>" track.setDescription("<p>" + track.getDescription() + "</p><p>"
+ stringUtils.generateTrackDescription(track, null, null) + "</p>"); + stringUtils.generateTrackDescription(track, null, null) + "</p>");
mapsClient = MyMapsFactory.newMapsClient(context, auth); mapsClient = new MapsFacade(context, auth);
// Create a new map if necessary: // Create a new map if necessary:
boolean isNewMap = mapId.equals(NEW_MAP_ID); boolean isNewMap = mapId.equals(NEW_MAP_ID);
@@ -142,17 +142,16 @@ public class SendToMyMaps implements Runnable {
if (success) { if (success) {
Cursor c = providerUtils.getWaypointsCursor( Cursor c = providerUtils.getWaypointsCursor(
track.getId(), 0, track.getId(), 0,
MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS); Constants.MAX_LOADED_WAYPOINTS_POINTS);
if (c != null) { if (c != null) {
try { try {
if (c.getCount() > 1 && c.moveToFirst()) { if (c.getCount() > 1 && c.moveToFirst()) {
// This will skip the 1st waypoint (it carries the stats for the // This will skip the 1st waypoint (it carries the stats for the
// last segment). // last segment).
ArrayList<WaypointData> waypoints = new ArrayList<WaypointData>(c.getCount() - 1); ArrayList<Waypoint> waypoints = new ArrayList<Waypoint>(c.getCount() - 1);
while (c.moveToNext()) { while (c.moveToNext()) {
Waypoint wpt = providerUtils.createWaypoint(c); Waypoint wpt = providerUtils.createWaypoint(c);
waypoints.add(new WaypointData( waypoints.add(wpt);
wpt.getName(), wpt.getDescription(), wpt.getIcon(), wpt.getLocation()));
} }
success = mapsClient.uploadWaypoints(mapId, waypoints); success = mapsClient.uploadWaypoints(mapId, waypoints);
@@ -165,8 +164,7 @@ public class SendToMyMaps implements Runnable {
} }
if (!success) { if (!success) {
Log.w(MyTracksConstants.TAG, Log.w(TAG, "SendToMyMaps: upload waypoints failed.");
"SendToMyMaps: upload waypoints failed.");
} }
} }
@@ -175,7 +173,7 @@ public class SendToMyMaps implements Runnable {
? R.string.status_new_mymap_has_been_created ? R.string.status_new_mymap_has_been_created
: R.string.status_tracks_have_been_uploaded; : R.string.status_tracks_have_been_uploaded;
} }
Log.d(MyTracksConstants.TAG, "SendToMyMaps: Done: " + success); Log.d(TAG, "SendToMyMaps: Done: " + success);
progressIndicator.setProgressValue(100); progressIndicator.setProgressValue(100);
} finally { } finally {
if (mapsClient != null) { if (mapsClient != null) {
@@ -210,7 +208,7 @@ public class SendToMyMaps implements Runnable {
providerUtils.getLocationsCursor(track.getId(), 0, -1, false); providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
try { try {
if (!locationsCursor.moveToFirst()) { 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; return false;
} }
@@ -223,7 +221,7 @@ public class SendToMyMaps implements Runnable {
// Limit the number of elevation readings. Ideally we would want around 250. // Limit the number of elevation readings. Ideally we would want around 250.
int elevationSamplingFrequency = int elevationSamplingFrequency =
Math.max(1, (int) (totalLocations / 250.0)); Math.max(1, (int) (totalLocations / 250.0));
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"Using elevation sampling factor: " + elevationSamplingFrequency "Using elevation sampling factor: " + elevationSamplingFrequency
+ " on " + totalLocations); + " on " + totalLocations);
double totalDistance = 0; double totalDistance = 0;
@@ -231,7 +229,7 @@ public class SendToMyMaps implements Runnable {
Vector<Double> distances = new Vector<Double>(); Vector<Double> distances = new Vector<Double>();
Vector<Double> elevations = new Vector<Double>(); Vector<Double> elevations = new Vector<Double>();
DoubleBuffer elevationBuffer = DoubleBuffer elevationBuffer =
new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD); List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
progressIndicator.setProgressMessage( progressIndicator.setProgressMessage(
@@ -312,7 +310,7 @@ public class SendToMyMaps implements Runnable {
int numLocations = locations.size(); int numLocations = locations.size();
if (numLocations < 2) { if (numLocations < 2) {
Log.d(MyTracksConstants.TAG, "Not preparing/uploading too few points"); Log.d(TAG, "Not preparing/uploading too few points");
totalLocationsUploaded += numLocations; totalLocationsUploaded += numLocations;
return true; return true;
} }
@@ -330,16 +328,16 @@ public class SendToMyMaps implements Runnable {
context.getString(R.string.part), totalSegmentsUploaded)); context.getString(R.string.part), totalSegmentsUploaded));
} }
totalSegmentsUploaded++; totalSegmentsUploaded++;
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"SendToMyMaps: Prepared feature for upload w/ " "SendToMyMaps: Prepared feature for upload w/ "
+ splitTrack.getLocations().size() + " points."); + splitTrack.getLocations().size() + " points.");
// Transmit tracks via GData feed: // Transmit tracks via GData feed:
// ------------------------------- // -------------------------------
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"SendToMyMaps: Uploading to map " + mapId + " w/ auth " + auth); "SendToMyMaps: Uploading to map " + mapId + " w/ auth " + auth);
if (!mapsClient.uploadTrackPoints(mapId, splitTrack.getName(), splitTrack.getLocations())) { if (!mapsClient.uploadTrackPoints(mapId, splitTrack.getName(), splitTrack.getLocations())) {
Log.e(MyTracksConstants.TAG, "Uploading failed"); Log.e(TAG, "Uploading failed");
return false; return false;
} }
} }
@@ -385,7 +383,7 @@ public class SendToMyMaps implements Runnable {
// Close up the last segment. // Close up the last segment.
prepareTrackSegment(segment, splitTracks); prepareTrackSegment(segment, splitTracks);
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"MyTracksSendToMyMaps: Starting new track segment..."); "MyTracksSendToMyMaps: Starting new track segment...");
startNewTrackSegment = false; startNewTrackSegment = false;
segment = new Track(); segment = new Track();
@@ -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.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat; 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.location.Location;
import android.os.Build; import android.os.Build;
@@ -30,6 +32,7 @@ import java.io.PrintWriter;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
/** /**
@@ -37,20 +40,35 @@ import java.util.TimeZone;
* As defined by: * As defined by:
* http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 * 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 * @author Sandor Dornbush
*/ */
public class TcxTrackWriter implements TrackFormatWriter { 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 PrintWriter pw = null;
private Track track; private Track track;
static final SimpleDateFormat TIMESTAMP_FORMAT = public TcxTrackWriter(Context context) {
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); this.context = context;
static {
TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
}
public TcxTrackWriter() { timestampFormatter = new SimpleDateFormat(TIMESTAMP_FORMAT);
timestampFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
} }
@Override @Override
@@ -93,16 +111,13 @@ public class TcxTrackWriter implements TrackFormatWriter {
if (pw == null) { if (pw == null) {
return; return;
} }
String startTime = timestampFormatter.format(track.getStatistics().getStartTime());
pw.println(" <Activities>"); pw.println(" <Activities>");
pw.print(" <Activity Sport=\""); pw.format(" <Activity Sport=\"%s\">\n", categoryToTcxSport(track.getCategory()));
if (track.getCategory() != null) { pw.format(" <Id>%s</Id>\n", startTime);
pw.print(track.getCategory()); pw.format(" <Lap StartTime=\"%s\">\n", startTime);
}
pw.println("\">");
pw.print(" <Id>");
pw.print(TIMESTAMP_FORMAT.format(track.getStatistics().getStartTime()));
pw.println("</Id>");
pw.println(" <Lap>");
pw.print(" <TotalTimeSeconds>"); pw.print(" <TotalTimeSeconds>");
pw.print(track.getStatistics().getTotalTime() / 1000); pw.print(track.getStatistics().getTotalTime() / 1000);
pw.println("</TotalTimeSeconds>"); pw.println("</TotalTimeSeconds>");
@@ -113,7 +128,7 @@ public class TcxTrackWriter implements TrackFormatWriter {
// Calories are a required element just put in 0. // Calories are a required element just put in 0.
pw.print("<Calories>0</Calories>"); pw.print("<Calories>0</Calories>");
pw.println("<Intensity>Active</Intensity>"); pw.println("<Intensity>Active</Intensity>");
pw.println("<TriggerMethod>Manual</TriggerMethod>)"); pw.println("<TriggerMethod>Manual</TriggerMethod>");
} }
@Override @Override
@@ -130,7 +145,7 @@ public class TcxTrackWriter implements TrackFormatWriter {
} }
pw.println(" <Trackpoint>"); pw.println(" <Trackpoint>");
Date d = new Date(location.getTime()); Date d = new Date(location.getTime());
pw.println(" <Time>" + TIMESTAMP_FORMAT.format(d) + "</Time>"); pw.println(" <Time>" + timestampFormatter.format(d) + "</Time>");
pw.println(" <Position>"); pw.println(" <Position>");
pw.print(" <LatitudeDegrees>"); pw.print(" <LatitudeDegrees>");
@@ -194,10 +209,18 @@ public class TcxTrackWriter implements TrackFormatWriter {
} }
pw.println(" </Lap>"); pw.println(" </Lap>");
pw.print(" <Creator xsi:type=\"Device_t\">"); pw.print(" <Creator xsi:type=\"Device_t\">");
pw.print("<Name>"); pw.format("<Name>%s</Name>\n", Build.MODEL);
pw.print(Build.MODEL);
pw.print("</Name>"); // The following code is correct. ID is inconsistently capitalized in the
pw.println("</Creator>)"); // TCX schema.
pw.println("<UnitId>0</UnitId>");
pw.println("<ProductID>0</ProductID>");
pw.println("<Version>");
pw.println("<VersionMajor>0</VersionMajor>");
pw.println("<VersionMinor>0</VersionMinor>");
pw.println("</Version>");
pw.println("</Creator>");
pw.println(" </Activity>"); pw.println(" </Activity>");
pw.println(" </Activities>"); pw.println(" </Activities>");
} }
@@ -207,8 +230,31 @@ public class TcxTrackWriter implements TrackFormatWriter {
if (pw == null) { if (pw == null) {
return; return;
} }
pw.print(" <Author xsi:type=\"Application_t\">"); pw.println(" <Author xsi:type=\"Application_t\">");
pw.print("<Name>My Tracks by Google</Name>");
// 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("<Name>My Tracks %s by Google</Name>\n", MyTracksUtils.getMyTracksVersion(context));
pw.println("<Build>");
// 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("<Version>");
pw.format("<VersionMajor>%d</VersionMajor>\n", MyTracksUtils.getMyTracksVersion(context));
pw.format("<VersionMinor>%d</VersionMinor>\n", MyTracksUtils.isRelease(context) ? 0 : 1);
pw.println("</Version>");
pw.format("<Type>%s</Type>\n", MyTracksUtils.isRelease(context) ? TCX_TYPE_RELEASE
: TCX_TYPE_INTERNAL);
pw.println("</Build>");
pw.format("<LangID>%s</LangID>\n", Locale.getDefault().getLanguage());
pw.println("<PartNumber>000-00000-00</PartNumber>");
pw.println("</Author>"); pw.println("</Author>");
pw.println("</TrainingCenterDatabase>"); pw.println("</TrainingCenterDatabase>");
} }
@@ -217,4 +263,15 @@ public class TcxTrackWriter implements TrackFormatWriter {
public void writeWaypoint(Waypoint waypoint) { public void writeWaypoint(Waypoint waypoint) {
// TODO Write out the waypoints somewhere. // 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;
}
}
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.io; 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.MyTracksLocation;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
@@ -160,16 +160,16 @@ public class TrackWriter {
String fileName = fileUtils.buildUniqueFileName( String fileName = fileUtils.buildUniqueFileName(
directory, track.getName(), writer.getExtension()); directory, track.getName(), writer.getExtension());
if (fileName == null) { if (fileName == null) {
Log.e(MyTracksConstants.TAG, Log.e(Constants.TAG,
"Unable to get a unique filename for " + fileName); "Unable to get a unique filename for " + fileName);
return false; return false;
} }
Log.i(MyTracksConstants.TAG, "Writing track to: " + fileName); Log.i(Constants.TAG, "Writing track to: " + fileName);
try { try {
writer.prepare(track, newOutputStream(fileName)); writer.prepare(track, newOutputStream(fileName));
} catch (FileNotFoundException e) { } 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; errorMessage = R.string.io_write_failed;
return false; return false;
} }
@@ -187,12 +187,12 @@ public class TrackWriter {
} }
if (!fileUtils.isSdCardAvailable()) { 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; errorMessage = R.string.io_no_external_storage_found;
return false; return false;
} }
if (!fileUtils.ensureDirectoryExists(directory)) { 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; errorMessage = R.string.io_create_dir_failed;
return false; return false;
} }
@@ -230,7 +230,7 @@ public class TrackWriter {
// same time. // same time.
Cursor cursor = null; Cursor cursor = null;
cursor = providerUtils.getWaypointsCursor(trackId, 0, cursor = providerUtils.getWaypointsCursor(trackId, 0,
MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS); Constants.MAX_LOADED_WAYPOINTS_POINTS);
if (cursor != null) { if (cursor != null) {
try { try {
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
@@ -253,14 +253,14 @@ public class TrackWriter {
* Does the actual work of writing the track to the now open file. * Does the actual work of writing the track to the now open file.
*/ */
void writeDocument() { void writeDocument() {
Log.d(MyTracksConstants.TAG, "Started writing track."); Log.d(Constants.TAG, "Started writing track.");
writer.writeHeader(); writer.writeHeader();
writeWaypoints(track.getId()); writeWaypoints(track.getId());
writeLocations(); writeLocations();
writer.writeFooter(); writer.writeFooter();
writer.close(); writer.close();
success = true; success = true;
Log.d(MyTracksConstants.TAG, "Done writing track."); Log.d(Constants.TAG, "Done writing track.");
errorMessage = R.string.io_write_finished; errorMessage = R.string.io_write_finished;
} }
@@ -296,7 +296,7 @@ public class TrackWriter {
locationFactory); locationFactory);
try { try {
if (!it.hasNext()) { 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; return;
} }
while (it.hasNext()) { while (it.hasNext()) {
@@ -53,7 +53,7 @@ public class TrackWriterFactory {
TCX { TCX {
@Override @Override
public TrackFormatWriter newFormatWriter(Context context) { public TrackFormatWriter newFormatWriter(Context context) {
return new TcxTrackWriter(); return new TcxTrackWriter(context);
} }
}; };
@@ -16,7 +16,7 @@
package com.google.android.apps.mytracks.io.backup; package com.google.android.apps.mytracks.io.backup;
import com.google.android.apps.mytracks.MyTracks; 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.apps.mytracks.util.FileUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -97,7 +97,7 @@ public class BackupActivityHelper {
backup.writeToDefaultFile(); backup.writeToDefaultFile();
showToast(R.string.io_write_finished); showToast(R.string.io_write_finished);
} catch (IOException e) { } 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); showToast(R.string.io_write_failed);
} finally { } finally {
dismissDialog(progressDialog); dismissDialog(progressDialog);
@@ -199,7 +199,7 @@ public class BackupActivityHelper {
backup.restoreFromDate(date); backup.restoreFromDate(date);
showToast(R.string.io_read_finished); showToast(R.string.io_read_finished);
} catch (IOException e) { } 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); showToast(R.string.io_read_failed);
} finally { } finally {
dismissDialog(progressDialog); dismissDialog(progressDialog);
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.io.backup; 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.MyTracksSettings;
import com.google.android.apps.mytracks.content.TrackPointsColumns; import com.google.android.apps.mytracks.content.TrackPointsColumns;
import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.content.TracksColumns;
@@ -88,7 +88,7 @@ class ExternalFileBackup {
private File getBackupsDirectory(boolean create) { private File getBackupsDirectory(boolean create) {
String dirName = fileUtils.buildExternalDirectoryPath(BACKUPS_SUBDIR); String dirName = fileUtils.buildExternalDirectoryPath(BACKUPS_SUBDIR);
final File dir = new File(dirName); final File dir = new File(dirName);
Log.d(MyTracksConstants.TAG, "Dir: " + dir.getAbsolutePath()); Log.d(Constants.TAG, "Dir: " + dir.getAbsolutePath());
if (create) { if (create) {
// Try to create - if that fails, return null // Try to create - if that fails, return null
return fileUtils.ensureDirectoryExists(dir) ? dir : null; return fileUtils.ensureDirectoryExists(dir) ? dir : null;
@@ -147,7 +147,7 @@ class ExternalFileBackup {
* Synchronously writes a backup to the given file. * Synchronously writes a backup to the given file.
*/ */
private void writeToFile(File outputFile) throws IOException { private void writeToFile(File outputFile) throws IOException {
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"Writing backup to file " + outputFile.getAbsolutePath()); "Writing backup to file " + outputFile.getAbsolutePath());
// Create all the auxiliary classes that will do the writing // Create all the auxiliary classes that will do the writing
@@ -219,7 +219,7 @@ class ExternalFileBackup {
* Synchronously restores the backup from the given file. * Synchronously restores the backup from the given file.
*/ */
private void restoreFromFile(File inputFile) throws IOException { private void restoreFromFile(File inputFile) throws IOException {
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"Restoring from file " + inputFile.getAbsolutePath()); "Restoring from file " + inputFile.getAbsolutePath());
PreferenceBackupHelper preferencesHelper = new PreferenceBackupHelper(); PreferenceBackupHelper preferencesHelper = new PreferenceBackupHelper();
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.io.backup; 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.MyTracksSettings;
import android.app.backup.BackupAgent; import android.app.backup.BackupAgent;
@@ -40,12 +40,12 @@ public class MyTracksBackupAgent extends BackupAgent {
@Override @Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException { ParcelFileDescriptor newState) throws IOException {
Log.i(MyTracksConstants.TAG, "Performing backup"); Log.i(Constants.TAG, "Performing backup");
SharedPreferences preferences = this.getSharedPreferences( SharedPreferences preferences = this.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); MyTracksSettings.SETTINGS_NAME, 0);
backupPreferences(data, preferences); backupPreferences(data, preferences);
Log.i(MyTracksConstants.TAG, "Backup complete"); Log.i(Constants.TAG, "Backup complete");
} }
private void backupPreferences(BackupDataOutput data, private void backupPreferences(BackupDataOutput data,
@@ -63,18 +63,18 @@ public class MyTracksBackupAgent extends BackupAgent {
@Override @Override
public void onRestore(BackupDataInput data, int appVersionCode, public void onRestore(BackupDataInput data, int appVersionCode,
ParcelFileDescriptor newState) throws IOException { ParcelFileDescriptor newState) throws IOException {
Log.i(MyTracksConstants.TAG, "Restoring from backup"); Log.i(Constants.TAG, "Restoring from backup");
while (data.readNextHeader()) { while (data.readNextHeader()) {
String key = data.getKey(); String key = data.getKey();
Log.d(MyTracksConstants.TAG, "Restoring entity " + key); Log.d(Constants.TAG, "Restoring entity " + key);
if (key.equals(PREFERENCES_ENTITY)) { if (key.equals(PREFERENCES_ENTITY)) {
restorePreferences(data); restorePreferences(data);
} else { } else {
Log.e(MyTracksConstants.TAG, "Found unknown backup entity: " + key); Log.e(Constants.TAG, "Found unknown backup entity: " + key);
data.skipEntityData(); data.skipEntityData();
} }
} }
Log.i(MyTracksConstants.TAG, "Done restoring from backup"); Log.i(Constants.TAG, "Done restoring from backup");
} }
/** /**
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.io.docs; 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.content.Track;
import com.google.android.apps.mytracks.io.AuthManager; import com.google.android.apps.mytracks.io.AuthManager;
import com.google.android.apps.mytracks.io.gdata.GDataWrapper; import com.google.android.apps.mytracks.io.gdata.GDataWrapper;
@@ -144,7 +144,7 @@ public class DocsHelper {
String id = result.substring( String id = result.substring(
idStringStart + DOCS_SPREADSHEET_URL.length(), idTagCloseIndex); 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); idSaver.set(id);
}}); }});
@@ -184,7 +184,7 @@ public class DocsHelper {
while (listParser.hasMoreData()) { while (listParser.hasMoreData()) {
Entry entry = listParser.readNextEntry(null); Entry entry = listParser.readNextEntry(null);
String entryTitle = entry.getTitle(); String entryTitle = entry.getTitle();
Log.i(MyTracksConstants.TAG, "Found docs entry: " + entryTitle); Log.i(Constants.TAG, "Found docs entry: " + entryTitle);
if (entryTitle.equals(title)) { if (entryTitle.equals(title)) {
String entryId = entry.getId(); String entryId = entry.getId();
int lastSlash = entryId.lastIndexOf('/'); int lastSlash = entryId.lastIndexOf('/');
@@ -233,7 +233,7 @@ public class DocsHelper {
trixWrapper.getAuthManager().getAuthToken()); trixWrapper.getAuthManager().getAuthToken());
sheetParser.init(); sheetParser.init();
if (!sheetParser.hasMoreData()) { if (!sheetParser.hasMoreData()) {
Log.i(MyTracksConstants.TAG, "Found no worksheets"); Log.i(Constants.TAG, "Found no worksheets");
return; return;
} }
@@ -308,7 +308,7 @@ public class DocsHelper {
if (track.getMapId().length() > 0) { if (track.getMapId().length() > 0) {
tagBuilder.append("map", String.format("%s?msa=0&msid=%s", 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() String postText = new StringBuilder()
@@ -319,14 +319,14 @@ public class DocsHelper {
.append("</entry>") .append("</entry>")
.toString(); .toString();
Log.i(MyTracksConstants.TAG, Log.i(Constants.TAG,
"Inserting at: " + spreadsheetId + " => " + worksheetUri); "Inserting at: " + spreadsheetId + " => " + worksheetUri);
Log.i(MyTracksConstants.TAG, postText); Log.i(Constants.TAG, postText);
writeRowData(trixAuth, worksheetUri, 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; String line;
while ((line = rd.readLine()) != null) { while ((line = rd.readLine()) != null) {
// Process line. // Process line.
Log.i(MyTracksConstants.TAG, "r: " + line); Log.i(Constants.TAG, "r: " + line);
} }
wr.close(); wr.close();
rd.close(); rd.close();
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.io.gdata; 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 com.google.wireless.gdata.client.GDataClient;
import android.content.Context; import android.content.Context;
@@ -43,7 +43,7 @@ public class GDataClientFactory {
} catch (LinkageError e) { } catch (LinkageError e) {
// On all other platforms use the client implementation packaged in the // On all other platforms use the client implementation packaged in the
// apk. // 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(); return new com.google.android.apps.mytracks.io.gdata.AndroidGDataClient();
} }
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.io.gdata; 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 com.google.android.apps.mytracks.io.AuthManager;
import android.util.Log; import android.util.Log;
@@ -173,14 +173,14 @@ public class GDataWrapper<C> {
return true; 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 (errorType == ERROR_AUTH && auth != null) {
if (!retryOnAuthFailure || !invalidateAndRefreshAuthToken()) { if (!retryOnAuthFailure || !invalidateAndRefreshAuthToken()) {
return false; return false;
} }
} }
Log.d(MyTracksConstants.TAG, "retrying function/query"); Log.d(Constants.TAG, "retrying function/query");
} }
return false; return false;
} }
@@ -206,11 +206,11 @@ public class GDataWrapper<C> {
errorMessage = null; errorMessage = null;
} catch (AuthenticationException e) { } catch (AuthenticationException e) {
Log.e(MyTracksConstants.TAG, "AuthenticationException", e); Log.e(Constants.TAG, "AuthenticationException", e);
errorType = ERROR_AUTH; errorType = ERROR_AUTH;
errorMessage = e.getMessage(); errorMessage = e.getMessage();
} catch (HttpException e) { } catch (HttpException e) {
Log.e(MyTracksConstants.TAG, Log.e(Constants.TAG,
"HttpException, code " + e.getStatusCode() + " message " + e.getMessage(), e); "HttpException, code " + e.getStatusCode() + " message " + e.getMessage(), e);
errorMessage = e.getMessage(); errorMessage = e.getMessage();
if (e.getStatusCode() == 401) { if (e.getStatusCode() == 401) {
@@ -219,11 +219,11 @@ public class GDataWrapper<C> {
errorType = ERROR_CONNECTION; errorType = ERROR_CONNECTION;
} }
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
Log.e(MyTracksConstants.TAG, "Exception", e); Log.e(Constants.TAG, "Exception", e);
errorType = ERROR_AUTH; errorType = ERROR_AUTH;
errorMessage = e.getMessage(); errorMessage = e.getMessage();
} catch (IOException e) { } catch (IOException e) {
Log.e(MyTracksConstants.TAG, "Exception", e); Log.e(Constants.TAG, "Exception", e);
errorMessage = e.getMessage(); errorMessage = e.getMessage();
if (errorMessage != null && errorMessage.contains("503")) { if (errorMessage != null && errorMessage.contains("503")) {
errorType = ERROR_INTERNAL; errorType = ERROR_INTERNAL;
@@ -231,11 +231,11 @@ public class GDataWrapper<C> {
errorType = ERROR_CONNECTION; errorType = ERROR_CONNECTION;
} }
} catch (ParseException e) { } catch (ParseException e) {
Log.e(MyTracksConstants.TAG, "Exception", e); Log.e(Constants.TAG, "Exception", e);
errorType = ERROR_LOCAL; errorType = ERROR_LOCAL;
errorMessage = e.getMessage(); errorMessage = e.getMessage();
} catch (ConflictDetectedException e) { } catch (ConflictDetectedException e) {
Log.e(MyTracksConstants.TAG, "Exception", e); Log.e(Constants.TAG, "Exception", e);
errorType = ERROR_CONFLICT; errorType = ERROR_CONFLICT;
errorMessage = e.getMessage(); errorMessage = e.getMessage();
} }
@@ -249,7 +249,7 @@ public class GDataWrapper<C> {
* times out. * times out.
*/ */
private boolean invalidateAndRefreshAuthToken() { 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 // This FutureTask doesn't do anything -- it exists simply to be
// blocked upon using get(). // blocked upon using get().
FutureTask<?> whenFinishedFuture = new FutureTask<Object>(new Runnable() { FutureTask<?> whenFinishedFuture = new FutureTask<Object>(new Runnable() {
@@ -259,18 +259,18 @@ public class GDataWrapper<C> {
auth.invalidateAndRefresh(whenFinishedFuture); auth.invalidateAndRefresh(whenFinishedFuture);
try { try {
Log.d(MyTracksConstants.TAG, "waiting for invalidate"); Log.d(Constants.TAG, "waiting for invalidate");
whenFinishedFuture.get(AUTH_TOKEN_INVALIDATE_REFRESH_TIMEOUT, whenFinishedFuture.get(AUTH_TOKEN_INVALIDATE_REFRESH_TIMEOUT,
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
Log.d(MyTracksConstants.TAG, "invalidate finished"); Log.d(Constants.TAG, "invalidate finished");
return true; return true;
} catch (InterruptedException e) { } catch (InterruptedException e) {
Log.e(MyTracksConstants.TAG, "Failed to invalidate", e); Log.e(Constants.TAG, "Failed to invalidate", e);
} catch (ExecutionException e) { } catch (ExecutionException e) {
Log.e(MyTracksConstants.TAG, "Failed to invalidate", e); Log.e(Constants.TAG, "Failed to invalidate", e);
} catch (TimeoutException 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 { } finally {
whenFinishedFuture.cancel(false); whenFinishedFuture.cancel(false);
} }
@@ -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;
}
}
@@ -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<String, String> mAttributes = new HashMap<String, String>();
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<String, String> getAllAttributes() {
return mAttributes;
}
}
@@ -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);
}
}
@@ -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", "<br>"));
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<Waypoint> 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<Location> 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<Location> 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<Location> 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));
}
}
@@ -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() { }
}
@@ -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<Integer> latitudeE6 = new Vector<Integer>();
/**
* The longitudes of the points of this feature in order, specified in
* millionths of a degree east.
*/
private final Vector<Integer> longitudeE6 = new Vector<Integer>();
/** 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);
}
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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);
}
}
@@ -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 &lt;entry&gt;.
*
* @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("<![CDATA[");
contentBuilder.append(parser.getText());
contentBuilder.append("]]>");
break;
case XmlPullParser.END_TAG:
if (parser.getDepth() > parentDepth) {
contentBuilder.append("</");
contentBuilder.append(parser.getName());
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();
}
}
}
@@ -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<? extends Entry> 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);
}
}
}
@@ -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("</Placemark>")) {
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<String, String> attrs = entry.getAllAttributes();
for (Map.Entry<String, String> 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");
}
}
}
}
@@ -16,7 +16,7 @@
package com.google.android.apps.mytracks.services; 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.content.Context;
import android.media.AudioManager; import android.media.AudioManager;
@@ -16,7 +16,7 @@
package com.google.android.apps.mytracks.services; 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; import android.util.Log;
@@ -77,7 +77,7 @@ public class PeriodicTaskExecuter {
} }
Date start = new Date(next); Date start = new Date(next);
Log.i(MyTracksConstants.TAG, Log.i(Constants.TAG,
task.getClass().getSimpleName() + " scheduled to start at " + start task.getClass().getSimpleName() + " scheduled to start at " + start
+ " every " + interval + " milliseconds."); + " every " + interval + " milliseconds.");
timer.scheduleAtFixedRate(new PeriodicTimerTask(), start, interval); timer.scheduleAtFixedRate(new PeriodicTimerTask(), start, interval);
@@ -87,7 +87,7 @@ public class PeriodicTaskExecuter {
* Cleans up this object. * Cleans up this object.
*/ */
public void shutdown() { public void shutdown() {
Log.i(MyTracksConstants.TAG, Log.i(Constants.TAG,
task.getClass().getSimpleName() + " shutting down."); task.getClass().getSimpleName() + " shutting down.");
if (timer != null) { if (timer != null) {
timer.cancel(); timer.cancel();
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.services; 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.apps.mytracks.MyTracksSettings;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -47,7 +47,7 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener {
this.sharedPreferences = service.getSharedPreferences( this.sharedPreferences = service.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0); MyTracksSettings.SETTINGS_NAME, 0);
if (sharedPreferences == null) { if (sharedPreferences == null) {
Log.w(MyTracksConstants.TAG, Log.w(Constants.TAG,
"TrackRecordingService: Couldn't get shared preferences."); "TrackRecordingService: Couldn't get shared preferences.");
throw new IllegalStateException("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, public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) { String key) {
if (service == null) { if (service == null) {
Log.w(MyTracksConstants.TAG, Log.w(Constants.TAG,
"onSharedPreferenceChanged: a preference change (key = " + key "onSharedPreferenceChanged: a preference change (key = " + key
+ ") after a call to shutdown()"); + ") after a call to shutdown()");
return; return;
@@ -98,7 +98,7 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener {
sharedPreferences.getInt( sharedPreferences.getInt(
minRecordingDistanceKey, minRecordingDistanceKey,
MyTracksSettings.DEFAULT_MIN_RECORDING_DISTANCE)); MyTracksSettings.DEFAULT_MIN_RECORDING_DISTANCE));
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"TrackRecordingService: minRecordingDistance = " "TrackRecordingService: minRecordingDistance = "
+ service.getMinRecordingDistance()); + service.getMinRecordingDistance());
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.services; 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.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.util.UnitConversions; import com.google.android.apps.mytracks.util.UnitConversions;
@@ -81,7 +81,7 @@ public class SplitManager {
if (splitFrequency >= 0) { if (splitFrequency >= 0) {
nextSplitDistance = Double.MAX_VALUE; nextSplitDistance = Double.MAX_VALUE;
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"SplitManager: Distance splits disabled."); "SplitManager: Distance splits disabled.");
return; return;
} }
@@ -94,7 +94,7 @@ public class SplitManager {
int index = (int) (dist / splitFrequency); int index = (int) (dist / splitFrequency);
index -= 1; index -= 1;
nextSplitDistance = splitFrequency * index; nextSplitDistance = splitFrequency * index;
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"SplitManager: Next split distance: " + nextSplitDistance); "SplitManager: Next split distance: " + nextSplitDistance);
} }
@@ -126,7 +126,7 @@ public class SplitManager {
* @param splitFrequency The frequency in time or distance * @param splitFrequency The frequency in time or distance
*/ */
public void setSplitFrequency(int splitFrequency) { public void setSplitFrequency(int splitFrequency) {
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"setSplitFrequency: splitFrequency = " + splitFrequency); "setSplitFrequency: splitFrequency = " + splitFrequency);
this.splitFrequency = splitFrequency; this.splitFrequency = splitFrequency;
@@ -16,7 +16,9 @@
package com.google.android.apps.mytracks.services; 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.MyTracksSettings;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.StringUtils; import com.google.android.apps.mytracks.util.StringUtils;
@@ -99,7 +101,7 @@ public class StatusAnnouncerTask implements PeriodicTask {
* Called when the TTS engine is initialized. * Called when the TTS engine is initialized.
*/ */
protected void onTtsInit(int status) { 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; this.ready = status == TextToSpeech.SUCCESS;
if (ready) { if (ready) {
@@ -111,7 +113,7 @@ public class StatusAnnouncerTask implements PeriodicTask {
languageAvailability == TextToSpeech.LANG_NOT_SUPPORTED) { languageAvailability == TextToSpeech.LANG_NOT_SUPPORTED) {
// English is probably supported. // English is probably supported.
// TODO: Somehow use announcement strings from English too. // 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; speechLanguage = Locale.ENGLISH;
} }
tts.setLanguage(speechLanguage); tts.setLanguage(speechLanguage);
@@ -129,7 +131,7 @@ public class StatusAnnouncerTask implements PeriodicTask {
@Override @Override
public void run(TrackRecordingService service) { public void run(TrackRecordingService service) {
if (service == null) { if (service == null) {
Log.e(MyTracksConstants.TAG, "StatusAnnouncer TrackRecordingService not initialized"); Log.e(TAG, "StatusAnnouncer TrackRecordingService not initialized");
return; return;
} }
@@ -143,23 +145,22 @@ public class StatusAnnouncerTask implements PeriodicTask {
*/ */
protected void runWithStatistics(TripStatistics statistics) { protected void runWithStatistics(TripStatistics statistics) {
if (statistics == null) { if (statistics == null) {
Log.e(MyTracksConstants.TAG, "StatusAnnouncer stats not initialized."); Log.e(TAG, "StatusAnnouncer stats not initialized.");
return; return;
} }
if (!ready || tts == null) { if (!ready || tts == null) {
Log.e(MyTracksConstants.TAG, "StatusAnnouncer Tts not ready."); Log.e(TAG, "StatusAnnouncer Tts not ready.");
return; return;
} }
if (!speechAllowed) { if (!speechAllowed) {
Log.i(MyTracksConstants.TAG, Log.i(Constants.TAG,
"Not making announcement - not allowed at this time"); "Not making announcement - not allowed at this time");
return; return;
} }
String announcement = getAnnouncement(statistics); String announcement = getAnnouncement(statistics);
Log.d(MyTracksConstants.TAG, "Announcement: " + announcement); Log.d(Constants.TAG, "Announcement: " + announcement);
speakAnnouncment(announcement); speakAnnouncment(announcement);
} }
@@ -218,7 +219,7 @@ public class StatusAnnouncerTask implements PeriodicTask {
speed = String.format("%.1f", s); speed = String.format("%.1f", s);
} else { } else {
double pace = 3600000.0 / s; double pace = 3600000.0 / s;
Log.w(MyTracksConstants.TAG, Log.w(Constants.TAG,
"Converted speed: " + s + " to pace: " + pace); "Converted speed: " + s + " to pace: " + pace);
speed = stringUtils.formatTimeLong((long) pace); speed = stringUtils.formatTimeLong((long) pace);
} }
@@ -237,7 +238,7 @@ public class StatusAnnouncerTask implements PeriodicTask {
@Override @Override
public void start() { public void start() {
Log.i(MyTracksConstants.TAG, "Starting TTS"); Log.i(Constants.TAG, "Starting TTS");
if (tts == null) { if (tts == null) {
// We can't have this class also be the listener, otherwise it's unsafe to // 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). // reference it in Cupcake (even if we don't instantiate it).
@@ -264,7 +265,7 @@ public class StatusAnnouncerTask implements PeriodicTask {
tts = null; tts = null;
} }
Log.i(MyTracksConstants.TAG, "TTS shut down"); Log.i(Constants.TAG, "TTS shut down");
} }
/** /**
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.services; 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; import android.util.Log;
@@ -49,14 +49,14 @@ public class TaskExecuterManager {
*/ */
public void setFrequency(int frequency, TrackRecordingService service) { public void setFrequency(int frequency, TrackRecordingService service) {
this.frequency = frequency; this.frequency = frequency;
Log.i(MyTracksConstants.TAG, "Frequency set to " + frequency Log.i(Constants.TAG, "Frequency set to " + frequency
+ " for task " + task.getClass().getSimpleName()); + " for task " + task.getClass().getSimpleName());
if (frequency == -1) { if (frequency == -1) {
if (executer != null) { if (executer != null) {
executer.shutdown(); executer.shutdown();
executer = null; executer = null;
Log.i(MyTracksConstants.TAG, Log.i(Constants.TAG,
"Shut down service: " + task.getClass().getSimpleName()); "Shut down service: " + task.getClass().getSimpleName());
} }
} else { } else {
@@ -15,20 +15,21 @@
*/ */
package com.google.android.apps.mytracks.services; 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.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.MyTracksSettings;
import com.google.android.apps.mytracks.content.MyTracksLocation; import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointCreationRequest; import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.content.WaypointsColumns; 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.SensorManager;
import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory; import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
@@ -144,7 +145,7 @@ public class TrackRecordingService extends Service implements LocationListener {
if (isRecording()) { if (isRecording()) {
handler.post(new Runnable() { handler.post(new Runnable() {
public void run() { public void run() {
Log.d(MyTracksConstants.TAG, Log.d(Constants.TAG,
"Re-registering location listener with TrackRecordingService."); "Re-registering location listener with TrackRecordingService.");
unregisterLocationListener(); unregisterLocationListener();
registerLocationListener(); registerLocationListener();
@@ -269,7 +270,7 @@ public class TrackRecordingService extends Service implements LocationListener {
// Insert failed, most likely because of SqlLite error code 5 // Insert failed, most likely because of SqlLite error code 5
// (SQLite_BUSY). This is expected to happen extremely rarely (if our // (SQLite_BUSY). This is expected to happen extremely rarely (if our
// listener gets invoked twice at about the same time). // listener gets invoked twice at about the same time).
Log.w(MyTracksConstants.TAG, Log.w(TAG,
"Caught SQLiteException: " + e.getMessage(), e); "Caught SQLiteException: " + e.getMessage(), e);
return false; return false;
} }
@@ -314,15 +315,15 @@ public class TrackRecordingService extends Service implements LocationListener {
try { try {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm == null) { if (pm == null) {
Log.e(MyTracksConstants.TAG, Log.e(TAG,
"TrackRecordingService: Power manager not found!"); "TrackRecordingService: Power manager not found!");
return; return;
} }
if (wakeLock == null) { if (wakeLock == null) {
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
MyTracksConstants.TAG); TAG);
if (wakeLock == null) { if (wakeLock == null) {
Log.e(MyTracksConstants.TAG, Log.e(TAG,
"TrackRecordingService: Could not create wake lock (null)."); "TrackRecordingService: Could not create wake lock (null).");
return; return;
} }
@@ -330,12 +331,12 @@ public class TrackRecordingService extends Service implements LocationListener {
if (!wakeLock.isHeld()) { if (!wakeLock.isHeld()) {
wakeLock.acquire(); wakeLock.acquire();
if (!wakeLock.isHeld()) { if (!wakeLock.isHeld()) {
Log.e(MyTracksConstants.TAG, Log.e(TAG,
"TrackRecordingService: Could not acquire wake lock."); "TrackRecordingService: Could not acquire wake lock.");
} }
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.e(MyTracksConstants.TAG, Log.e(TAG,
"TrackRecordingService: Caught unexpected exception: " "TrackRecordingService: Caught unexpected exception: "
+ e.getMessage(), e); + e.getMessage(), e);
} }
@@ -376,37 +377,37 @@ public class TrackRecordingService extends Service implements LocationListener {
public void registerLocationListener() { public void registerLocationListener() {
if (locationManager == null) { if (locationManager == null) {
Log.e(MyTracksConstants.TAG, Log.e(TAG,
"TrackRecordingService: Do not have any location manager."); "TrackRecordingService: Do not have any location manager.");
return; return;
} }
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"Preparing to register location listener w/ TrackRecordingService..."); "Preparing to register location listener w/ TrackRecordingService...");
try { try {
long desiredInterval = locationListenerPolicy.getDesiredPollingInterval(); long desiredInterval = locationListenerPolicy.getDesiredPollingInterval();
locationManager.requestLocationUpdates( locationManager.requestLocationUpdates(
MyTracksConstants.GPS_PROVIDER, desiredInterval, Constants.GPS_PROVIDER, desiredInterval,
locationListenerPolicy.getMinDistance(), locationListenerPolicy.getMinDistance(),
// , 0 /* minDistance, get all updates to properly time pauses */ // , 0 /* minDistance, get all updates to properly time pauses */
TrackRecordingService.this); TrackRecordingService.this);
currentRecordingInterval = desiredInterval; currentRecordingInterval = desiredInterval;
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"...location listener now registered w/ TrackRecordingService @ " "...location listener now registered w/ TrackRecordingService @ "
+ currentRecordingInterval); + currentRecordingInterval);
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.e(MyTracksConstants.TAG, Log.e(TAG,
"Could not register location listener: " + e.getMessage(), e); "Could not register location listener: " + e.getMessage(), e);
} }
} }
public void unregisterLocationListener() { public void unregisterLocationListener() {
if (locationManager == null) { if (locationManager == null) {
Log.e(MyTracksConstants.TAG, Log.e(TAG,
"TrackRecordingService: Do not have any location manager."); "TrackRecordingService: Do not have any location manager.");
return; return;
} }
locationManager.removeUpdates(this); locationManager.removeUpdates(this);
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"Location listener now unregistered w/ TrackRecordingService."); "Location listener now unregistered w/ TrackRecordingService.");
} }
@@ -419,7 +420,7 @@ public class TrackRecordingService extends Service implements LocationListener {
} }
private void restoreStats(Track track) { private void restoreStats(Track track) {
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"Restoring stats of track with ID: " + track.getId()); "Restoring stats of track with ID: " + track.getId());
TripStatistics stats = track.getStatistics(); TripStatistics stats = track.getStatistics();
@@ -446,7 +447,7 @@ public class TrackRecordingService extends Service implements LocationListener {
Cursor cursor = null; Cursor cursor = null;
try { try {
cursor = providerUtils.getLocationsCursor( cursor = providerUtils.getLocationsCursor(
recordingTrackId, -1, MyTracksConstants.MAX_LOADED_TRACK_POINTS, recordingTrackId, -1, Constants.MAX_LOADED_TRACK_POINTS,
true); true);
if (cursor != null) { if (cursor != null) {
if (cursor.moveToLast()) { if (cursor.moveToLast()) {
@@ -465,10 +466,10 @@ public class TrackRecordingService extends Service implements LocationListener {
statsBuilder.pauseAt(stats.getStopTime()); statsBuilder.pauseAt(stats.getStopTime());
statsBuilder.resumeAt(System.currentTimeMillis()); statsBuilder.resumeAt(System.currentTimeMillis());
} else { } else {
Log.e(MyTracksConstants.TAG, "Could not get track points cursor."); Log.e(TAG, "Could not get track points cursor.");
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.e(MyTracksConstants.TAG, "Error while restoring track.", e); Log.e(TAG, "Error while restoring track.", e);
} finally { } finally {
if (cursor != null) { if (cursor != null) {
cursor.close(); cursor.close();
@@ -493,12 +494,12 @@ public class TrackRecordingService extends Service implements LocationListener {
} }
private void onLocationChangedAsync(Location location) { private void onLocationChangedAsync(Location location) {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.onLocationChanged"); Log.d(TAG, "TrackRecordingService.onLocationChanged");
try { try {
// Don't record if the service has been asked to pause recording: // Don't record if the service has been asked to pause recording:
if (!isRecording) { if (!isRecording) {
Log.w(MyTracksConstants.TAG, Log.w(TAG,
"Not recording because recording has been paused."); "Not recording because recording has been paused.");
return; 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 // This should never happen, but just in case (we really don't want the
// service to crash): // service to crash):
if (location == null) { if (location == null) {
Log.w(MyTracksConstants.TAG, Log.w(TAG,
"Location changed, but location is null."); "Location changed, but location is null.");
return; return;
} }
// Don't record if the accuracy is too bad: // Don't record if the accuracy is too bad:
if (location.getAccuracy() > minRequiredAccuracy) { if (location.getAccuracy() > minRequiredAccuracy) {
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"Not recording. Bad accuracy."); "Not recording. Bad accuracy.");
return; return;
} }
@@ -521,7 +522,7 @@ public class TrackRecordingService extends Service implements LocationListener {
// At least one track must be available for appending points: // At least one track must be available for appending points:
recordingTrack = getRecordingTrack(); recordingTrack = getRecordingTrack();
if (recordingTrack == null) { if (recordingTrack == null) {
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"Not recording. No track to append to available."); "Not recording. No track to append to available.");
return; return;
} }
@@ -555,7 +556,7 @@ public class TrackRecordingService extends Service implements LocationListener {
// maxRecordingDistance = 0 // maxRecordingDistance = 0
if (distanceToLast == 0 && !hasSensorData) { if (distanceToLast == 0 && !hasSensorData) {
if (isMoving) { if (isMoving) {
Log.d(MyTracksConstants.TAG, "Found two identical locations."); Log.d(TAG, "Found two identical locations.");
isMoving = false; isMoving = false;
if (lastLocation != null && lastRecordedLocation != null if (lastLocation != null && lastRecordedLocation != null
&& !lastRecordedLocation.equals(lastLocation)) { && !lastRecordedLocation.equals(lastLocation)) {
@@ -570,7 +571,7 @@ public class TrackRecordingService extends Service implements LocationListener {
lastRecordedLocationId++; lastRecordedLocationId++;
} }
} else { } else {
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"Not recording. More than two identical locations."); "Not recording. More than two identical locations.");
} }
} else if (distanceToLastRecorded > minRecordingDistance } else if (distanceToLastRecorded > minRecordingDistance
@@ -595,8 +596,8 @@ public class TrackRecordingService extends Service implements LocationListener {
&& recordingTrack.getStartId() >= 0; && recordingTrack.getStartId() >= 0;
if (startNewSegment) { if (startNewSegment) {
// Insert a separator point to indicate start of new track: // Insert a separator point to indicate start of new track:
Log.d(MyTracksConstants.TAG, "Inserting a separator."); Log.d(TAG, "Inserting a separator.");
Location separator = new Location(MyTracksConstants.GPS_PROVIDER); Location separator = new Location(Constants.GPS_PROVIDER);
separator.setLongitude(0); separator.setLongitude(0);
separator.setLatitude(100); separator.setLatitude(100);
separator.setTime(lastRecordedLocation.getTime()); separator.setTime(lastRecordedLocation.getTime());
@@ -608,7 +609,7 @@ public class TrackRecordingService extends Service implements LocationListener {
return; return;
} }
} else { } else {
Log.d(MyTracksConstants.TAG, String.format( Log.d(TAG, String.format(
"Not recording. Distance to last recorded point (%f m) is less than" "Not recording. Distance to last recorded point (%f m) is less than"
+ " %d m.", distanceToLastRecorded, minRecordingDistance)); + " %d m.", distanceToLastRecorded, minRecordingDistance));
// Return here so that the location is NOT recorded as the last location. // 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) { } catch (Error e) {
// Probably important enough to rethrow. // Probably important enough to rethrow.
Log.e(MyTracksConstants.TAG, "Error in onLocationChanged", e); Log.e(TAG, "Error in onLocationChanged", e);
throw e; throw e;
} catch (RuntimeException e) { } catch (RuntimeException e) {
// Safe usually to trap exceptions. // Safe usually to trap exceptions.
Log.e(MyTracksConstants.TAG, Log.e(TAG,
"Trapping exception in onLocationChanged", e); "Trapping exception in onLocationChanged", e);
throw e; throw e;
} }
@@ -657,7 +658,7 @@ public class TrackRecordingService extends Service implements LocationListener {
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
Log.d(MyTracksConstants.TAG, "TrackRecordingService.onCreate"); Log.d(TAG, "TrackRecordingService.onCreate");
providerUtils = MyTracksProviderUtils.Factory.get(this); providerUtils = MyTracksProviderUtils.Factory.get(this);
notificationManager = notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE); (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
@@ -682,7 +683,7 @@ public class TrackRecordingService extends Service implements LocationListener {
} else { } else {
if (recordingTrackId != -1) { if (recordingTrackId != -1) {
// Make sure we have consistent state in shared preferences. // 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); + "Resetting an orphaned recording track = " + recordingTrackId);
} }
prefManager.setRecordingTrack(recordingTrackId = -1); prefManager.setRecordingTrack(recordingTrackId = -1);
@@ -697,7 +698,7 @@ public class TrackRecordingService extends Service implements LocationListener {
* the announcements, otherwise this method is no-op. * the announcements, otherwise this method is no-op.
*/ */
private void setUpAnnouncer() { private void setUpAnnouncer() {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.setUpAnnouncer: " Log.d(TAG, "TrackRecordingService.setUpAnnouncer: "
+ announcementExecuter); + announcementExecuter);
if (announcementFrequency != -1 && recordingTrackId != -1) { if (announcementFrequency != -1 && recordingTrackId != -1) {
handler.post(new Runnable() { handler.post(new Runnable() {
@@ -723,7 +724,7 @@ public class TrackRecordingService extends Service implements LocationListener {
} }
private void shutdownAnnouncer() { private void shutdownAnnouncer() {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.shutdownAnnouncer: " Log.d(TAG, "TrackRecordingService.shutdownAnnouncer: "
+ announcementExecuter); + announcementExecuter);
if (announcementExecuter != null) { if (announcementExecuter != null) {
try { try {
@@ -736,7 +737,7 @@ public class TrackRecordingService extends Service implements LocationListener {
@Override @Override
public void onDestroy() { public void onDestroy() {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.onDestroy"); Log.d(TAG, "TrackRecordingService.onDestroy");
isRecording = false; isRecording = false;
showNotification(); showNotification();
@@ -770,19 +771,19 @@ public class TrackRecordingService extends Service implements LocationListener {
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.onBind"); Log.d(TAG, "TrackRecordingService.onBind");
return binder; return binder;
} }
@Override @Override
public boolean onUnbind(Intent intent) { public boolean onUnbind(Intent intent) {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.onUnbind"); Log.d(TAG, "TrackRecordingService.onUnbind");
return super.onUnbind(intent); return super.onUnbind(intent);
} }
@Override @Override
public boolean stopService(Intent name) { public boolean stopService(Intent name) {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.stopService"); Log.d(TAG, "TrackRecordingService.stopService");
unregisterLocationListener(); unregisterLocationListener();
return super.stopService(name); return super.stopService(name);
} }
@@ -799,17 +800,17 @@ public class TrackRecordingService extends Service implements LocationListener {
} }
private void handleStartCommand(Intent intent, int startId) { private void handleStartCommand(Intent intent, int startId) {
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"TrackRecordingService.handleStartCommand: " + startId); "TrackRecordingService.handleStartCommand: " + startId);
// Check if called on phone reboot with resume intent. // Check if called on phone reboot with resume intent.
if (intent != null && if (intent != null &&
intent.getBooleanExtra(RESUME_TRACK_EXTRA_NAME, false)) { 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. // Make sure that the current track exists and is fresh enough.
if (recordingTrack == null || !shouldResumeTrack(recordingTrack)) { if (recordingTrack == null || !shouldResumeTrack(recordingTrack)) {
Log.i(MyTracksConstants.TAG, Log.i(TAG,
"TrackRecordingService: Not resuming, because the previous track (" "TrackRecordingService: Not resuming, because the previous track ("
+ recordingTrack + ") doesn't exist or is too old"); + recordingTrack + ") doesn't exist or is too old");
isRecording = false; isRecording = false;
@@ -818,19 +819,19 @@ public class TrackRecordingService extends Service implements LocationListener {
return; return;
} }
Log.i(MyTracksConstants.TAG, "TrackRecordingService: resuming"); Log.i(TAG, "TrackRecordingService: resuming");
} }
} }
private void setAutoResumeTrackRetries( private void setAutoResumeTrackRetries(
SharedPreferences sharedPreferences, int retryAttempts) { SharedPreferences sharedPreferences, int retryAttempts) {
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"Updating auto-resume retry attempts to: " + retryAttempts); "Updating auto-resume retry attempts to: " + retryAttempts);
prefManager.setAutoResumeTrackCurrentRetry(retryAttempts); prefManager.setAutoResumeTrackCurrentRetry(retryAttempts);
} }
private boolean shouldResumeTrack(Track track) { private boolean shouldResumeTrack(Track track) {
Log.d(MyTracksConstants.TAG, "shouldResumeTrack: autoResumeTrackTimeout = " Log.d(TAG, "shouldResumeTrack: autoResumeTrackTimeout = "
+ autoResumeTrackTimeout); + autoResumeTrackTimeout);
// Check if we haven't exceeded the maximum number of retry attempts. // Check if we haven't exceeded the maximum number of retry attempts.
@@ -838,11 +839,11 @@ public class TrackRecordingService extends Service implements LocationListener {
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
int retries = sharedPreferences.getInt( int retries = sharedPreferences.getInt(
getString(R.string.auto_resume_track_current_retry_key), 0); getString(R.string.auto_resume_track_current_retry_key), 0);
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"shouldResumeTrack: Attempting to auto-resume the track (" "shouldResumeTrack: Attempting to auto-resume the track ("
+ (retries + 1) + "/" + MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS + ")"); + (retries + 1) + "/" + MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS + ")");
if (retries >= 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 " "shouldResumeTrack: Not resuming because exceeded the maximum "
+ "number of auto-resume retries"); + "number of auto-resume retries");
return false; return false;
@@ -854,12 +855,12 @@ public class TrackRecordingService extends Service implements LocationListener {
// Check for special cases. // Check for special cases.
if (autoResumeTrackTimeout == 0) { if (autoResumeTrackTimeout == 0) {
// Never resume. // Never resume.
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"shouldResumeTrack: Auto-resume disabled (never resume)"); "shouldResumeTrack: Auto-resume disabled (never resume)");
return false; return false;
} else if (autoResumeTrackTimeout == -1) { } else if (autoResumeTrackTimeout == -1) {
// Always resume. // Always resume.
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"shouldResumeTrack: Auto-resume forced (always resume)"); "shouldResumeTrack: Auto-resume forced (always resume)");
return true; return true;
} }
@@ -867,7 +868,7 @@ public class TrackRecordingService extends Service implements LocationListener {
// Check if the last modified time is within the acceptable range. // Check if the last modified time is within the acceptable range.
long lastModified = long lastModified =
track.getStatistics() != null ? track.getStatistics().getStopTime() : 0; track.getStatistics() != null ? track.getStatistics().getStopTime() : 0;
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"shouldResumeTrack: lastModified = " + lastModified "shouldResumeTrack: lastModified = " + lastModified
+ ", autoResumeTrackTimeout: " + autoResumeTrackTimeout); + ", autoResumeTrackTimeout: " + autoResumeTrackTimeout);
return lastModified > 0 && System.currentTimeMillis() - lastModified <= return lastModified > 0 && System.currentTimeMillis() - lastModified <=
@@ -897,7 +898,8 @@ public class TrackRecordingService extends Service implements LocationListener {
} }
wpt.setTrackId(recordingTrackId); wpt.setTrackId(recordingTrackId);
wpt.setLength(length); wpt.setLength(length);
if (lastValidLocation == null) { if (lastLocation == null
|| statsBuilder == null || statsBuilder.getStatistics() == null) {
// A null location is ok, and expected on track start. // A null location is ok, and expected on track start.
// Make it an impossible location. // Make it an impossible location.
Location l = new Location(""); Location l = new Location("");
@@ -905,11 +907,9 @@ public class TrackRecordingService extends Service implements LocationListener {
l.setLongitude(180); l.setLongitude(180);
wpt.setLocation(l); wpt.setLocation(l);
} else { } else {
// A null location is ok, and expected on track start.
wpt.setLocation(lastLocation); wpt.setLocation(lastLocation);
if (lastLocation != null) { wpt.setDuration(lastLocation.getTime()
wpt.setDuration(lastLocation.getTime() - statsBuilder.getStatistics().getStartTime()); - statsBuilder.getStatistics().getStartTime());
}
} }
Uri uri = providerUtils.insertWaypoint(wpt); Uri uri = providerUtils.insertWaypoint(wpt);
return Long.parseLong(uri.getLastPathSegment()); return Long.parseLong(uri.getLastPathSegment());
@@ -1057,11 +1057,11 @@ public class TrackRecordingService extends Service implements LocationListener {
public byte[] getSensorData() { public byte[] getSensorData() {
checkService(); checkService();
if (service.sensorManager == null) { if (service.sensorManager == null) {
Log.d(MyTracksConstants.TAG, "No sensor manager for data."); Log.d(TAG, "No sensor manager for data.");
return null; return null;
} }
if (service.sensorManager.getSensorDataSet() == 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 null;
} }
return service.sensorManager.getSensorDataSet().toByteArray(); return service.sensorManager.getSensorDataSet().toByteArray();
@@ -1071,7 +1071,7 @@ public class TrackRecordingService extends Service implements LocationListener {
public int getSensorState() { public int getSensorState() {
checkService(); checkService();
if (service.sensorManager == null) { 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 Sensor.SensorState.NONE.getNumber();
} }
return service.sensorManager.getSensorState().getNumber(); return service.sensorManager.getSensorState().getNumber();
@@ -1079,7 +1079,7 @@ public class TrackRecordingService extends Service implements LocationListener {
} }
public long startNewTrack() { public long startNewTrack() {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.startNewTrack"); Log.d(TAG, "TrackRecordingService.startNewTrack");
if (recordingTrackId != -1 || isRecording) { if (recordingTrackId != -1 || isRecording) {
throw new IllegalStateException("A track is already in progress!"); throw new IllegalStateException("A track is already in progress!");
} }
@@ -1129,7 +1129,7 @@ public class TrackRecordingService extends Service implements LocationListener {
} }
private void endCurrentTrack() { private void endCurrentTrack() {
Log.d(MyTracksConstants.TAG, "TrackRecordingService.endCurrentTrack"); Log.d(TAG, "TrackRecordingService.endCurrentTrack");
if (recordingTrackId == -1 || !isRecording) { if (recordingTrackId == -1 || !isRecording) {
throw new IllegalStateException("No recording track in progress!"); throw new IllegalStateException("No recording track in progress!");
} }
@@ -15,17 +15,17 @@
*/ */
package com.google.android.apps.mytracks.services.sensors; package com.google.android.apps.mytracks.services.sensors;
import static com.google.android.apps.mytracks.MyTracksConstants.TAG; import static com.google.android.apps.mytracks.Constants.TAG;
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.MyTracksSettings;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.services.sensors.ant.AntChannelIdMessage; import com.google.android.apps.mytracks.services.sensors.ant.AntChannelIdMessage;
import com.google.android.apps.mytracks.services.sensors.ant.AntChannelResponseMessage; import com.google.android.apps.mytracks.services.sensors.ant.AntChannelResponseMessage;
import com.google.android.maps.mytracks.R; 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.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.util.Log; import android.util.Log;
@@ -15,14 +15,14 @@
*/ */
package com.google.android.apps.mytracks.services.sensors; 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.AntDefine;
import com.dsi.ant.AntMesg; import com.dsi.ant.AntMesg;
import com.dsi.ant.exception.AntInterfaceException; 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.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@@ -82,10 +82,10 @@ public class AntSRMSensorManager extends AntSensorManager {
@Override @Override
public void handleMessage(byte[] antMessage) { public void handleMessage(byte[] antMessage) {
// Parse channel number // Parse channel number
byte receivedChannel = (byte) (antMessage[AntMesg.MESG_DATA_OFFSET] byte recievedChannel = (byte) (antMessage[AntMesg.MESG_DATA_OFFSET]
& AntDefine.CHANNEL_NUMBER_MASK); & AntDefine.CHANNEL_NUMBER_MASK);
if (receivedChannel != channel) { if (recievedChannel != channel) {
Log.d(TAG, "Unexpected channel: " + receivedChannel); Log.d(Constants.TAG, "Unexpected channel: " + recievedChannel);
return; return;
} }
switch (antMessage[AntMesg.MESG_ID_OFFSET]) { switch (antMessage[AntMesg.MESG_ID_OFFSET]) {
@@ -99,17 +99,18 @@ public class AntSRMSensorManager extends AntSensorManager {
handleChannelId(antMessage); handleChannelId(antMessage);
break; break;
default: default:
Log.e(TAG, "Unexpected message id: " + antMessage[3]); Log.e(Constants.TAG,
"Unexpected message id: " + antMessage[3]);
} }
} }
private void handleBroadcastData(byte[] antMessage) { private void handleBroadcastData(byte[] antMessage) {
if (deviceId == WILDCARD) { if (deviceId == WILDCARD) {
try { try {
Log.d(TAG, "Requesting channel id id."); Log.d(Constants.TAG, "Requesting channel id id.");
getAntReceiver().ANTRequestMessage(channel, AntMesg.MESG_CHANNEL_ID_ID); getAntReceiver().ANTRequestMessage(channel, AntMesg.MESG_CHANNEL_ID_ID);
} catch (AntInterfaceException e) { } 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); setSensorState(Sensor.SensorState.CONNECTED);
@@ -121,14 +122,15 @@ public class AntSRMSensorManager extends AntSensorManager {
parseSensorData(antMessage); parseSensorData(antMessage);
break; break;
default: 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) { private void handleChannelId(byte[] antMessage) {
// Store the device id. // Store the device id.
deviceId = antMessage[3]; deviceId = antMessage[3];
Log.i(TAG, "Found device id: " + deviceId); Log.i(Constants.TAG, "Found device id: " + deviceId);
SharedPreferences prefs = context.getSharedPreferences( SharedPreferences prefs = context.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, Context.MODE_PRIVATE); MyTracksSettings.SETTINGS_NAME, Context.MODE_PRIVATE);
@@ -141,34 +143,38 @@ public class AntSRMSensorManager extends AntSensorManager {
if (antMessage[3] == AntMesg.MESG_EVENT_ID if (antMessage[3] == AntMesg.MESG_EVENT_ID
&& antMessage[4] == AntDefine.EVENT_RX_SEARCH_TIMEOUT) { && antMessage[4] == AntDefine.EVENT_RX_SEARCH_TIMEOUT) {
// Search timeout // Search timeout
Log.w(TAG, "Search timed out. Unassigning channel."); Log.w(Constants.TAG, "Search timed out. Unassigning channel.");
try { try {
getAntReceiver().ANTUnassignChannel(channel); getAntReceiver().ANTUnassignChannel(channel);
} catch (AntInterfaceException e) { } 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); setSensorState(Sensor.SensorState.DISCONNECTED);
} else if (antMessage[3] == AntMesg.MESG_UNASSIGN_CHANNEL_ID) { } else if (antMessage[3] == AntMesg.MESG_UNASSIGN_CHANNEL_ID) {
setSensorState(Sensor.SensorState.DISCONNECTED); 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) { private void parseSensorData(byte[] antMessage) {
if (antMessage.length != 11) { if (antMessage.length != 11) {
Log.e(TAG, "Unexpected ant message length: " + antMessage.length); Log.e(Constants.TAG,
"Unexpected ant message length: " + antMessage.length);
return; return;
} }
int newMessageId = antMessage[MESSAGE_ID_INDEX] & 0xFF; int newMessageId = antMessage[MESSAGE_ID_INDEX] & 0xFF;
if (lastMessageId == newMessageId) { if (lastMessageId == newMessageId) {
// Repeated message. // 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; return;
} }
if (newMessageId < lastMessageId) { if (newMessageId < lastMessageId) {
if (!(newMessageId < 20 && lastMessageId > 200)) { 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; return;
} // else assume the byte overflowed to 0. } // else assume the byte overflowed to 0.
} }
@@ -15,16 +15,16 @@
*/ */
package com.google.android.apps.mytracks.services.sensors; 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.AntDefine;
import com.dsi.ant.AntInterface; import com.dsi.ant.AntInterface;
import com.dsi.ant.AntInterfaceIntent; import com.dsi.ant.AntInterfaceIntent;
import com.dsi.ant.AntMesg; import com.dsi.ant.AntMesg;
import com.dsi.ant.exception.AntInterfaceException; 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.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@@ -84,7 +84,7 @@ public abstract class AntSensorManager extends SensorManager {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
String antAction = intent.getAction(); 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 @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
String antAction = intent.getAction(); 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)) { if (antAction.equals(AntInterfaceIntent.ANT_RX_MESSAGE_ACTION)) {
byte[] antMessage = intent.getByteArrayExtra(AntInterfaceIntent.ANT_MESSAGE); byte[] antMessage = intent.getByteArrayExtra(AntInterfaceIntent.ANT_MESSAGE);
if (DEBUGGING) { if (DEBUGGING) {
Log.d(TAG, "Received RX message " + messageToString(antMessage)); Log.d(Constants.TAG, "Received RX message " + messageToString(antMessage));
} }
handleMessage(antMessage); handleMessage(antMessage);
@@ -119,7 +119,7 @@ public abstract class AntSensorManager extends SensorManager {
@Override @Override
public void onServiceDisconnected() { 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 @Override
public void onDestroy() { public void onDestroy() {
Log.i(TAG, "destroying AntSensorManager"); Log.i(Constants.TAG, "destroying AntSensorManager");
context.unregisterReceiver(statusReceiver); context.unregisterReceiver(statusReceiver);
context.unregisterReceiver(dataReceiver); context.unregisterReceiver(dataReceiver);
try { try {
antReceiver.releaseInterface(); antReceiver.releaseInterface();
} catch (AntInterfaceException e) { } catch (AntInterfaceException e) {
Log.e(TAG, "failed to release ANT interface", e); Log.e(Constants.TAG, "failed to release ANT interface", e);
} }
antReceiver.destroy(); antReceiver.destroy();
@@ -177,7 +177,7 @@ public abstract class AntSensorManager extends SensorManager {
antReceiver = AntInterface.getInstance(context, antServiceListener); antReceiver = AntInterface.getInstance(context, antServiceListener);
if (antReceiver == null) { if (antReceiver == null) {
Log.e(TAG, "Failed to get ANT Receiver"); Log.e(Constants.TAG, "Failed to get ANT Receiver");
return; return;
} }
@@ -190,11 +190,11 @@ public abstract class AntSensorManager extends SensorManager {
* to initiate any ANT commands. * to initiate any ANT commands.
*/ */
private synchronized void serviceConnected() { private synchronized void serviceConnected() {
Log.d(TAG, "ANT service connected"); Log.d(Constants.TAG, "ANT service connected");
try { try {
if (!antReceiver.claimInterface()) { if (!antReceiver.claimInterface()) {
Log.e(TAG, "failed to claim ANT interface"); Log.e(Constants.TAG, "failed to claim ANT interface");
return; return;
} }
@@ -202,14 +202,14 @@ public abstract class AntSensorManager extends SensorManager {
// Make sure not to call AntInterface.enable() again, if it has been // Make sure not to call AntInterface.enable() again, if it has been
// already called before // already called before
if (antInterrupted == false) { if (antInterrupted == false) {
Log.i(TAG, "Powering on Radio"); Log.i(Constants.TAG, "Powering on Radio");
antReceiver.enable(); antReceiver.enable();
} }
} else { } else {
Log.i(TAG, "Radio already enabled"); Log.i(Constants.TAG, "Radio already enabled");
} }
} catch (AntInterfaceException e) { } catch (AntInterfaceException e) {
Log.e(TAG, "failed to enable ANT", e); Log.e(Constants.TAG, "failed to enable ANT", e);
} }
try { try {
@@ -220,7 +220,7 @@ public abstract class AntSensorManager extends SensorManager {
// that message. // that message.
antReceiver.ANTResetSystem(); antReceiver.ANTResetSystem();
} catch (AntInterfaceException e) { } 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) { protected void handleMessage(byte[] antMessage) {
int len = antMessage[0]; int len = antMessage[0];
if (len != antMessage.length - 2 || antMessage.length <= 2) { if (len != antMessage.length - 2 || antMessage.length <= 2) {
Log.e(TAG, "Invalid message: " + messageToString(antMessage)); Log.e(Constants.TAG, "Invalid message: " + messageToString(antMessage));
return; return;
} }
@@ -253,7 +253,8 @@ public abstract class AntSensorManager extends SensorManager {
*/ */
protected boolean handleMessage(byte messageId, byte[] messageData) { protected boolean handleMessage(byte messageId, byte[] messageData) {
if (messageId == AntMesg.MESG_STARTUP_MESG_ID) { 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())); new AntStartupMessage(messageData).getMessage()));
setupAntSensorChannels(); setupAntSensorChannels();
return true; return true;
@@ -304,13 +305,13 @@ public abstract class AntSensorManager extends SensorManager {
return true; return true;
} catch (AntInterfaceException e) { } catch (AntInterfaceException e) {
Log.e(TAG, "failed to setup ANT channel", e); Log.e(Constants.TAG, "failed to setup ANT channel", e);
return false; return false;
} }
} }
private void registerForAntIntents() { private void registerForAntIntents() {
Log.i(TAG, "Registering for ant intents."); Log.i(Constants.TAG, "Registering for ant intents.");
// Register for ANT intent broadcasts. // Register for ANT intent broadcasts.
IntentFilter statusIntentFilter = new IntentFilter(); IntentFilter statusIntentFilter = new IntentFilter();
statusIntentFilter.addAction(AntInterfaceIntent.ANT_ENABLED_ACTION); statusIntentFilter.addAction(AntInterfaceIntent.ANT_ENABLED_ACTION);
@@ -16,8 +16,7 @@
package com.google.android.apps.mytracks.services.sensors; 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;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
@@ -86,7 +85,7 @@ public class BluetoothConnectionManager {
*/ */
private synchronized void setState(Sensor.SensorState state) { private synchronized void setState(Sensor.SensorState state) {
// TODO pretty print this. // TODO pretty print this.
Log.d(TAG, "setState(" + state + ")"); Log.d(Constants.TAG, "setState(" + state + ")");
this.state = state; this.state = state;
// Give the new state to the Handler so the UI Activity can update // 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() * in listening (server) mode. Called by the Activity onResume()
*/ */
public synchronized void start() { public synchronized void start() {
Log.d(TAG, "BluetoothConnectionManager.start()"); Log.d(Constants.TAG, "BluetoothConnectionManager.start()");
// Cancel any thread attempting to make a connection // Cancel any thread attempting to make a connection
if (connectThread != null) { if (connectThread != null) {
@@ -128,7 +127,7 @@ public class BluetoothConnectionManager {
* @param device The BluetoothDevice to connect * @param device The BluetoothDevice to connect
*/ */
public synchronized void connect(BluetoothDevice device) { 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 // Cancel any thread attempting to make a connection
if (state == Sensor.SensorState.CONNECTING) { if (state == Sensor.SensorState.CONNECTING) {
@@ -158,7 +157,7 @@ public class BluetoothConnectionManager {
*/ */
public synchronized void connected(BluetoothSocket socket, public synchronized void connected(BluetoothSocket socket,
BluetoothDevice device) { BluetoothDevice device) {
Log.d(TAG, "connected"); Log.d(Constants.TAG, "connected");
// Cancel the thread that completed the connection // Cancel the thread that completed the connection
if (connectThread != null) { if (connectThread != null) {
@@ -190,7 +189,7 @@ public class BluetoothConnectionManager {
* Stop all threads * Stop all threads
*/ */
public synchronized void stop() { public synchronized void stop() {
Log.d(TAG, "stop()"); Log.d(Constants.TAG, "stop()");
if (connectThread != null) { if (connectThread != null) {
connectThread.cancel(); connectThread.cancel();
connectThread = null; connectThread = null;
@@ -227,7 +226,7 @@ public class BluetoothConnectionManager {
*/ */
private void connectionFailed() { private void connectionFailed() {
setState(Sensor.SensorState.DISCONNECTED); 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() { private void connectionLost() {
setState(Sensor.SensorState.DISCONNECTED); 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 { try {
tmp = getSocket(); tmp = getSocket();
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "create() failed", e); Log.e(Constants.TAG, "create() failed", e);
} }
socket = tmp; socket = tmp;
} }
@@ -269,22 +268,22 @@ public class BluetoothConnectionManager {
insecure.setAccessible(true); insecure.setAccessible(true);
return (BluetoothSocket) insecure.invoke(device, 1); return (BluetoothSocket) insecure.invoke(device, 1);
} catch (SecurityException e) { } 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) { } 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) { } 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) { } 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) { } 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); return device.createRfcommSocketToServiceRecord(SPP_UUID);
} }
@Override @Override
public void run() { public void run() {
Log.d(TAG, "BEGIN mConnectThread"); Log.d(Constants.TAG, "BEGIN mConnectThread");
// Always cancel discovery because it will slow down a connection // Always cancel discovery because it will slow down a connection
adapter.cancelDiscovery(); adapter.cancelDiscovery();
@@ -300,7 +299,8 @@ public class BluetoothConnectionManager {
try { try {
socket.close(); socket.close();
} catch (IOException e2) { } 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 // Start the service over to restart listening mode
BluetoothConnectionManager.this.start(); BluetoothConnectionManager.this.start();
@@ -320,7 +320,7 @@ public class BluetoothConnectionManager {
try { try {
socket.close(); socket.close();
} catch (IOException e) { } 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; private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) { public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "create ConnectedThread"); Log.d(Constants.TAG, "create ConnectedThread");
btSocket = socket; btSocket = socket;
InputStream tmpIn = null; InputStream tmpIn = null;
OutputStream tmpOut = null; OutputStream tmpOut = null;
@@ -345,7 +345,7 @@ public class BluetoothConnectionManager {
tmpIn = socket.getInputStream(); tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream(); tmpOut = socket.getOutputStream();
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "temp sockets not created", e); Log.e(Constants.TAG, "temp sockets not created", e);
} }
mmInStream = tmpIn; mmInStream = tmpIn;
@@ -354,7 +354,7 @@ public class BluetoothConnectionManager {
@Override @Override
public void run() { public void run() {
Log.i(TAG, "BEGIN mConnectedThread"); Log.i(Constants.TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[parser.getFrameSize()]; byte[] buffer = new byte[parser.getFrameSize()];
int bytes; int bytes;
int offset = 0; int offset = 0;
@@ -383,10 +383,11 @@ public class BluetoothConnectionManager {
// re-align // re-align
offset = parser.getFrameSize() - index; offset = parser.getFrameSize() - index;
System.arraycopy(buffer, index, buffer, 0, offset); 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; continue;
} }
Log.w(TAG, "Could not find valid data, dropping data"); Log.w(Constants.TAG, "Could not find valid data, dropping data");
offset = 0; offset = 0;
continue; continue;
} }
@@ -397,7 +398,7 @@ public class BluetoothConnectionManager {
handler.obtainMessage(MESSAGE_READ, bytes, -1, buffer) handler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget(); .sendToTarget();
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "disconnected", e); Log.e(Constants.TAG, "disconnected", e);
connectionLost(); connectionLost();
break; break;
} }
@@ -416,7 +417,7 @@ public class BluetoothConnectionManager {
// Share the sent message back to the UI Activity // Share the sent message back to the UI Activity
handler.obtainMessage(MESSAGE_WRITE, -1, -1, buffer).sendToTarget(); handler.obtainMessage(MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
} catch (IOException e) { } 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 { try {
btSocket.close(); btSocket.close();
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e); Log.e(Constants.TAG, "close() of connect socket failed", e);
} }
} }
} }
@@ -15,8 +15,7 @@
*/ */
package com.google.android.apps.mytracks.services.sensors; 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.MyTracksSettings;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -67,7 +66,7 @@ public class BluetoothSensorManager extends SensorManager {
} }
private void setupSensor() { private void setupSensor() {
Log.d(TAG, "setupSensor()"); Log.d(Constants.TAG, "setupSensor()");
// Initialize the BluetoothSensorAdapter to perform bluetooth connections. // Initialize the BluetoothSensorAdapter to perform bluetooth connections.
connectionManager = new BluetoothConnectionManager(messageHandler, parser); connectionManager = new BluetoothConnectionManager(messageHandler, parser);
@@ -79,7 +78,7 @@ public class BluetoothSensorManager extends SensorManager {
public void setupChannel() { public void setupChannel() {
if (!isEnabled() || connectionManager == null) { if (!isEnabled() || connectionManager == null) {
Log.w(TAG, "Disabled manager onStartTrack"); Log.w(Constants.TAG, "Disabled manager onStartTrack");
return; return;
} }
SharedPreferences prefs = SharedPreferences prefs =
@@ -89,7 +88,7 @@ public class BluetoothSensorManager extends SensorManager {
if (address == null) { if (address == null) {
return; return;
} }
Log.w(TAG, "Connecting to bluetooth sensor: " + address); Log.w(Constants.TAG, "Connecting to bluetooth sensor: " + address);
// Get the BluetoothDevice object // Get the BluetoothDevice object
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device // Attempt to connect to the device
@@ -103,7 +102,7 @@ public class BluetoothSensorManager extends SensorManager {
// already // already
if (connectionManager.getState() == Sensor.SensorState.NONE) { if (connectionManager.getState() == Sensor.SensorState.NONE) {
// Start the Bluetooth sensor services // Start the Bluetooth sensor services
Log.w(TAG, "Disabled manager onStartTrack"); Log.w(Constants.TAG, "Disabled manager onStartTrack");
connectionManager.start(); connectionManager.start();
} }
} }
@@ -133,7 +132,7 @@ public class BluetoothSensorManager extends SensorManager {
switch (msg.what) { switch (msg.what) {
case BluetoothConnectionManager.MESSAGE_STATE_CHANGE: case BluetoothConnectionManager.MESSAGE_STATE_CHANGE:
// TODO should we update the SensorManager state var? // 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; break;
case BluetoothConnectionManager.MESSAGE_WRITE: case BluetoothConnectionManager.MESSAGE_WRITE:
break; break;
@@ -142,14 +141,15 @@ public class BluetoothSensorManager extends SensorManager {
try { try {
readBuf = (byte[]) msg.obj; readBuf = (byte[]) msg.obj;
sensorDataSet = parser.parseBuffer(readBuf); sensorDataSet = parser.parseBuffer(readBuf);
Log.d(TAG, "MESSAGE_READ: " + sensorDataSet.toString()); Log.d(Constants.TAG, "MESSAGE_READ: " + sensorDataSet.toString());
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
sensorDataSet = null; 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); iae);
} catch (RuntimeException re) { } catch (RuntimeException re) {
sensorDataSet = null; sensorDataSet = null;
Log.i(TAG, "Unexpected exception on read.", re); Log.i(Constants.TAG, "Unexpected exception on read.", re);
} }
break; break;
case BluetoothConnectionManager.MESSAGE_DEVICE_NAME: case BluetoothConnectionManager.MESSAGE_DEVICE_NAME:
@@ -15,14 +15,13 @@
*/ */
package com.google.android.apps.mytracks.services.sensors; package com.google.android.apps.mytracks.services.sensors;
import static com.google.android.apps.mytracks.MyTracksConstants.TAG; import java.util.Timer;
import java.util.TimerTask;
import com.google.android.apps.mytracks.content.Sensor;
import android.util.Log; import android.util.Log;
import java.util.Timer; import com.google.android.apps.mytracks.Constants;
import java.util.TimerTask; import com.google.android.apps.mytracks.content.Sensor;
/** /**
* Manage the connection to a sensor. * Manage the connection to a sensor.
@@ -51,17 +50,19 @@ public abstract class SensorManager {
private TimerTask checkSensorManager = new TimerTask() { private TimerTask checkSensorManager = new TimerTask() {
@Override @Override
public void run() { public void run() {
Log.i(TAG, "SensorManager state: " + getSensorState()); Log.i(Constants.TAG,
"SensorManager state: " + getSensorState());
switch (getSensorState()) { switch (getSensorState()) {
case CONNECTING: case CONNECTING:
long age = System.currentTimeMillis() - getSensorStateTimestamp(); long age = System.currentTimeMillis() - getSensorStateTimestamp();
if (age > 2 * RETRY_PERIOD) { if (age > 2 * RETRY_PERIOD) {
Log.i(TAG, "Retrying connecting SensorManager."); Log.i(Constants.TAG, "Retrying connecting SensorManager.");
setupChannel(); setupChannel();
} }
break; break;
case DISCONNECTED: case DISCONNECTED:
Log.i(TAG, "Re-registering disconnected SensorManager."); Log.i(Constants.TAG,
"Re-registering disconnected SensoManager.");
setupChannel(); setupChannel();
break; break;
} }
@@ -15,8 +15,7 @@
*/ */
package com.google.android.apps.mytracks.services.sensors; 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.MyTracksSettings;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -30,7 +29,9 @@ import android.util.Log;
* @author Sandor Dornbush * @author Sandor Dornbush
*/ */
public class SensorManagerFactory { public class SensorManagerFactory {
private SensorManagerFactory() {}
private SensorManagerFactory() {
}
/** /**
* Get a new sensor manager. * Get a new sensor manager.
@@ -45,7 +46,7 @@ public class SensorManagerFactory {
} }
String sensor = prefs.getString(context.getString(R.string.sensor_type_key), 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) { if (sensor == null) {
return null; return null;
@@ -56,7 +57,7 @@ public class SensorManagerFactory {
} else if (sensor.equals(context.getString(R.string.zephyr_sensor_type))) { } else if (sensor.equals(context.getString(R.string.zephyr_sensor_type))) {
return new ZephyrSensorManager(context); return new ZephyrSensorManager(context);
} else { } else {
Log.w(TAG, "Unable to find sensor type: " + sensor); Log.w(Constants.TAG, "Unable to find sensor type: " + sensor);
return null; return null;
} }
} }
@@ -15,12 +15,11 @@
*/ */
package com.google.android.apps.mytracks.services.sensors; 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 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. * 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++) { for (int i = 0; i < buffer.length; i++) {
sb.append(String.format("%02X", buffer[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. // The provided units are 1/16 strides per minute.
// TODO: Fix the cadence calculation. // TODO: Fix the cadence calculation.
// int cadence = SensorUtils.unsignedShortToInt(buffer, 56); // int cadence = SensorUtils.unsignedShortToInt(buffer, 56);
@@ -16,7 +16,9 @@
package com.google.android.apps.mytracks.stats; 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 com.google.android.apps.mytracks.MyTracksSettings;
import android.location.Location; import android.location.Location;
@@ -65,25 +67,25 @@ public class TripStatisticsBuilder {
* A buffer of the last speed readings in meters/second. * A buffer of the last speed readings in meters/second.
*/ */
private final DoubleBuffer speedBuffer = 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. * A buffer of the recent elevation readings in meters.
*/ */
private final DoubleBuffer elevationBuffer = 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. * A buffer of the distance between recent gps readings in meters.
*/ */
private final DoubleBuffer distanceBuffer = private final DoubleBuffer distanceBuffer =
new DoubleBuffer(MyTracksConstants.DISTANCE_SMOOTHING_FACTOR); new DoubleBuffer(Constants.DISTANCE_SMOOTHING_FACTOR);
/** /**
* A buffer of the recent grade calculations. * A buffer of the recent grade calculations.
*/ */
private final DoubleBuffer gradeBuffer = private final DoubleBuffer gradeBuffer =
new DoubleBuffer(MyTracksConstants.GRADE_SMOOTHING_FACTOR); new DoubleBuffer(Constants.GRADE_SMOOTHING_FACTOR);
/** /**
* The total number of locations in this trip. * The total number of locations in this trip.
@@ -126,7 +128,7 @@ public class TripStatisticsBuilder {
*/ */
public boolean addLocation(Location currentLocation, long systemTime) { public boolean addLocation(Location currentLocation, long systemTime) {
if (paused) { if (paused) {
Log.w(MyTracksConstants.TAG, Log.w(TAG,
"Tried to account for location while track is paused"); "Tried to account for location while track is paused");
return false; return false;
} }
@@ -151,7 +153,7 @@ public class TripStatisticsBuilder {
// Don't do anything if we didn't move since last fix: // Don't do anything if we didn't move since last fix:
double distance = lastLocation.distanceTo(currentLocation); double distance = lastLocation.distanceTo(currentLocation);
if (distance < minRecordingDistance && if (distance < minRecordingDistance &&
currentSpeed < MyTracksConstants.MAX_NO_MOVEMENT_SPEED) { currentSpeed < Constants.MAX_NO_MOVEMENT_SPEED) {
lastLocation = currentLocation; lastLocation = currentLocation;
return false; return false;
} }
@@ -208,7 +210,7 @@ public class TripStatisticsBuilder {
// We are now sure the user is moving. // We are now sure the user is moving.
long timeDifference = updateTime - lastLocationTime; long timeDifference = updateTime - lastLocationTime;
if (timeDifference < 0) { if (timeDifference < 0) {
Log.e(MyTracksConstants.TAG, Log.e(TAG,
"Found negative time change: " + timeDifference); "Found negative time change: " + timeDifference);
} }
data.addMovingTime(timeDifference); data.addMovingTime(timeDifference);
@@ -224,7 +226,7 @@ public class TripStatisticsBuilder {
data.setMaxSpeed(movingSpeed); data.setMaxSpeed(movingSpeed);
} }
} else { } else {
Log.d(MyTracksConstants.TAG, Log.d(TAG,
"TripStatistics ignoring big change: Raw Speed: " + speed "TripStatistics ignoring big change: Raw Speed: " + speed
+ " old: " + lastLocationSpeed + " [" + toString() + "]"); + " old: " + lastLocationSpeed + " [" + toString() + "]");
} }
@@ -263,7 +265,7 @@ public class TripStatisticsBuilder {
// likely. Ignore any speeds that imply accelaration greater than 2g's // likely. Ignore any speeds that imply accelaration greater than 2g's
// Really who can accelerate faster? // Really who can accelerate faster?
double speedDifference = Math.abs(lastLocationSpeed - speed); double speedDifference = Math.abs(lastLocationSpeed - speed);
if (speedDifference > MyTracksConstants.MAX_ACCELERATION * timeDifference) { if (speedDifference > Constants.MAX_ACCELERATION * timeDifference) {
return false; return false;
} }
@@ -275,7 +277,7 @@ public class TripStatisticsBuilder {
double smoothedDiff = Math.abs(smoothedSpeed - speed); double smoothedDiff = Math.abs(smoothedSpeed - speed);
return !speedBuffer.isFull() || return !speedBuffer.isFull() ||
(speed < smoothedSpeed * 10 (speed < smoothedSpeed * 10
&& smoothedDiff < MyTracksConstants.MAX_ACCELERATION * timeDifference); && smoothedDiff < Constants.MAX_ACCELERATION * timeDifference);
} }
/** /**
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.util; 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.os.Build;
import android.util.Log; import android.util.Log;
@@ -72,7 +72,7 @@ public class ApiFeatures {
apiPlatformAdapter = new CupcakePlatformAdapter(); apiPlatformAdapter = new CupcakePlatformAdapter();
} }
Log.i(MyTracksConstants.TAG, "Using platform adapter " + apiPlatformAdapter.getClass()); Log.i(Constants.TAG, "Using platform adapter " + apiPlatformAdapter.getClass());
} }
public ApiPlatformAdapter getApiPlatformAdapter() { public ApiPlatformAdapter getApiPlatformAdapter() {
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.util; 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.BluetoothAdapter;
import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothClass;
@@ -158,14 +158,14 @@ public abstract class BluetoothDeviceUtils {
public static BluetoothDeviceUtils getInstance() { public static BluetoothDeviceUtils getInstance() {
if (instance == null) { if (instance == null) {
if (!isBluetoothMethodSupported()) { if (!isBluetoothMethodSupported()) {
Log.d(MyTracksConstants.TAG, "Using dummy bluetooth utils"); Log.d(Constants.TAG, "Using dummy bluetooth utils");
instance = new DummyImpl(); instance = new DummyImpl();
} else { } else {
Log.d(MyTracksConstants.TAG, "Using real bluetooth utils"); Log.d(Constants.TAG, "Using real bluetooth utils");
try { try {
instance = new RealImpl(); instance = new RealImpl();
} catch (IllegalStateException ise) { } 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(); instance = new DummyImpl();
} }
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.util; 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.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.Service; import android.app.Service;
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.util; 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; import android.os.Environment;
@@ -49,7 +49,7 @@ public class FileUtils {
StringBuilder dirNameBuilder = new StringBuilder(); StringBuilder dirNameBuilder = new StringBuilder();
dirNameBuilder.append(Environment.getExternalStorageDirectory()); dirNameBuilder.append(Environment.getExternalStorageDirectory());
dirNameBuilder.append(File.separatorChar); dirNameBuilder.append(File.separatorChar);
dirNameBuilder.append(MyTracksConstants.SDCARD_TOP_DIR); dirNameBuilder.append(Constants.SDCARD_TOP_DIR);
for (String component : components) { for (String component : components) {
dirNameBuilder.append(File.separatorChar); dirNameBuilder.append(File.separatorChar);
dirNameBuilder.append(component); dirNameBuilder.append(component);
@@ -1,6 +1,6 @@
package com.google.android.apps.mytracks.util; 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.content.SharedPreferences.Editor;
import android.os.StrictMode; import android.os.StrictMode;
@@ -21,7 +21,7 @@ public class GingerbreadPlatformAdapter extends EclairPlatformAdapter {
@Override @Override
public void enableStrictMode() { public void enableStrictMode() {
Log.d(MyTracksConstants.TAG, "Enabling strict mode"); Log.d(Constants.TAG, "Enabling strict mode");
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskWrites() .detectDiskWrites()
.detectNetwork() .detectNetwork()
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.util; 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.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.apps.mytracks.stats.TripStatistics;
@@ -146,7 +146,7 @@ public class MyTracksUtils {
} }
idx++; idx++;
} }
Log.d(MyTracksConstants.TAG, "Decimating " + n + " points to " + i Log.d(Constants.TAG, "Decimating " + n + " points to " + i
+ " w/ tolerance = " + tolerance); + " w/ tolerance = " + tolerance);
} }
@@ -268,7 +268,7 @@ public class MyTracksUtils {
} }
} }
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {
Log.e(MyTracksConstants.TAG, "Unable to get signatures", e); Log.e(Constants.TAG, "Unable to get signatures", e);
} }
return false; return false;
} }
@@ -285,7 +285,7 @@ public class MyTracksUtils {
PackageManager.GET_META_DATA); PackageManager.GET_META_DATA);
return pi.versionName; return pi.versionName;
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {
Log.w(MyTracksConstants.TAG, "Failed to get version info.", e); Log.w(Constants.TAG, "Failed to get version info.", e);
return ""; return "";
} }
} }
@@ -295,19 +295,19 @@ public class MyTracksUtils {
* and gives up trying in case the wake lock cannot be acquired. * and gives up trying in case the wake lock cannot be acquired.
*/ */
public static WakeLock acquireWakeLock(Activity activity, WakeLock wakeLock) { 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 { try {
PowerManager pm = (PowerManager) activity PowerManager pm = (PowerManager) activity
.getSystemService(Context.POWER_SERVICE); .getSystemService(Context.POWER_SERVICE);
if (pm == null) { if (pm == null) {
Log.e(MyTracksConstants.TAG, "MyTracksUtils: Power manager not found!"); Log.e(Constants.TAG, "MyTracksUtils: Power manager not found!");
return wakeLock; return wakeLock;
} }
if (wakeLock == null) { if (wakeLock == null) {
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
MyTracksConstants.TAG); Constants.TAG);
if (wakeLock == null) { if (wakeLock == null) {
Log.e(MyTracksConstants.TAG, Log.e(Constants.TAG,
"MyTracksUtils: Could not create wake lock (null)."); "MyTracksUtils: Could not create wake lock (null).");
} }
return wakeLock; return wakeLock;
@@ -315,12 +315,12 @@ public class MyTracksUtils {
if (!wakeLock.isHeld()) { if (!wakeLock.isHeld()) {
wakeLock.acquire(); wakeLock.acquire();
if (!wakeLock.isHeld()) { if (!wakeLock.isHeld()) {
Log.e(MyTracksConstants.TAG, Log.e(Constants.TAG,
"MyTracksUtils: Could not acquire wake lock."); "MyTracksUtils: Could not acquire wake lock.");
} }
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.e(MyTracksConstants.TAG, Log.e(Constants.TAG,
"MyTracksUtils: Caught unexpected exception: " + e.getMessage(), e); "MyTracksUtils: Caught unexpected exception: " + e.getMessage(), e);
} }
return wakeLock; return wakeLock;
@@ -165,7 +165,7 @@ public class MyTracksTest extends ActivityInstrumentationTestCase2<MyTracks>{
// Watch for MyTracksDetails activity. // Watch for MyTracksDetails activity.
ActivityMonitor monitor = getInstrumentation().addMonitor( 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 // Now, stop the track and make sure that it is still selected, but
// no longer recording. // no longer recording.
@@ -173,7 +173,7 @@ public class MyTracksTest extends ActivityInstrumentationTestCase2<MyTracks>{
// Check if we got back MyTracksDetails activity. // Check if we got back MyTracksDetails activity.
Activity activity = getInstrumentation().waitForMonitor(monitor); 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 // TODO: Update track name and other properties and test if they were
// properly saved. // properly saved.
@@ -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.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor; 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.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import java.util.Date;
import java.util.List;
/** /**
* Tests for the GPX track exporter. * Tests for the GPX track exporter.
* *
* @author Sandor Dornbush * @author Sandor Dornbush
*/ */
public class TcxTrackWriterTest extends TrackFormatWriterTest { 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 { public void testXmlOutput() throws Exception {
TrackFormatWriter writer = new TcxTrackWriter(); TrackFormatWriter writer = new TcxTrackWriter(getContext());
String result = writeTrack(writer); String result = writeTrack(writer);
Document doc = parseXmlDocument(result); Document doc = parseXmlDocument(result);
@@ -58,8 +69,8 @@ public class TcxTrackWriterTest extends TrackFormatWriterTest {
getChildTextValue(posTag, "LatitudeDegrees")); getChildTextValue(posTag, "LatitudeDegrees"));
assertEquals(Double.toString(loc.getLongitude()), assertEquals(Double.toString(loc.getLongitude()),
getChildTextValue(posTag, "LongitudeDegrees")); getChildTextValue(posTag, "LongitudeDegrees"));
assertEquals(
TcxTrackWriter.TIMESTAMP_FORMAT.format(new Date(loc.getTime())), assertEquals(timestampFormatter.format(loc.getTime()),
getChildTextValue(tag, "Time")); getChildTextValue(tag, "Time"));
assertEquals(Double.toString(loc.getAltitude()), assertEquals(Double.toString(loc.getAltitude()),
getChildTextValue(tag, "AltitudeMeters")); getChildTextValue(tag, "AltitudeMeters"));
@@ -82,7 +82,6 @@ public class PreferenceBackupHelperTest extends TestCase {
return put(key, value); return put(key, value);
} }
@Override
public Editor putStringSet(String key, Set<String> value) { public Editor putStringSet(String key, Set<String> value) {
return put(key, value); return put(key, value);
} }
@@ -143,7 +142,6 @@ public class PreferenceBackupHelperTest extends TestCase {
return get(key, defValue); return get(key, defValue);
} }
@Override
public Set<String> getStringSet(String key, Set<String> defValue) { public Set<String> getStringSet(String key, Set<String> defValue) {
return get(key, defValue); return get(key, defValue);
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.services; 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.MyTracksSettings;
import com.google.android.apps.mytracks.content.MyTracksProvider; import com.google.android.apps.mytracks.content.MyTracksProvider;
@@ -2,7 +2,7 @@
package com.google.android.apps.mytracks.stats; 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; import android.location.Location;
@@ -56,18 +56,18 @@ public class TripStatisticsBuilderTest extends TestCase {
assertEquals(10000 * i, stats.getTotalTime()); assertEquals(10000 * i, stats.getTotalTime());
assertEquals(10000 * i, stats.getMovingTime()); assertEquals(10000 * i, stats.getMovingTime());
assertEquals(i, builder.getSmoothedElevation(), assertEquals(i, builder.getSmoothedElevation(),
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR / 2); Constants.ELEVATION_SMOOTHING_FACTOR / 2);
assertEquals(0.0, stats.getMinElevation()); assertEquals(0.0, stats.getMinElevation());
assertEquals(i, stats.getMaxElevation(), assertEquals(i, stats.getMaxElevation(),
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR / 2); Constants.ELEVATION_SMOOTHING_FACTOR / 2);
assertEquals(i, stats.getTotalElevationGain(), 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); assertEquals(11.1f, stats.getMaxSpeed(), 0.1);
} }
if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR) if ((i > Constants.GRADE_SMOOTHING_FACTOR)
&& (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) { && (i > Constants.ELEVATION_SMOOTHING_FACTOR)) {
assertEquals(0.009, stats.getMinGrade(), 0.0001); assertEquals(0.009, stats.getMinGrade(), 0.0001);
assertEquals(0.009, stats.getMaxGrade(), 0.0001); assertEquals(0.009, stats.getMaxGrade(), 0.0001);
} }
@@ -97,9 +97,9 @@ public class TripStatisticsBuilderTest extends TestCase {
public void testElevationGain() throws Exception { public void testElevationGain() throws Exception {
for (double i = 0; i < 1000; i++) { for (double i = 0; i < 1000; i++) {
double expectedGain; double expectedGain;
if (i < (MyTracksConstants.ELEVATION_SMOOTHING_FACTOR - 1)) { if (i < (Constants.ELEVATION_SMOOTHING_FACTOR - 1)) {
expectedGain = 0; expectedGain = 0;
} else if (i < MyTracksConstants.ELEVATION_SMOOTHING_FACTOR) { } else if (i < Constants.ELEVATION_SMOOTHING_FACTOR) {
expectedGain = 0.5; expectedGain = 0.5;
} else { } else {
expectedGain = 1.0; expectedGain = 1.0;
@@ -110,9 +110,9 @@ public class TripStatisticsBuilderTest extends TestCase {
TripStatistics data = builder.getStatistics(); TripStatistics data = builder.getStatistics();
assertEquals(0.0, data.getMinElevation(), 0.0); assertEquals(0.0, data.getMinElevation(), 0.0);
assertEquals(i, data.getMaxElevation(), assertEquals(i, data.getMaxElevation(),
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); Constants.ELEVATION_SMOOTHING_FACTOR);
assertEquals(i, data.getTotalElevationGain(), assertEquals(i, data.getTotalElevationGain(),
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR); Constants.ELEVATION_SMOOTHING_FACTOR);
} }
} }
@@ -122,8 +122,8 @@ public class TripStatisticsBuilderTest extends TestCase {
// buffer. // buffer.
builder.updateElevation(i); builder.updateElevation(i);
builder.updateGrade(100, 100); builder.updateGrade(100, 100);
if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR) if ((i > Constants.GRADE_SMOOTHING_FACTOR)
&& (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) { && (i > Constants.ELEVATION_SMOOTHING_FACTOR)) {
assertEquals(1.0, builder.getStatistics().getMaxGrade()); assertEquals(1.0, builder.getStatistics().getMaxGrade());
assertEquals(1.0, builder.getStatistics().getMinGrade()); assertEquals(1.0, builder.getStatistics().getMinGrade());
} }
@@ -133,8 +133,8 @@ public class TripStatisticsBuilderTest extends TestCase {
// buffer. // buffer.
builder.updateElevation(i); builder.updateElevation(i);
builder.updateGrade(100, -100); builder.updateGrade(100, -100);
if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR) if ((i > Constants.GRADE_SMOOTHING_FACTOR)
&& (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) { && (i > Constants.ELEVATION_SMOOTHING_FACTOR)) {
assertEquals(1.0, builder.getStatistics().getMaxGrade()); assertEquals(1.0, builder.getStatistics().getMaxGrade());
assertEquals(-1.0, builder.getStatistics().getMinGrade()); assertEquals(-1.0, builder.getStatistics().getMinGrade());
} }
@@ -176,7 +176,7 @@ public class TripStatisticsBuilderTest extends TestCase {
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
builder.updateSpeed(i + 1000, 4.0, i, 4.0); builder.updateSpeed(i + 1000, 4.0, i, 4.0);
assertEquals((i + 1) * 1000, builder.getStatistics().getMovingTime()); 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()); assertEquals(4.0, builder.getStatistics().getMaxSpeed());
} }
} }
@@ -15,7 +15,7 @@
*/ */
package com.google.android.apps.mytracks.util; 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; import android.os.Environment;
@@ -53,7 +53,7 @@ public class FileUtilsTest extends TestCase {
public void testBuildExternalDirectoryPath() { public void testBuildExternalDirectoryPath() {
String expectedName = Environment.getExternalStorageDirectory() String expectedName = Environment.getExternalStorageDirectory()
+ File.separator + File.separator
+ MyTracksConstants.SDCARD_TOP_DIR + Constants.SDCARD_TOP_DIR
+ File.separator + File.separator
+ "a" + "a"
+ File.separator + File.separator
+56
View File
@@ -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