Compare commits

..

9 Commits

Author SHA1 Message Date
Rodrigo Damazio 38de0e352f Releasing 1.1.5 2011-05-25 16:19:54 -03:00
Rodrigo Damazio 053fb403c5 Merging 2011-05-24 14:19:12 -03:00
Rodrigo Damazio 1d70d4bca0 Merging 2011-05-24 14:18:57 -03:00
Rodrigo Damazio bba04ba1bd If the only listener is a new one (and since for optimization we keep its state as the global state), we want to reset the global state before loading points onto it. 2011-05-24 13:53:26 -03:00
Rodrigo Damazio 1588c25fba Merging to head 2011-05-20 14:42:10 -03:00
Rodrigo Damazio da928fb549 Making data hub tests run considerably faster. 2011-05-19 21:42:40 -03:00
Rodrigo Damazio f657c2f1d1 Adding tests and making minor reorg changes. 2011-05-19 20:59:40 -03:00
Rodrigo Damazio d00c92ef99 Fixing incremental loading when there's only a single listener. 2011-05-18 17:55:39 -03:00
Rodrigo Damazio cb75c6fbe6 Fixing eclipse warnings all over the project. 2011-05-17 00:15:02 -03:00
20 changed files with 144 additions and 260 deletions
-1
View File
@@ -5,7 +5,6 @@
<classpathentry kind="lib" path="libs/google-common.jar"/> <classpathentry kind="lib" path="libs/google-common.jar"/>
<classpathentry kind="lib" path="libs/accounts.jar"/> <classpathentry kind="lib" path="libs/accounts.jar"/>
<classpathentry kind="lib" path="libs/google-api-client-1.2.2-alpha.jar"/> <classpathentry kind="lib" path="libs/google-api-client-1.2.2-alpha.jar"/>
<classpathentry kind="lib" path="libs/libGoogleAnalytics.jar"/>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="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"/>
+2 -3
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="30" android:versionCode="28"
android:versionName="1.1.7"> android:versionName="1.1.5">
<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">
@@ -114,7 +114,6 @@ limitations under the License.
<!-- Permissions for recording tracks and showing maps --> <!-- Permissions for recording tracks and showing maps -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH" />
Binary file not shown.
-5
View File
@@ -170,11 +170,6 @@ limitations under the License.
<item>inline skating</item> <item>inline skating</item>
<item>skate boarding</item> <item>skate boarding</item>
<item>roller skiing (classic)</item>
<item>roller skiing (skate)</item>
<item>cross-country skiing (classic)</item>
<item>cross-country skiing (skate)</item>
<item>snow shoeing</item> <item>snow shoeing</item>
<item>skiing</item> <item>skiing</item>
<item>snow boarding</item> <item>snow boarding</item>
@@ -38,6 +38,16 @@ limitations under the License.
<item>100</item> <item>100</item>
</string-array> </string-array>
<string-array name="min_recording_distance_values">
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>10</item>
<item>100</item>
</string-array>
<string-array name="max_recording_distance_values"> <string-array name="max_recording_distance_values">
<item>50</item> <item>50</item>
<item>100</item> <item>100</item>
-3
View File
@@ -39,7 +39,4 @@ limitations under the License.
<string name="sendtogoogle_google_fusiontables_url">google.com/fusiontables</string> <string name="sendtogoogle_google_fusiontables_url">google.com/fusiontables</string>
<string name="sendtogoogle_google_mymaps_url">maps.google.com</string> <string name="sendtogoogle_google_mymaps_url">maps.google.com</string>
<string name="sendtogoogle_google_docs_url">docs.google.com</string> <string name="sendtogoogle_google_docs_url">docs.google.com</string>
<!-- ID for Google Analytics -->
<string name="google_analytics_id">UA-7222692-2</string>
</resources> </resources>
+1 -1
View File
@@ -42,7 +42,7 @@ limitations under the License.
android:summary="@string/settings_announcement_frequency_summary" android:summary="@string/settings_announcement_frequency_summary"
android:entries="@array/task_frequency_options" android:entries="@array/task_frequency_options"
android:entryValues="@array/task_frequency_values" android:entryValues="@array/task_frequency_values"
android:defaultValue="0" /> android:defaultValue="-1" />
<com.google.android.apps.mytracks.IntegerListPreference <com.google.android.apps.mytracks.IntegerListPreference
android:key="@string/split_frequency_key" android:key="@string/split_frequency_key"
@@ -144,7 +144,6 @@ public class ChartActivity extends Activity implements TrackDataListener {
dataHub.registerTrackDataListener(this, EnumSet.of( dataHub.registerTrackDataListener(this, EnumSet.of(
ListenerDataType.SELECTED_TRACK_CHANGED, ListenerDataType.SELECTED_TRACK_CHANGED,
ListenerDataType.TRACK_UPDATES,
ListenerDataType.POINT_UPDATES, ListenerDataType.POINT_UPDATES,
ListenerDataType.SAMPLED_OUT_POINT_UPDATES, ListenerDataType.SAMPLED_OUT_POINT_UPDATES,
ListenerDataType.WAYPOINT_UPDATES, ListenerDataType.WAYPOINT_UPDATES,
@@ -425,7 +424,7 @@ public class ChartActivity extends Activity implements TrackDataListener {
this.metricUnits = metric; this.metricUnits = metric;
chartView.setMetricUnits(metric); chartView.setMetricUnits(metric);
return true; // Reload data return true; // Reload data
} }
@@ -1,12 +1,12 @@
/* /*
* Copyright 2009 Google Inc. * Copyright 2009 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * 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 * use this file except in compliance with the License. You may obtain a copy of
* the License at * the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -133,7 +133,7 @@ public class ExportAllTracks {
Log.i(Constants.TAG, "ExportAllTracks: Releasing wake lock."); Log.i(Constants.TAG, "ExportAllTracks: Releasing wake lock.");
} }
Log.i(Constants.TAG, "ExportAllTracks: Done"); Log.i(Constants.TAG, "ExportAllTracks: Done");
showToast(R.string.export_done, Toast.LENGTH_SHORT); Toast.makeText(activity, R.string.export_done, Toast.LENGTH_SHORT).show();
} }
private void makeProgressDialog(final int trackCount) { private void makeProgressDialog(final int trackCount) {
@@ -189,16 +189,12 @@ public class ExportAllTracks {
Log.i(Constants.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);
if (writer == null) {
showToast(R.string.error_track_does_not_exist, Toast.LENGTH_LONG);
return;
}
writer.writeTrack(); writer.writeTrack();
if (!writer.wasSuccess()) { if (!writer.wasSuccess()) {
// Abort the whole export on the first error. // Abort the whole export on the first error.
showToast(writer.getErrorMessage(), Toast.LENGTH_LONG); int error = writer.getErrorMessage();
Toast.makeText(activity, error, Toast.LENGTH_LONG).show();
return; return;
} }
} }
@@ -214,13 +210,4 @@ public class ExportAllTracks {
} }
} }
} }
private void showToast(final int messageId, final int length) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity, messageId, length).show();
}
});
}
} }
@@ -1,12 +1,12 @@
/* /*
* Copyright 2008 Google Inc. * Copyright 2008 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * 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 * use this file except in compliance with the License. You may obtain a copy of
* the License at * the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -51,7 +51,6 @@ import android.widget.ImageButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import java.util.EnumSet; import java.util.EnumSet;
@@ -337,9 +336,9 @@ public class MapActivity extends com.google.android.maps.MapActivity
if (trackSelected) { if (trackSelected) {
busyPane.setVisibility(View.VISIBLE); busyPane.setVisibility(View.VISIBLE);
zoomMapToBoundaries(track); zoomMapToBoundaries(track);
mapOverlay.setShowEndMarker(!isRecording); mapOverlay.setShowEndMarker(!isRecording);
busyPane.setVisibility(View.GONE); busyPane.setVisibility(View.GONE);
} }
@@ -465,21 +464,21 @@ public class MapActivity extends com.google.android.maps.MapActivity
@Override @Override
public void onProviderStateChange(ProviderState state) { public void onProviderStateChange(ProviderState state) {
final int messageId; final int messageId;
final boolean isGpsDisabled; final boolean bindClick;
switch (state) { switch (state) {
case DISABLED: case DISABLED:
messageId = R.string.status_enable_gps; messageId = R.string.status_enable_gps;
isGpsDisabled = true; bindClick = true;
break; break;
case NO_FIX: case NO_FIX:
case BAD_FIX: case BAD_FIX:
messageId = R.string.wait_for_fix; messageId = R.string.wait_for_fix;
isGpsDisabled = false; bindClick = false;
break; break;
case GOOD_FIX: case GOOD_FIX:
// Nothing to show. // Nothing to show.
messageId = -1; messageId = -1;
isGpsDisabled = false; bindClick = false;
break; break;
default: default:
throw new IllegalArgumentException("Unexpected state: " + state); throw new IllegalArgumentException("Unexpected state: " + state);
@@ -492,13 +491,7 @@ public class MapActivity extends com.google.android.maps.MapActivity
messageText.setText(messageId); messageText.setText(messageId);
messagePane.setVisibility(View.VISIBLE); messagePane.setVisibility(View.VISIBLE);
if (isGpsDisabled) { if (bindClick) {
// Give a warning about this state.
Toast.makeText(MapActivity.this,
R.string.error_no_gps_location_provider,
Toast.LENGTH_LONG).show();
// Make clicking take the user to the location settings.
messagePane.setOnClickListener(MapActivity.this); messagePane.setOnClickListener(MapActivity.this);
} else { } else {
messagePane.setOnClickListener(null); messagePane.setOnClickListener(null);
@@ -21,7 +21,6 @@ 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;
import com.google.android.accounts.Account; import com.google.android.accounts.Account;
import com.google.android.apps.analytics.GoogleAnalyticsTracker;
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.TrackDataHub; import com.google.android.apps.mytracks.content.TrackDataHub;
@@ -160,11 +159,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
private SharedPreferences sharedPreferences; private SharedPreferences sharedPreferences;
/**
* Google Analytics tracker
*/
private GoogleAnalyticsTracker tracker;
/** /**
* The connection to the track recording service. * The connection to the track recording service.
*/ */
@@ -256,13 +250,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
apiFeatures.getApiPlatformAdapter().enableStrictMode(); apiFeatures.getApiPlatformAdapter().enableStrictMode();
} }
tracker = GoogleAnalyticsTracker.getInstance();
// Start the tracker in manual dispatch mode...
tracker.start(this.getString(R.string.google_analytics_id), this.getApplicationContext());
tracker.setProductVersion("android-mytracks", SystemUtils.getMyTracksVersion(this));
tracker.trackPageView("/appstart");
tracker.dispatch();
providerUtils = MyTracksProviderUtils.Factory.get(this); providerUtils = MyTracksProviderUtils.Factory.get(this);
sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, 0); sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
dataHub = new TrackDataHub(this, sharedPreferences, providerUtils); dataHub = new TrackDataHub(this, sharedPreferences, providerUtils);
@@ -338,8 +325,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
dataHub.destroy(); dataHub.destroy();
tryUnbindTrackRecordingService(); tryUnbindTrackRecordingService();
tracker.dispatch();
tracker.stop();
super.onDestroy(); super.onDestroy();
} }
@@ -920,7 +905,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
* Initiates the process to send tracks to google. * Initiates the process to send tracks to google.
* This is called once the user has selected sending options via the * This is called once the user has selected sending options via the
* SendToGoogleDialog. * SendToGoogleDialog.
* *
* TODO: Change this whole flow to an actual state machine. * TODO: Change this whole flow to an actual state machine.
*/ */
public void sendToGoogle() { public void sendToGoogle() {
@@ -946,7 +931,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
private void sendToGoogleMapsOrPickMap(SendDialog sendToGoogleDialog) { private void sendToGoogleMapsOrPickMap(SendDialog sendToGoogleDialog) {
tracker.trackPageView("/send/maps");
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);
@@ -979,12 +963,8 @@ public class MyTracks extends TabActivity implements OnTouchListener,
// Update the map id for this track: // Update the map id for this track:
try { try {
Track track = providerUtils.getTrack(trackId); Track track = providerUtils.getTrack(trackId);
if (track != null) { track.setMapId(mapId);
track.setMapId(mapId); providerUtils.updateTrack(track);
providerUtils.updateTrack(track);
} else {
Log.w(TAG, "Updating map id failed.");
}
} 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.
@@ -1026,7 +1006,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
private void sendToFusionTables(final long trackId) { private void sendToFusionTables(final long trackId) {
tracker.trackPageView("/send/fusion_tables");
OnSendCompletedListener onCompletion = new OnSendCompletedListener() { OnSendCompletedListener onCompletion = new OnSendCompletedListener() {
@Override @Override
public void onSendCompleted(String tableId, boolean success, public void onSendCompleted(String tableId, boolean success,
@@ -1038,19 +1017,15 @@ public class MyTracks extends TabActivity implements OnTouchListener,
// Update the table id for this track: // Update the table id for this track:
try { try {
Track track = providerUtils.getTrack(trackId); Track track = providerUtils.getTrack(trackId);
if (track != null) { track.setTableId(tableId);
track.setTableId(tableId); providerUtils.updateTrack(track);
providerUtils.updateTrack(track);
} else {
Log.w(TAG, "Updating table id failed.");
}
} 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(TAG, "Updating table id failed.", e); Log.w(TAG, "Updating table id failed.", e);
} }
} }
onSendToFusionTablesDone(); onSendToFusionTablesDone();
} }
}; };
@@ -1095,10 +1070,9 @@ public class MyTracks extends TabActivity implements OnTouchListener,
private void sendToGoogleDocs(final long trackId) { private void sendToGoogleDocs(final long trackId) {
Log.d(TAG, "Sending to Docs...."); Log.d(TAG, "Sending to Docs....");
tracker.trackPageView("/send/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,
authMap.get(SendToDocs.GDATA_SERVICE_NAME_TRIX), authMap.get(SendToDocs.GDATA_SERVICE_NAME_TRIX),
authMap.get(SendToDocs.GDATA_SERVICE_NAME_DOCLIST), trackId); authMap.get(SendToDocs.GDATA_SERVICE_NAME_DOCLIST), trackId);
sendToTrackId = trackId; sendToTrackId = trackId;
@@ -1121,7 +1095,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
} }
private void onSendToGoogleDone() { private void onSendToGoogleDone() {
tracker.dispatch();
SendDialog sendToGoogleDialog = dialogManager.getSendToGoogleDialog(); SendDialog sendToGoogleDialog = dialogManager.getSendToGoogleDialog();
final boolean sentToMyMaps = sendToGoogleDialog.getSendToMyMaps(); final boolean sentToMyMaps = sendToGoogleDialog.getSendToMyMaps();
final boolean sentToFusionTables = sendToGoogleDialog.getSendToFusionTables(); final boolean sentToFusionTables = sendToGoogleDialog.getSendToFusionTables();
@@ -1255,11 +1228,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
*/ */
public void saveTrack(long trackId, TrackFileFormat format) { public void saveTrack(long trackId, TrackFileFormat format) {
TrackWriter writer = TrackWriterFactory.newWriter(this, providerUtils, trackId, format); TrackWriter writer = TrackWriterFactory.newWriter(this, providerUtils, trackId, format);
if (writer == null) {
dialogManager.showMessageDialog(R.string.error_track_does_not_exist, false);
return;
}
WriteProgressController controller = new WriteProgressController(this, writer); WriteProgressController controller = new WriteProgressController(this, writer);
controller.setOnCompletionListener(new WriteProgressController.OnCompletionListener() { controller.setOnCompletionListener(new WriteProgressController.OnCompletionListener() {
@Override @Override
@@ -1279,10 +1247,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
*/ */
public void sendTrack(long trackId, final TrackFileFormat format) { public void sendTrack(long trackId, final TrackFileFormat format) {
TrackWriter writer = TrackWriterFactory.newWriter(this, providerUtils, trackId, format); TrackWriter writer = TrackWriterFactory.newWriter(this, providerUtils, trackId, format);
if (writer == null) {
dialogManager.showMessageDialog(R.string.error_track_does_not_exist, false);
return;
}
FileUtils fileUtils = new FileUtils(); FileUtils fileUtils = new FileUtils();
String extension = format.getExtension(); String extension = format.getExtension();
@@ -1349,17 +1313,17 @@ public class MyTracks extends TabActivity implements OnTouchListener,
long getRecordingTrackId() { long getRecordingTrackId() {
return sharedPreferences.getLong(getString(R.string.recording_track_key), -1); return sharedPreferences.getLong(getString(R.string.recording_track_key), -1);
} }
// @VisibleForTesting // @VisibleForTesting
SharedPreferences getSharedPreferences() { SharedPreferences getSharedPreferences() {
return sharedPreferences; return sharedPreferences;
} }
// @VisibleForTesting // @VisibleForTesting
static void clearInstance() { static void clearInstance() {
instance = null; instance = null;
} }
// @VisibleForTesting // @VisibleForTesting
ITrackRecordingService getTrackRecordingService() { ITrackRecordingService getTrackRecordingService() {
return trackRecordingService; return trackRecordingService;
@@ -1,12 +1,12 @@
/* /*
* Copyright 2009 Google Inc. * Copyright 2009 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * 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 * use this file except in compliance with the License. You may obtain a copy of
* the License at * the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -73,18 +73,15 @@ public class WaypointsList extends ListActivity
contextPosition = info.position; contextPosition = info.position;
waypointId = WaypointsList.this.listView.getAdapter() waypointId = WaypointsList.this.listView.getAdapter()
.getItemId(contextPosition); .getItemId(contextPosition);
Waypoint waypoint = providerUtils.getWaypoint(info.id); int type = providerUtils.getWaypoint(info.id).getType();
if (waypoint != null) { menu.add(0, Constants.MENU_SHOW, 0,
int type = waypoint.getType(); R.string.waypointslist_show_waypoint);
menu.add(0, Constants.MENU_SHOW, 0, menu.add(0, Constants.MENU_EDIT, 0,
R.string.waypointslist_show_waypoint); R.string.waypointslist_edit_waypoint);
menu.add(0, Constants.MENU_EDIT, 0, menu.add(0, Constants.MENU_DELETE, 0,
R.string.waypointslist_edit_waypoint); R.string.waypointslist_delete_waypoint).setEnabled(
menu.add(0, Constants.MENU_DELETE, 0, recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT ||
R.string.waypointslist_delete_waypoint).setEnabled( info.id != providerUtils.getLastWaypointId(recordingTrackId));
recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT ||
info.id != providerUtils.getLastWaypointId(recordingTrackId));
}
} }
}; };
@@ -162,7 +159,7 @@ public class WaypointsList extends ListActivity
trackId = -1; trackId = -1;
} }
final long firstWaypointId = providerUtils.getFirstWaypointId(trackId); final long firstWaypointId = providerUtils.getFirstWaypointId(trackId);
waypointsCursor = getContentResolver().query( waypointsCursor = getContentResolver().query(
WaypointsColumns.CONTENT_URI, null, WaypointsColumns.CONTENT_URI, null,
WaypointsColumns.TRACKID + "=" + trackId + " AND " WaypointsColumns.TRACKID + "=" + trackId + " AND "
@@ -212,7 +209,7 @@ public class WaypointsList extends ListActivity
new String[] { WaypointsColumns.NAME, WaypointsColumns.TIME, new String[] { WaypointsColumns.NAME, WaypointsColumns.TIME,
WaypointsColumns.CATEGORY, WaypointsColumns.TYPE }, WaypointsColumns.CATEGORY, WaypointsColumns.TYPE },
new int[] { R.id.waypointslist_item_name, new int[] { R.id.waypointslist_item_name,
R.id.waypointslist_item_time, R.id.waypointslist_item_time,
R.id.waypointslist_item_category, R.id.waypointslist_item_category,
R.id.waypointslist_item_icon }); R.id.waypointslist_item_icon });
@@ -222,7 +219,7 @@ public class WaypointsList extends ListActivity
waypointsCursor.getColumnIndexOrThrow(WaypointsColumns.TYPE); waypointsCursor.getColumnIndexOrThrow(WaypointsColumns.TYPE);
adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() { adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
@Override @Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) { public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (columnIndex == timeIdx) { if (columnIndex == timeIdx) {
long time = cursor.getLong(timeIdx); long time = cursor.getLong(timeIdx);
TextView textView = (TextView) view; TextView textView = (TextView) view;
@@ -1,12 +1,12 @@
/* /*
* Copyright 2011 Google Inc. * Copyright 2011 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * 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 * use this file except in compliance with the License. You may obtain a copy of
* the License at * the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -17,10 +17,10 @@ package com.google.android.apps.mytracks.content;
import static com.google.android.apps.mytracks.Constants.DEFAULT_MIN_REQUIRED_ACCURACY; import static com.google.android.apps.mytracks.Constants.DEFAULT_MIN_REQUIRED_ACCURACY;
import static com.google.android.apps.mytracks.Constants.MAX_DISPLAYED_WAYPOINTS_POINTS; import static com.google.android.apps.mytracks.Constants.MAX_DISPLAYED_WAYPOINTS_POINTS;
import static com.google.android.apps.mytracks.Constants.TARGET_DISPLAYED_TRACK_POINTS;
import static com.google.android.apps.mytracks.Constants.MAX_LOCATION_AGE_MS; import static com.google.android.apps.mytracks.Constants.MAX_LOCATION_AGE_MS;
import static com.google.android.apps.mytracks.Constants.MAX_NETWORK_AGE_MS; import static com.google.android.apps.mytracks.Constants.MAX_NETWORK_AGE_MS;
import static com.google.android.apps.mytracks.Constants.TAG; import static com.google.android.apps.mytracks.Constants.TAG;
import static com.google.android.apps.mytracks.Constants.TARGET_DISPLAYED_TRACK_POINTS;
import com.google.android.apps.mytracks.content.DataSourceManager.DataSourceListener; import com.google.android.apps.mytracks.content.DataSourceManager.DataSourceListener;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.DoubleBufferedLocationFactory; import com.google.android.apps.mytracks.content.MyTracksProviderUtils.DoubleBufferedLocationFactory;
@@ -40,6 +40,7 @@ import android.location.LocationManager;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.util.Log; import android.util.Log;
import android.widget.Toast;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
@@ -445,7 +446,7 @@ public class TrackDataHub {
/** /**
* Reloads all track data received so far into the specified listeners. * Reloads all track data received so far into the specified listeners.
* *
* Assumes it's called from a block that synchronizes on {@link #listeners}. * Assumes it's called from a block that synchronizes on {@link #listeners}.
*/ */
private void reloadDataForListener(final ListenerRegistration registration) { private void reloadDataForListener(final ListenerRegistration registration) {
@@ -614,7 +615,7 @@ public class TrackDataHub {
@Override @Override
public void run() { public void run() {
Set<TrackDataListener> displayListeners = Set<TrackDataListener> displayListeners =
getListenersFor(ListenerDataType.DISPLAY_PREFERENCES); getListenersFor(ListenerDataType.DISPLAY_PREFERENCES);
for (TrackDataListener listener : displayListeners) { for (TrackDataListener listener : displayListeners) {
// TODO: Do the reloading just once for all interested listeners // TODO: Do the reloading just once for all interested listeners
@@ -635,7 +636,7 @@ public class TrackDataHub {
runInListenerThread(new Runnable() { runInListenerThread(new Runnable() {
@Override @Override
public void run() { public void run() {
Set<TrackDataListener> displayListeners = getListenersFor(ListenerDataType.DISPLAY_PREFERENCES); Set<TrackDataListener> displayListeners = getListenersFor(ListenerDataType.DISPLAY_PREFERENCES);
for (TrackDataListener listener : displayListeners) { for (TrackDataListener listener : displayListeners) {
if (listener.onUnitsChanged(useMetricUnits)) { if (listener.onUnitsChanged(useMetricUnits)) {
@@ -653,6 +654,9 @@ public class TrackDataHub {
final TrackDataListener.ProviderState state; final TrackDataListener.ProviderState state;
if (!hasProviderEnabled) { if (!hasProviderEnabled) {
state = ProviderState.DISABLED; state = ProviderState.DISABLED;
// Give a global warning about this state.
Toast.makeText(context, R.string.error_no_gps_location_provider, Toast.LENGTH_LONG).show();
} else if (!hasFix) { } else if (!hasFix) {
state = ProviderState.NO_FIX; state = ProviderState.NO_FIX;
} else if (!hasGoodFix) { } else if (!hasGoodFix) {
@@ -790,6 +794,10 @@ public class TrackDataHub {
public void run() { public void run() {
for (TrackDataListener listener : listeners) { for (TrackDataListener listener : listeners) {
listener.onSelectedTrackChanged(track, isRecordingSelected()); listener.onSelectedTrackChanged(track, isRecordingSelected());
if (track != null) {
listener.onTrackUpdated(track);
}
} }
} }
}); });
@@ -843,7 +851,7 @@ public class TrackDataHub {
if (!LocationUtils.isValidLocation(waypoint.getLocation())) { if (!LocationUtils.isValidLocation(waypoint.getLocation())) {
continue; continue;
} }
for (TrackDataListener listener : listeners) { for (TrackDataListener listener : listeners) {
listener.onNewWaypoint(waypoint); listener.onNewWaypoint(waypoint);
} }
@@ -854,7 +862,7 @@ public class TrackDataHub {
cursor.close(); cursor.close();
} }
} }
for (TrackDataListener listener : listeners) { for (TrackDataListener listener : listeners) {
listener.onNewWaypointsDone(); listener.onNewWaypointsDone();
} }
@@ -179,11 +179,6 @@ public class SendToFusionTables implements Runnable {
// Get the track meta-data // Get the track meta-data
Track track = providerUtils.getTrack(trackId); Track track = providerUtils.getTrack(trackId);
if (track == null) {
Log.w(Constants.TAG, "Cannot get track.");
return;
}
String originalDescription = track.getDescription(); String originalDescription = track.getDescription();
// Create a new table: // Create a new table:
@@ -212,6 +207,7 @@ public class SendToFusionTables implements Runnable {
Log.d(Constants.TAG, "SendToFusionTables: Done: " + success); Log.d(Constants.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() {
@@ -308,7 +304,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 == null || !locationsCursor.moveToFirst()) { if (!locationsCursor.moveToFirst()) {
Log.w(Constants.TAG, "Unable to get any points to upload"); Log.w(Constants.TAG, "Unable to get any points to upload");
return false; return false;
} }
@@ -395,9 +391,7 @@ public class SendToFusionTables implements Runnable {
return true; return true;
} finally { } finally {
if (locationsCursor != null) { locationsCursor.close();
locationsCursor.close();
}
} }
} }
@@ -1,12 +1,12 @@
/* /*
* Copyright 2008 Google Inc. * Copyright 2008 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * 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 * use this file except in compliance with the License. You may obtain a copy of
* the License at * the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -76,7 +76,7 @@ public class SendToMyMaps implements Runnable {
public interface OnSendCompletedListener { public interface OnSendCompletedListener {
void onSendCompleted(String mapId, boolean success, int statusMessage); void onSendCompleted(String mapId, boolean success, int statusMessage);
} }
public SendToMyMaps(Activity context, String mapId, AuthManager auth, public SendToMyMaps(Activity context, String mapId, AuthManager auth,
long trackId, ProgressIndicator progressIndicator, long trackId, ProgressIndicator progressIndicator,
OnSendCompletedListener onCompletion) { OnSendCompletedListener onCompletion) {
@@ -103,20 +103,15 @@ public class SendToMyMaps implements Runnable {
progressIndicator.setProgressValue(1); progressIndicator.setProgressValue(1);
progressIndicator.setProgressMessage( progressIndicator.setProgressMessage(
R.string.progress_message_reading_track); R.string.progress_message_reading_track);
// Get the track meta-data // Get the track meta-data
Track track = providerUtils.getTrack(trackId); Track track = providerUtils.getTrack(trackId);
if (track == null) {
Log.w(Constants.TAG, "Cannot get track.");
return;
}
String originalDescription = track.getDescription(); String originalDescription = track.getDescription();
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 = new MapsFacade(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);
if (isNewMap) { if (isNewMap) {
@@ -171,7 +166,7 @@ public class SendToMyMaps implements Runnable {
Log.w(TAG, "SendToMyMaps: upload waypoints failed."); Log.w(TAG, "SendToMyMaps: upload waypoints failed.");
} }
} }
if (success) { if (success) {
statusMessageId = isNewMap statusMessageId = isNewMap
? R.string.status_new_mymap_has_been_created ? R.string.status_new_mymap_has_been_created
@@ -183,7 +178,7 @@ public class SendToMyMaps implements Runnable {
if (mapsClient != null) { if (mapsClient != null) {
mapsClient.cleanUp(); mapsClient.cleanUp();
} }
final boolean finalSuccess = success; final boolean finalSuccess = success;
final int finalStatusMessageId = statusMessageId; final int finalStatusMessageId = statusMessageId;
context.runOnUiThread(new Runnable() { context.runOnUiThread(new Runnable() {
@@ -211,17 +206,17 @@ public class SendToMyMaps implements Runnable {
Cursor locationsCursor = Cursor locationsCursor =
providerUtils.getLocationsCursor(track.getId(), 0, -1, false); providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
try { try {
if (locationsCursor == null || !locationsCursor.moveToFirst()) { if (!locationsCursor.moveToFirst()) {
Log.w(TAG, "Unable to get any points to upload"); Log.w(TAG, "Unable to get any points to upload");
return false; return false;
} }
totalLocationsRead = 0; totalLocationsRead = 0;
totalLocationsPrepared = 0; totalLocationsPrepared = 0;
totalLocationsUploaded = 0; totalLocationsUploaded = 0;
totalLocations = locationsCursor.getCount(); totalLocations = locationsCursor.getCount();
totalSegmentsUploaded = 0; totalSegmentsUploaded = 0;
// 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));
@@ -229,12 +224,12 @@ public class SendToMyMaps implements Runnable {
"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 = DoubleBuffer elevationBuffer =
new DoubleBuffer(Constants.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(
R.string.progress_message_reading_track); R.string.progress_message_reading_track);
@@ -243,15 +238,15 @@ public class SendToMyMaps implements Runnable {
if (totalLocationsRead % 100 == 0) { if (totalLocationsRead % 100 == 0) {
updateProgress(); updateProgress();
} }
Location loc = providerUtils.createLocation(locationsCursor); Location loc = providerUtils.createLocation(locationsCursor);
locations.add(loc); locations.add(loc);
if (totalLocationsRead == 0) { if (totalLocationsRead == 0) {
// Put a marker at the first point of the first valid segment: // Put a marker at the first point of the first valid segment:
mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(), loc, true); mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(), loc, true);
} }
// Add to the elevation profile. // Add to the elevation profile.
if (loc != null && LocationUtils.isValidLocation(loc)) { if (loc != null && LocationUtils.isValidLocation(loc)) {
// All points go into the smoothing buffer... // All points go into the smoothing buffer...
@@ -261,19 +256,19 @@ public class SendToMyMaps implements Runnable {
double dist = lastLocation.distanceTo(loc); double dist = lastLocation.distanceTo(loc);
totalDistance += dist; totalDistance += dist;
} }
// ...but only a few points are really used to keep the url short. // ...but only a few points are really used to keep the url short.
if (totalLocationsRead % elevationSamplingFrequency == 0) { if (totalLocationsRead % elevationSamplingFrequency == 0) {
distances.add(totalDistance); distances.add(totalDistance);
elevations.add(elevationBuffer.getAverage()); elevations.add(elevationBuffer.getAverage());
} }
} }
// If the location was not valid, it's a segment split, so make sure the // If the location was not valid, it's a segment split, so make sure the
// distance between the previous segment and the new one is not accounted // distance between the previous segment and the new one is not accounted
// for in the next iteration. // for in the next iteration.
lastLocation = loc; lastLocation = loc;
// Every now and then, upload the accumulated points // Every now and then, upload the accumulated points
if (totalLocationsRead % MAX_POINTS_PER_UPLOAD if (totalLocationsRead % MAX_POINTS_PER_UPLOAD
== MAX_POINTS_PER_UPLOAD - 1) { == MAX_POINTS_PER_UPLOAD - 1) {
@@ -281,30 +276,28 @@ public class SendToMyMaps implements Runnable {
return false; return false;
} }
} }
totalLocationsRead++; totalLocationsRead++;
} while (locationsCursor.moveToNext()); } while (locationsCursor.moveToNext());
// Do a final upload with what's left // Do a final upload with what's left
if (!prepareAndUploadPoints(track, locations)) { if (!prepareAndUploadPoints(track, locations)) {
return false; return false;
} }
// Put an end marker at the last point of the last valid segment: // Put an end marker at the last point of the last valid segment:
if (lastLocation != null) { if (lastLocation != null) {
track.setDescription("<p>" + originalDescription + "</p><p>" track.setDescription("<p>" + originalDescription + "</p><p>"
+ stringUtils.generateTrackDescription( + stringUtils.generateTrackDescription(
track, distances, elevations) track, distances, elevations)
+ "</p>"); + "</p>");
return mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(), return mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(),
lastLocation, false); lastLocation, false);
} }
return true; return true;
} finally { } finally {
if (locationsCursor != null) { locationsCursor.close();
locationsCursor.close();
}
} }
} }
@@ -313,17 +306,17 @@ public class SendToMyMaps implements Runnable {
progressIndicator.setProgressMessage( progressIndicator.setProgressMessage(
R.string.progress_message_preparing_track); R.string.progress_message_preparing_track);
updateProgress(); updateProgress();
int numLocations = locations.size(); int numLocations = locations.size();
if (numLocations < 2) { if (numLocations < 2) {
Log.d(TAG, "Not preparing/uploading too few points"); Log.d(TAG, "Not preparing/uploading too few points");
totalLocationsUploaded += numLocations; totalLocationsUploaded += numLocations;
return true; return true;
} }
// Prepare/pre-process the points // Prepare/pre-process the points
ArrayList<Track> splitTracks = prepareLocations(track, locations); ArrayList<Track> splitTracks = prepareLocations(track, locations);
// Start uploading them // Start uploading them
progressIndicator.setProgressMessage( progressIndicator.setProgressMessage(
R.string.progress_message_sending_mymaps); R.string.progress_message_sending_mymaps);
@@ -337,7 +330,7 @@ public class SendToMyMaps implements Runnable {
Log.d(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(TAG, Log.d(TAG,
@@ -347,7 +340,7 @@ public class SendToMyMaps implements Runnable {
return false; return false;
} }
} }
locations.clear(); locations.clear();
totalLocationsUploaded += numLocations; totalLocationsUploaded += numLocations;
updateProgress(); updateProgress();
@@ -365,7 +358,7 @@ public class SendToMyMaps implements Runnable {
private ArrayList<Track> prepareLocations( private ArrayList<Track> prepareLocations(
Track track, Iterable<Location> locations) { Track track, Iterable<Location> locations) {
ArrayList<Track> splitTracks = new ArrayList<Track>(); ArrayList<Track> splitTracks = new ArrayList<Track>();
// Create segments from each full track: // Create segments from each full track:
Track segment = new Track(); Track segment = new Track();
TripStatistics segmentStats = segment.getStatistics(); TripStatistics segmentStats = segment.getStatistics();
@@ -384,11 +377,11 @@ public class SendToMyMaps implements Runnable {
if (loc.getLatitude() > 90) { if (loc.getLatitude() > 90) {
startNewTrackSegment = true; startNewTrackSegment = true;
} }
if (startNewTrackSegment) { if (startNewTrackSegment) {
// Close up the last segment. // Close up the last segment.
prepareTrackSegment(segment, splitTracks); prepareTrackSegment(segment, splitTracks);
Log.d(TAG, Log.d(TAG,
"MyTracksSendToMyMaps: Starting new track segment..."); "MyTracksSendToMyMaps: Starting new track segment...");
startNewTrackSegment = false; startNewTrackSegment = false;
@@ -398,7 +391,7 @@ public class SendToMyMaps implements Runnable {
segment.setDescription(/* track.getDescription() */ ""); segment.setDescription(/* track.getDescription() */ "");
segment.setCategory(track.getCategory()); segment.setCategory(track.getCategory());
} }
if (loc.getLatitude() <= 90) { if (loc.getLatitude() <= 90) {
segment.addLocation(loc); segment.addLocation(loc);
if (segmentStats.getStartTime() < 0) { if (segmentStats.getStartTime() < 0) {
@@ -407,9 +400,9 @@ public class SendToMyMaps implements Runnable {
} }
totalLocationsPrepared++; totalLocationsPrepared++;
} }
prepareTrackSegment(segment, splitTracks); prepareTrackSegment(segment, splitTracks);
return splitTracks; return splitTracks;
} }
@@ -432,13 +425,13 @@ public class SendToMyMaps implements Runnable {
&& segment.getLocations().size() > 0) { && segment.getLocations().size() > 0) {
segmentStats.setStopTime(segment.getLocations().size() - 1); segmentStats.setStopTime(segment.getLocations().size() - 1);
} }
/* /*
* Decimate to 2 meter precision. Mapshop doesn't like too many * Decimate to 2 meter precision. Mapshop doesn't like too many
* points: * points:
*/ */
LocationUtils.decimate(segment, 2.0); LocationUtils.decimate(segment, 2.0);
/* It the track still has > 500 points, split it in pieces: */ /* It the track still has > 500 points, split it in pieces: */
if (segment.getLocations().size() > 500) { if (segment.getLocations().size() > 500) {
splitTracks.addAll(LocationUtils.split(segment, 500)); splitTracks.addAll(LocationUtils.split(segment, 500));
@@ -187,7 +187,7 @@ public class TcxTrackWriter implements TrackFormatWriter {
&& sensorData.getCadence().getState() == Sensor.SensorState.SENDING && sensorData.getCadence().getState() == Sensor.SensorState.SENDING
&& sensorData.getCadence().hasValue()) { && sensorData.getCadence().hasValue()) {
pw.print(" <Cadence>"); pw.print(" <Cadence>");
pw.print(Math.min(254, sensorData.getCadence().getValue())); pw.print(sensorData.getCadence().getValue());
pw.println("</Cadence>"); pw.println("</Cadence>");
} }
} }
@@ -16,13 +16,10 @@
package com.google.android.apps.mytracks.io.file; package com.google.android.apps.mytracks.io.file;
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;
import android.content.Context; import android.content.Context;
import android.util.Log;
/** /**
* A factory to produce track writers for any format. * A factory to produce track writers for any format.
@@ -93,11 +90,6 @@ public class TrackWriterFactory {
MyTracksProviderUtils providerUtils, MyTracksProviderUtils providerUtils,
long trackId, TrackFileFormat format) { long trackId, TrackFileFormat format) {
Track track = providerUtils.getTrack(trackId); Track track = providerUtils.getTrack(trackId);
if (track == null) {
Log.w(TAG, "Trying to create a writer for an invalid track, id=" + trackId);
return null;
}
return newWriter(context, providerUtils, track, format); return newWriter(context, providerUtils, track, format);
} }
@@ -1,12 +1,12 @@
/* /*
* Copyright 2008 Google Inc. * Copyright 2008 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * 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 * use this file except in compliance with the License. You may obtain a copy of
* the License at * the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -40,7 +40,7 @@ import java.util.NoSuchElementException;
public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
private final ContentResolver contentResolver; private final ContentResolver contentResolver;
private int defaultCursorBatchSize = 2000; private int defaultCursorBatchSize = 2000;
public MyTracksProviderUtilsImpl(ContentResolver contentResolver) { public MyTracksProviderUtilsImpl(ContentResolver contentResolver) {
@@ -199,12 +199,12 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
public final int idxLatitude; public final int idxLatitude;
public final int idxLongitude; public final int idxLongitude;
public final int idxAltitude; public final int idxAltitude;
public final int idxTime; public final int idxTime;
public final int idxBearing; public final int idxBearing;
public final int idxAccuracy; public final int idxAccuracy;
public final int idxSpeed; public final int idxSpeed;
public final int idxSensor; public final int idxSensor;
public CachedTrackColumnIndices(Cursor cursor) { public CachedTrackColumnIndices(Cursor cursor) {
idxId = cursor.getColumnIndex(TrackPointsColumns._ID); idxId = cursor.getColumnIndex(TrackPointsColumns._ID);
idxLatitude = cursor.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE); idxLatitude = cursor.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE);
@@ -217,11 +217,11 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
idxSensor = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR); idxSensor = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR);
} }
} }
private void fillLocation(Cursor cursor, CachedTrackColumnIndices columnIndices, private void fillLocation(Cursor cursor, CachedTrackColumnIndices columnIndices,
Location location) { Location location) {
location.reset(); location.reset();
if (!cursor.isNull(columnIndices.idxLatitude)) { if (!cursor.isNull(columnIndices.idxLatitude)) {
location.setLatitude(1. * cursor.getInt(columnIndices.idxLatitude) / 1E6); location.setLatitude(1. * cursor.getInt(columnIndices.idxLatitude) / 1E6);
} }
@@ -256,7 +256,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
} }
} }
} }
@Override @Override
public void fillLocation(Cursor cursor, Location location) { public void fillLocation(Cursor cursor, Location location) {
CachedTrackColumnIndices columnIndicies = new CachedTrackColumnIndices(cursor); CachedTrackColumnIndices columnIndicies = new CachedTrackColumnIndices(cursor);
@@ -660,10 +660,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override @Override
public Waypoint getFirstWaypoint(long trackId) { public Waypoint getFirstWaypoint(long trackId) {
if (trackId < 0) {
return null;
}
Cursor cursor = contentResolver.query( Cursor cursor = contentResolver.query(
WaypointsColumns.CONTENT_URI, WaypointsColumns.CONTENT_URI,
null /*projection*/, null /*projection*/,
@@ -686,10 +682,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override @Override
public Waypoint getWaypoint(long waypointId) { public Waypoint getWaypoint(long waypointId) {
if (waypointId < 0) {
return null;
}
Cursor cursor = contentResolver.query( Cursor cursor = contentResolver.query(
WaypointsColumns.CONTENT_URI, WaypointsColumns.CONTENT_URI,
null /*projection*/, null /*projection*/,
@@ -712,10 +704,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override @Override
public long getLastLocationId(long trackId) { public long getLastLocationId(long trackId) {
if (trackId < 0) {
return -1;
}
final String[] projection = {"_id"}; final String[] projection = {"_id"};
Cursor cursor = contentResolver.query( Cursor cursor = contentResolver.query(
TrackPointsColumns.CONTENT_URI, TrackPointsColumns.CONTENT_URI,
@@ -740,10 +728,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override @Override
public long getFirstWaypointId(long trackId) { public long getFirstWaypointId(long trackId) {
if (trackId < 0) {
return -1;
}
final String[] projection = {"_id"}; final String[] projection = {"_id"};
Cursor cursor = contentResolver.query( Cursor cursor = contentResolver.query(
WaypointsColumns.CONTENT_URI, WaypointsColumns.CONTENT_URI,
@@ -768,10 +752,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override @Override
public long getLastWaypointId(long trackId) { public long getLastWaypointId(long trackId) {
if (trackId < 0) {
return -1;
}
final String[] projection = {"_id"}; final String[] projection = {"_id"};
Cursor cursor = contentResolver.query( Cursor cursor = contentResolver.query(
WaypointsColumns.CONTENT_URI, WaypointsColumns.CONTENT_URI,
@@ -835,10 +815,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override @Override
public Location getLocation(long id) { public Location getLocation(long id) {
if (id < 0) {
return null;
}
String selection = TrackPointsColumns._ID + "=" + id; String selection = TrackPointsColumns._ID + "=" + id;
return findLocationBy(selection); return findLocationBy(selection);
} }
@@ -846,11 +822,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override @Override
public Cursor getLocationsCursor(long trackId, long minTrackPointId, public Cursor getLocationsCursor(long trackId, long minTrackPointId,
int maxLocations, boolean descending) { int maxLocations, boolean descending) {
if (trackId < 0) { String selection;
return null;
}
String selection;
if (minTrackPointId >= 0) { if (minTrackPointId >= 0) {
selection = String.format("%s=%d AND %s%s%d", selection = String.format("%s=%d AND %s%s%d",
TrackPointsColumns.TRACKID, trackId, TrackPointsColumns._ID, TrackPointsColumns.TRACKID, trackId, TrackPointsColumns._ID,
@@ -870,10 +842,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override @Override
public Cursor getWaypointsCursor(long trackId, long minWaypointId, public Cursor getWaypointsCursor(long trackId, long minWaypointId,
int maxWaypoints) { int maxWaypoints) {
if (trackId < 0) {
return null;
}
String selection; String selection;
if (minWaypointId > 0) { if (minWaypointId > 0) {
selection = String.format("%s=%d AND %s>=%d", selection = String.format("%s=%d AND %s>=%d",
@@ -895,10 +863,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override @Override
public Track getTrack(long id) { public Track getTrack(long id) {
if (id < 0) {
return null;
}
String select = TracksColumns._ID + "=" + id; String select = TracksColumns._ID + "=" + id;
return findTrackBy(select); return findTrackBy(select);
} }
@@ -965,10 +929,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
@Override @Override
public boolean trackExists(long id) { public boolean trackExists(long id) {
if (id < 0) {
return false;
}
Cursor cursor = null; Cursor cursor = null;
try { try {
final String[] projection = { TracksColumns._ID }; final String[] projection = { TracksColumns._ID };
@@ -1007,7 +967,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
private Cursor cursor = getCursor(startTrackPointId); private Cursor cursor = getCursor(startTrackPointId);
private final CachedTrackColumnIndices columnIndices = cursor != null ? private final CachedTrackColumnIndices columnIndices = cursor != null ?
new CachedTrackColumnIndices(cursor) : null; new CachedTrackColumnIndices(cursor) : null;
private Cursor getCursor(long trackPointId) { private Cursor getCursor(long trackPointId) {
return getLocationsCursor(trackId, trackPointId, defaultCursorBatchSize, descending); return getLocationsCursor(trackId, trackPointId, defaultCursorBatchSize, descending);
} }
@@ -1019,7 +979,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
cursor = getCursor(pointId); cursor = getCursor(pointId);
return cursor != null; return cursor != null;
} }
@Override @Override
public long getLocationId() { public long getLocationId() {
return lastTrackPointId; return lastTrackPointId;
@@ -1039,7 +999,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
return cursor.getCount() == defaultCursorBatchSize && return cursor.getCount() == defaultCursorBatchSize &&
advanceCursorToNextBatch() && !cursor.isAfterLast(); advanceCursorToNextBatch() && !cursor.isAfterLast();
} }
return true; return true;
} }
@@ -1049,11 +1009,11 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
!(cursor.moveToNext() || advanceCursorToNextBatch() || cursor.moveToNext())) { !(cursor.moveToNext() || advanceCursorToNextBatch() || cursor.moveToNext())) {
throw new NoSuchElementException(); throw new NoSuchElementException();
} }
lastTrackPointId = cursor.getLong(columnIndices.idxId); lastTrackPointId = cursor.getLong(columnIndices.idxId);
Location location = locationFactory.createLocation(); Location location = locationFactory.createLocation();
fillLocation(cursor, columnIndices, location); fillLocation(cursor, columnIndices, location);
return location; return location;
} }
@@ -1071,7 +1031,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
} }
}; };
} }
// @VisibleForTesting // @VisibleForTesting
void setDefaultCursorBatchSize(int defaultCursorBatchSize) { void setDefaultCursorBatchSize(int defaultCursorBatchSize) {
this.defaultCursorBatchSize = defaultCursorBatchSize; this.defaultCursorBatchSize = defaultCursorBatchSize;
@@ -26,23 +26,20 @@ public class ZephyrMessageParserTest extends TestCase {
public void testParseBuffer() { public void testParseBuffer() {
byte[] buf = new byte[60]; byte[] buf = new byte[60];
// Heartrate (-1 =^ 255 unsigned byte) buf[12] = 50;
buf[12] = -1;
// Power
buf[11] = 51; buf[11] = 51;
// Cadence (=^ 255*16 strides/min) buf[56] = 32;
buf[56] = -1; buf[57] = 0;
buf[57] = 15;
Sensor.SensorDataSet sds = parser.parseBuffer(buf); Sensor.SensorDataSet sds = parser.parseBuffer(buf);
assertTrue(sds.hasHeartRate()); assertTrue(sds.hasHeartRate());
assertTrue(sds.getHeartRate().getState() == Sensor.SensorState.SENDING); assertTrue(sds.getHeartRate().getState() == Sensor.SensorState.SENDING);
assertEquals(255, sds.getHeartRate().getValue()); assertEquals(50, sds.getHeartRate().getValue());
assertTrue(sds.hasPower()); assertTrue(sds.hasPower());
assertTrue(sds.getPower().getState() == Sensor.SensorState.SENDING); assertTrue(sds.getPower().getState() == Sensor.SensorState.SENDING);
assertEquals(51, sds.getPower().getValue()); assertEquals(51, sds.getPower().getValue());
assertTrue(sds.hasCadence()); assertTrue(sds.hasCadence());
assertTrue(sds.getCadence().getState() == Sensor.SensorState.SENDING); assertTrue(sds.getCadence().getState() == Sensor.SensorState.SENDING);
assertEquals(255, sds.getCadence().getValue()); assertEquals(2, sds.getCadence().getValue());
} }
public void testFindNextAlignment() { public void testFindNextAlignment() {
@@ -1,12 +1,12 @@
/* /*
* Copyright 2010 Google Inc. * Copyright 2010 Google Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not * 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 * use this file except in compliance with the License. You may obtain a copy of
* the License at * the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,10 +15,10 @@
*/ */
package com.google.android.apps.mytracks.signalstrength; package com.google.android.apps.mytracks.signalstrength;
import static com.google.android.apps.mytracks.signalstrength.SignalStrengthConstants.START_SAMPLING; import static com.google.android.apps.mytracks.signalstrength.SignalStrengthConstants.*;
import static com.google.android.apps.mytracks.signalstrength.SignalStrengthConstants.STOP_SAMPLING;
import static com.google.android.apps.mytracks.signalstrength.SignalStrengthConstants.TAG;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtilsImpl;
import com.google.android.apps.mytracks.content.WaypointCreationRequest; import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.services.ITrackRecordingService; import com.google.android.apps.mytracks.services.ITrackRecordingService;
import com.google.android.apps.mytracks.signalstrength.SignalStrengthListener.SignalStrengthCallback; import com.google.android.apps.mytracks.signalstrength.SignalStrengthListener.SignalStrengthCallback;
@@ -206,7 +206,7 @@ public class SignalStrengthService extends Service
// Tell the user we've stopped // Tell the user we've stopped
Toast.makeText(this, R.string.stopped_sampling, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.stopped_sampling, Toast.LENGTH_SHORT).show();
// Stop // Stop
stopSelf(); stopSelf();
} }