mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-02 17:43:06 +02:00
Properly handling invalid track/point/waypoint IDs.
This makes the provider utils implementation return null for those cases, and fixes all callers which didn't check for that.
This commit is contained in:
@@ -144,6 +144,7 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
|
||||
dataHub.registerTrackDataListener(this, EnumSet.of(
|
||||
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||
ListenerDataType.TRACK_UPDATES,
|
||||
ListenerDataType.POINT_UPDATES,
|
||||
ListenerDataType.SAMPLED_OUT_POINT_UPDATES,
|
||||
ListenerDataType.WAYPOINT_UPDATES,
|
||||
@@ -424,7 +425,7 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
this.metricUnits = metric;
|
||||
|
||||
chartView.setMetricUnits(metric);
|
||||
|
||||
|
||||
return true; // Reload data
|
||||
}
|
||||
|
||||
|
||||
@@ -189,6 +189,11 @@ public class ExportAllTracks {
|
||||
Log.i(Constants.TAG, "ExportAllTracks: exporting: " + id);
|
||||
TrackWriter writer =
|
||||
TrackWriterFactory.newWriter(activity, providerUtils, id, format);
|
||||
if (writer == null) {
|
||||
showToast(R.string.error_track_does_not_exist, Toast.LENGTH_LONG);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.writeTrack();
|
||||
|
||||
if (!writer.wasSuccess()) {
|
||||
|
||||
@@ -905,7 +905,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
* Initiates the process to send tracks to google.
|
||||
* This is called once the user has selected sending options via the
|
||||
* SendToGoogleDialog.
|
||||
*
|
||||
*
|
||||
* TODO: Change this whole flow to an actual state machine.
|
||||
*/
|
||||
public void sendToGoogle() {
|
||||
@@ -963,8 +963,12 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
// Update the map id for this track:
|
||||
try {
|
||||
Track track = providerUtils.getTrack(trackId);
|
||||
track.setMapId(mapId);
|
||||
providerUtils.updateTrack(track);
|
||||
if (track != null) {
|
||||
track.setMapId(mapId);
|
||||
providerUtils.updateTrack(track);
|
||||
} else {
|
||||
Log.w(TAG, "Updating map id failed.");
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
// If that fails whatever reasons we'll just log an error, but
|
||||
// continue.
|
||||
@@ -1017,15 +1021,19 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
// Update the table id for this track:
|
||||
try {
|
||||
Track track = providerUtils.getTrack(trackId);
|
||||
track.setTableId(tableId);
|
||||
providerUtils.updateTrack(track);
|
||||
if (track != null) {
|
||||
track.setTableId(tableId);
|
||||
providerUtils.updateTrack(track);
|
||||
} else {
|
||||
Log.w(TAG, "Updating table id failed.");
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
// If that fails whatever reasons we'll just log an error, but
|
||||
// continue.
|
||||
Log.w(TAG, "Updating table id failed.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onSendToFusionTablesDone();
|
||||
}
|
||||
};
|
||||
@@ -1072,7 +1080,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
Log.d(TAG, "Sending to Docs....");
|
||||
setProgressValue(50);
|
||||
setProgressMessage(R.string.progress_message_sending_docs);
|
||||
final SendToDocs sender = new SendToDocs(this,
|
||||
final SendToDocs sender = new SendToDocs(this,
|
||||
authMap.get(SendToDocs.GDATA_SERVICE_NAME_TRIX),
|
||||
authMap.get(SendToDocs.GDATA_SERVICE_NAME_DOCLIST), trackId);
|
||||
sendToTrackId = trackId;
|
||||
@@ -1228,6 +1236,11 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
*/
|
||||
public void saveTrack(long trackId, TrackFileFormat 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);
|
||||
controller.setOnCompletionListener(new WriteProgressController.OnCompletionListener() {
|
||||
@Override
|
||||
@@ -1247,6 +1260,10 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
*/
|
||||
public void sendTrack(long trackId, final TrackFileFormat 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();
|
||||
String extension = format.getExtension();
|
||||
@@ -1313,17 +1330,17 @@ public class MyTracks extends TabActivity implements OnTouchListener,
|
||||
long getRecordingTrackId() {
|
||||
return sharedPreferences.getLong(getString(R.string.recording_track_key), -1);
|
||||
}
|
||||
|
||||
|
||||
// @VisibleForTesting
|
||||
SharedPreferences getSharedPreferences() {
|
||||
return sharedPreferences;
|
||||
}
|
||||
|
||||
|
||||
// @VisibleForTesting
|
||||
static void clearInstance() {
|
||||
instance = null;
|
||||
}
|
||||
|
||||
|
||||
// @VisibleForTesting
|
||||
ITrackRecordingService getTrackRecordingService() {
|
||||
return trackRecordingService;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
@@ -73,15 +73,18 @@ public class WaypointsList extends ListActivity
|
||||
contextPosition = info.position;
|
||||
waypointId = WaypointsList.this.listView.getAdapter()
|
||||
.getItemId(contextPosition);
|
||||
int type = providerUtils.getWaypoint(info.id).getType();
|
||||
menu.add(0, Constants.MENU_SHOW, 0,
|
||||
R.string.waypointslist_show_waypoint);
|
||||
menu.add(0, Constants.MENU_EDIT, 0,
|
||||
R.string.waypointslist_edit_waypoint);
|
||||
menu.add(0, Constants.MENU_DELETE, 0,
|
||||
R.string.waypointslist_delete_waypoint).setEnabled(
|
||||
recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT ||
|
||||
info.id != providerUtils.getLastWaypointId(recordingTrackId));
|
||||
Waypoint waypoint = providerUtils.getWaypoint(info.id);
|
||||
if (waypoint != null) {
|
||||
int type = waypoint.getType();
|
||||
menu.add(0, Constants.MENU_SHOW, 0,
|
||||
R.string.waypointslist_show_waypoint);
|
||||
menu.add(0, Constants.MENU_EDIT, 0,
|
||||
R.string.waypointslist_edit_waypoint);
|
||||
menu.add(0, Constants.MENU_DELETE, 0,
|
||||
R.string.waypointslist_delete_waypoint).setEnabled(
|
||||
recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT ||
|
||||
info.id != providerUtils.getLastWaypointId(recordingTrackId));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -159,7 +162,7 @@ public class WaypointsList extends ListActivity
|
||||
trackId = -1;
|
||||
}
|
||||
|
||||
final long firstWaypointId = providerUtils.getFirstWaypointId(trackId);
|
||||
final long firstWaypointId = providerUtils.getFirstWaypointId(trackId);
|
||||
waypointsCursor = getContentResolver().query(
|
||||
WaypointsColumns.CONTENT_URI, null,
|
||||
WaypointsColumns.TRACKID + "=" + trackId + " AND "
|
||||
@@ -209,7 +212,7 @@ public class WaypointsList extends ListActivity
|
||||
new String[] { WaypointsColumns.NAME, WaypointsColumns.TIME,
|
||||
WaypointsColumns.CATEGORY, WaypointsColumns.TYPE },
|
||||
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_icon });
|
||||
|
||||
@@ -219,7 +222,7 @@ public class WaypointsList extends ListActivity
|
||||
waypointsCursor.getColumnIndexOrThrow(WaypointsColumns.TYPE);
|
||||
adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
|
||||
@Override
|
||||
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
|
||||
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
|
||||
if (columnIndex == timeIdx) {
|
||||
long time = cursor.getLong(timeIdx);
|
||||
TextView textView = (TextView) view;
|
||||
|
||||
@@ -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.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_NETWORK_AGE_MS;
|
||||
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.MyTracksProviderUtils.DoubleBufferedLocationFactory;
|
||||
@@ -40,7 +40,6 @@ import android.location.LocationManager;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
@@ -791,10 +790,6 @@ public class TrackDataHub {
|
||||
public void run() {
|
||||
for (TrackDataListener listener : listeners) {
|
||||
listener.onSelectedTrackChanged(track, isRecordingSelected());
|
||||
|
||||
if (track != null) {
|
||||
listener.onTrackUpdated(track);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -179,6 +179,11 @@ public class SendToFusionTables implements Runnable {
|
||||
|
||||
// Get the track meta-data
|
||||
Track track = providerUtils.getTrack(trackId);
|
||||
if (track == null) {
|
||||
Log.w(Constants.TAG, "Cannot get track.");
|
||||
return;
|
||||
}
|
||||
|
||||
String originalDescription = track.getDescription();
|
||||
|
||||
// Create a new table:
|
||||
@@ -207,7 +212,6 @@ public class SendToFusionTables implements Runnable {
|
||||
Log.d(Constants.TAG, "SendToFusionTables: Done: " + success);
|
||||
progressIndicator.setProgressValue(PROGRESS_COMPLETE);
|
||||
} finally {
|
||||
|
||||
final boolean finalSuccess = success;
|
||||
final int finalStatusMessageId = statusMessageId;
|
||||
context.runOnUiThread(new Runnable() {
|
||||
@@ -304,7 +308,7 @@ public class SendToFusionTables implements Runnable {
|
||||
|
||||
Cursor locationsCursor = providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
|
||||
try {
|
||||
if (!locationsCursor.moveToFirst()) {
|
||||
if (locationsCursor == null || !locationsCursor.moveToFirst()) {
|
||||
Log.w(Constants.TAG, "Unable to get any points to upload");
|
||||
return false;
|
||||
}
|
||||
@@ -391,7 +395,9 @@ public class SendToFusionTables implements Runnable {
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
locationsCursor.close();
|
||||
if (locationsCursor != null) {
|
||||
locationsCursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2008 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
|
||||
@@ -76,7 +76,7 @@ public class SendToMyMaps implements Runnable {
|
||||
public interface OnSendCompletedListener {
|
||||
void onSendCompleted(String mapId, boolean success, int statusMessage);
|
||||
}
|
||||
|
||||
|
||||
public SendToMyMaps(Activity context, String mapId, AuthManager auth,
|
||||
long trackId, ProgressIndicator progressIndicator,
|
||||
OnSendCompletedListener onCompletion) {
|
||||
@@ -103,15 +103,20 @@ public class SendToMyMaps implements Runnable {
|
||||
progressIndicator.setProgressValue(1);
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_reading_track);
|
||||
|
||||
|
||||
// Get the track meta-data
|
||||
Track track = providerUtils.getTrack(trackId);
|
||||
if (track == null) {
|
||||
Log.w(Constants.TAG, "Cannot get track.");
|
||||
return;
|
||||
}
|
||||
|
||||
String originalDescription = track.getDescription();
|
||||
track.setDescription("<p>" + track.getDescription() + "</p><p>"
|
||||
+ stringUtils.generateTrackDescription(track, null, null) + "</p>");
|
||||
|
||||
mapsClient = new MapsFacade(context, auth);
|
||||
|
||||
|
||||
// Create a new map if necessary:
|
||||
boolean isNewMap = mapId.equals(NEW_MAP_ID);
|
||||
if (isNewMap) {
|
||||
@@ -166,7 +171,7 @@ public class SendToMyMaps implements Runnable {
|
||||
Log.w(TAG, "SendToMyMaps: upload waypoints failed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (success) {
|
||||
statusMessageId = isNewMap
|
||||
? R.string.status_new_mymap_has_been_created
|
||||
@@ -178,7 +183,7 @@ public class SendToMyMaps implements Runnable {
|
||||
if (mapsClient != null) {
|
||||
mapsClient.cleanUp();
|
||||
}
|
||||
|
||||
|
||||
final boolean finalSuccess = success;
|
||||
final int finalStatusMessageId = statusMessageId;
|
||||
context.runOnUiThread(new Runnable() {
|
||||
@@ -206,17 +211,17 @@ public class SendToMyMaps implements Runnable {
|
||||
Cursor locationsCursor =
|
||||
providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
|
||||
try {
|
||||
if (!locationsCursor.moveToFirst()) {
|
||||
if (locationsCursor == null || !locationsCursor.moveToFirst()) {
|
||||
Log.w(TAG, "Unable to get any points to upload");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
totalLocationsRead = 0;
|
||||
totalLocationsPrepared = 0;
|
||||
totalLocationsUploaded = 0;
|
||||
totalLocations = locationsCursor.getCount();
|
||||
totalSegmentsUploaded = 0;
|
||||
|
||||
|
||||
// Limit the number of elevation readings. Ideally we would want around 250.
|
||||
int elevationSamplingFrequency =
|
||||
Math.max(1, (int) (totalLocations / 250.0));
|
||||
@@ -224,12 +229,12 @@ public class SendToMyMaps implements Runnable {
|
||||
"Using elevation sampling factor: " + elevationSamplingFrequency
|
||||
+ " on " + totalLocations);
|
||||
double totalDistance = 0;
|
||||
|
||||
|
||||
Vector<Double> distances = new Vector<Double>();
|
||||
Vector<Double> elevations = new Vector<Double>();
|
||||
DoubleBuffer elevationBuffer =
|
||||
new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
|
||||
|
||||
|
||||
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_reading_track);
|
||||
@@ -238,15 +243,15 @@ public class SendToMyMaps implements Runnable {
|
||||
if (totalLocationsRead % 100 == 0) {
|
||||
updateProgress();
|
||||
}
|
||||
|
||||
|
||||
Location loc = providerUtils.createLocation(locationsCursor);
|
||||
locations.add(loc);
|
||||
|
||||
|
||||
if (totalLocationsRead == 0) {
|
||||
// Put a marker at the first point of the first valid segment:
|
||||
mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(), loc, true);
|
||||
}
|
||||
|
||||
|
||||
// Add to the elevation profile.
|
||||
if (loc != null && LocationUtils.isValidLocation(loc)) {
|
||||
// All points go into the smoothing buffer...
|
||||
@@ -256,19 +261,19 @@ public class SendToMyMaps implements Runnable {
|
||||
double dist = lastLocation.distanceTo(loc);
|
||||
totalDistance += dist;
|
||||
}
|
||||
|
||||
|
||||
// ...but only a few points are really used to keep the url short.
|
||||
if (totalLocationsRead % elevationSamplingFrequency == 0) {
|
||||
distances.add(totalDistance);
|
||||
elevations.add(elevationBuffer.getAverage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
// for in the next iteration.
|
||||
lastLocation = loc;
|
||||
|
||||
|
||||
// Every now and then, upload the accumulated points
|
||||
if (totalLocationsRead % MAX_POINTS_PER_UPLOAD
|
||||
== MAX_POINTS_PER_UPLOAD - 1) {
|
||||
@@ -276,28 +281,30 @@ public class SendToMyMaps implements Runnable {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
totalLocationsRead++;
|
||||
} while (locationsCursor.moveToNext());
|
||||
|
||||
|
||||
// Do a final upload with what's left
|
||||
if (!prepareAndUploadPoints(track, locations)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Put an end marker at the last point of the last valid segment:
|
||||
if (lastLocation != null) {
|
||||
track.setDescription("<p>" + originalDescription + "</p><p>"
|
||||
+ stringUtils.generateTrackDescription(
|
||||
track, distances, elevations)
|
||||
+ "</p>");
|
||||
return mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(),
|
||||
return mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(),
|
||||
lastLocation, false);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
locationsCursor.close();
|
||||
if (locationsCursor != null) {
|
||||
locationsCursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,17 +313,17 @@ public class SendToMyMaps implements Runnable {
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_preparing_track);
|
||||
updateProgress();
|
||||
|
||||
|
||||
int numLocations = locations.size();
|
||||
if (numLocations < 2) {
|
||||
Log.d(TAG, "Not preparing/uploading too few points");
|
||||
totalLocationsUploaded += numLocations;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Prepare/pre-process the points
|
||||
ArrayList<Track> splitTracks = prepareLocations(track, locations);
|
||||
|
||||
|
||||
// Start uploading them
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_sending_mymaps);
|
||||
@@ -330,7 +337,7 @@ public class SendToMyMaps implements Runnable {
|
||||
Log.d(TAG,
|
||||
"SendToMyMaps: Prepared feature for upload w/ "
|
||||
+ splitTrack.getLocations().size() + " points.");
|
||||
|
||||
|
||||
// Transmit tracks via GData feed:
|
||||
// -------------------------------
|
||||
Log.d(TAG,
|
||||
@@ -340,7 +347,7 @@ public class SendToMyMaps implements Runnable {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
locations.clear();
|
||||
totalLocationsUploaded += numLocations;
|
||||
updateProgress();
|
||||
@@ -358,7 +365,7 @@ public class SendToMyMaps implements Runnable {
|
||||
private ArrayList<Track> prepareLocations(
|
||||
Track track, Iterable<Location> locations) {
|
||||
ArrayList<Track> splitTracks = new ArrayList<Track>();
|
||||
|
||||
|
||||
// Create segments from each full track:
|
||||
Track segment = new Track();
|
||||
TripStatistics segmentStats = segment.getStatistics();
|
||||
@@ -377,11 +384,11 @@ public class SendToMyMaps implements Runnable {
|
||||
if (loc.getLatitude() > 90) {
|
||||
startNewTrackSegment = true;
|
||||
}
|
||||
|
||||
|
||||
if (startNewTrackSegment) {
|
||||
// Close up the last segment.
|
||||
prepareTrackSegment(segment, splitTracks);
|
||||
|
||||
|
||||
Log.d(TAG,
|
||||
"MyTracksSendToMyMaps: Starting new track segment...");
|
||||
startNewTrackSegment = false;
|
||||
@@ -391,7 +398,7 @@ public class SendToMyMaps implements Runnable {
|
||||
segment.setDescription(/* track.getDescription() */ "");
|
||||
segment.setCategory(track.getCategory());
|
||||
}
|
||||
|
||||
|
||||
if (loc.getLatitude() <= 90) {
|
||||
segment.addLocation(loc);
|
||||
if (segmentStats.getStartTime() < 0) {
|
||||
@@ -400,9 +407,9 @@ public class SendToMyMaps implements Runnable {
|
||||
}
|
||||
totalLocationsPrepared++;
|
||||
}
|
||||
|
||||
|
||||
prepareTrackSegment(segment, splitTracks);
|
||||
|
||||
|
||||
return splitTracks;
|
||||
}
|
||||
|
||||
@@ -425,13 +432,13 @@ public class SendToMyMaps implements Runnable {
|
||||
&& segment.getLocations().size() > 0) {
|
||||
segmentStats.setStopTime(segment.getLocations().size() - 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decimate to 2 meter precision. Mapshop doesn't like too many
|
||||
* points:
|
||||
*/
|
||||
LocationUtils.decimate(segment, 2.0);
|
||||
|
||||
|
||||
/* It the track still has > 500 points, split it in pieces: */
|
||||
if (segment.getLocations().size() > 500) {
|
||||
splitTracks.addAll(LocationUtils.split(segment, 500));
|
||||
|
||||
@@ -16,10 +16,13 @@
|
||||
|
||||
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.Track;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A factory to produce track writers for any format.
|
||||
@@ -90,6 +93,11 @@ public class TrackWriterFactory {
|
||||
MyTracksProviderUtils providerUtils,
|
||||
long trackId, TrackFileFormat format) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
+58
-18
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2008 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
|
||||
@@ -40,7 +40,7 @@ import java.util.NoSuchElementException;
|
||||
public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
|
||||
private final ContentResolver contentResolver;
|
||||
|
||||
|
||||
private int defaultCursorBatchSize = 2000;
|
||||
|
||||
public MyTracksProviderUtilsImpl(ContentResolver contentResolver) {
|
||||
@@ -199,12 +199,12 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
public final int idxLatitude;
|
||||
public final int idxLongitude;
|
||||
public final int idxAltitude;
|
||||
public final int idxTime;
|
||||
public final int idxBearing;
|
||||
public final int idxTime;
|
||||
public final int idxBearing;
|
||||
public final int idxAccuracy;
|
||||
public final int idxSpeed;
|
||||
public final int idxSensor;
|
||||
|
||||
public final int idxSensor;
|
||||
|
||||
public CachedTrackColumnIndices(Cursor cursor) {
|
||||
idxId = cursor.getColumnIndex(TrackPointsColumns._ID);
|
||||
idxLatitude = cursor.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE);
|
||||
@@ -217,11 +217,11 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
idxSensor = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void fillLocation(Cursor cursor, CachedTrackColumnIndices columnIndices,
|
||||
Location location) {
|
||||
location.reset();
|
||||
|
||||
|
||||
if (!cursor.isNull(columnIndices.idxLatitude)) {
|
||||
location.setLatitude(1. * cursor.getInt(columnIndices.idxLatitude) / 1E6);
|
||||
}
|
||||
@@ -256,7 +256,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void fillLocation(Cursor cursor, Location location) {
|
||||
CachedTrackColumnIndices columnIndicies = new CachedTrackColumnIndices(cursor);
|
||||
@@ -660,6 +660,10 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
|
||||
@Override
|
||||
public Waypoint getFirstWaypoint(long trackId) {
|
||||
if (trackId <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Cursor cursor = contentResolver.query(
|
||||
WaypointsColumns.CONTENT_URI,
|
||||
null /*projection*/,
|
||||
@@ -682,6 +686,10 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
|
||||
@Override
|
||||
public Waypoint getWaypoint(long waypointId) {
|
||||
if (waypointId < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Cursor cursor = contentResolver.query(
|
||||
WaypointsColumns.CONTENT_URI,
|
||||
null /*projection*/,
|
||||
@@ -704,6 +712,10 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
|
||||
@Override
|
||||
public long getLastLocationId(long trackId) {
|
||||
if (trackId < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final String[] projection = {"_id"};
|
||||
Cursor cursor = contentResolver.query(
|
||||
TrackPointsColumns.CONTENT_URI,
|
||||
@@ -728,6 +740,10 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
|
||||
@Override
|
||||
public long getFirstWaypointId(long trackId) {
|
||||
if (trackId < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final String[] projection = {"_id"};
|
||||
Cursor cursor = contentResolver.query(
|
||||
WaypointsColumns.CONTENT_URI,
|
||||
@@ -752,6 +768,10 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
|
||||
@Override
|
||||
public long getLastWaypointId(long trackId) {
|
||||
if (trackId < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final String[] projection = {"_id"};
|
||||
Cursor cursor = contentResolver.query(
|
||||
WaypointsColumns.CONTENT_URI,
|
||||
@@ -815,6 +835,10 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
|
||||
@Override
|
||||
public Location getLocation(long id) {
|
||||
if (id < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String selection = TrackPointsColumns._ID + "=" + id;
|
||||
return findLocationBy(selection);
|
||||
}
|
||||
@@ -822,7 +846,11 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
@Override
|
||||
public Cursor getLocationsCursor(long trackId, long minTrackPointId,
|
||||
int maxLocations, boolean descending) {
|
||||
String selection;
|
||||
if (trackId < 0 || maxLocations < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String selection;
|
||||
if (minTrackPointId >= 0) {
|
||||
selection = String.format("%s=%d AND %s%s%d",
|
||||
TrackPointsColumns.TRACKID, trackId, TrackPointsColumns._ID,
|
||||
@@ -842,6 +870,10 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
@Override
|
||||
public Cursor getWaypointsCursor(long trackId, long minWaypointId,
|
||||
int maxWaypoints) {
|
||||
if (trackId < 0 || maxWaypoints < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String selection;
|
||||
if (minWaypointId > 0) {
|
||||
selection = String.format("%s=%d AND %s>=%d",
|
||||
@@ -863,6 +895,10 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
|
||||
@Override
|
||||
public Track getTrack(long id) {
|
||||
if (id < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String select = TracksColumns._ID + "=" + id;
|
||||
return findTrackBy(select);
|
||||
}
|
||||
@@ -929,6 +965,10 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
|
||||
@Override
|
||||
public boolean trackExists(long id) {
|
||||
if (id < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
final String[] projection = { TracksColumns._ID };
|
||||
@@ -967,7 +1007,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
private Cursor cursor = getCursor(startTrackPointId);
|
||||
private final CachedTrackColumnIndices columnIndices = cursor != null ?
|
||||
new CachedTrackColumnIndices(cursor) : null;
|
||||
|
||||
|
||||
private Cursor getCursor(long trackPointId) {
|
||||
return getLocationsCursor(trackId, trackPointId, defaultCursorBatchSize, descending);
|
||||
}
|
||||
@@ -979,7 +1019,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
cursor = getCursor(pointId);
|
||||
return cursor != null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getLocationId() {
|
||||
return lastTrackPointId;
|
||||
@@ -999,7 +1039,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
return cursor.getCount() == defaultCursorBatchSize &&
|
||||
advanceCursorToNextBatch() && !cursor.isAfterLast();
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1009,11 +1049,11 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
!(cursor.moveToNext() || advanceCursorToNextBatch() || cursor.moveToNext())) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
|
||||
lastTrackPointId = cursor.getLong(columnIndices.idxId);
|
||||
Location location = locationFactory.createLocation();
|
||||
fillLocation(cursor, columnIndices, location);
|
||||
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
@@ -1031,7 +1071,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// @VisibleForTesting
|
||||
void setDefaultCursorBatchSize(int defaultCursorBatchSize) {
|
||||
this.defaultCursorBatchSize = defaultCursorBatchSize;
|
||||
|
||||
Reference in New Issue
Block a user