diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyMapsList.java b/MyTracks/src/com/google/android/apps/mytracks/MyMapsList.java
index bcdbe11f8..7b74ac606 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/MyMapsList.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/MyMapsList.java
@@ -19,7 +19,6 @@ import com.google.android.accounts.Account;
import com.google.android.apps.mytracks.io.AuthManager;
import com.google.android.apps.mytracks.io.AuthManagerFactory;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
-import com.google.android.apps.mytracks.io.mymaps.MapsFacadeImpl;
import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants;
import com.google.android.maps.mytracks.R;
@@ -125,7 +124,7 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
auth.doLogin(new Runnable() {
public void run() {
// Runs in UI thread.
- mapsClient = new MapsFacadeImpl(MyMapsList.this, auth);
+ mapsClient = new MapsFacade(MyMapsList.this, auth);
startLookup();
}
@@ -200,7 +199,7 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
shareIntent.putExtra(Intent.EXTRA_TEXT, String.format(
getText(R.string.share_map_body_format).toString(),
listItem[1],
- MapsFacadeImpl.buildMapUrl(listItem[0])));
+ MapsFacade.buildMapUrl(listItem[0])));
startActivity(Intent.createChooser(shareIntent,
getText(R.string.share_map).toString()));
return true;
diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java b/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java
index 3050efd94..64db86daf 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java
@@ -35,7 +35,7 @@ import com.google.android.apps.mytracks.io.TempFileCleaner;
import com.google.android.apps.mytracks.io.TrackWriter;
import com.google.android.apps.mytracks.io.TrackWriterFactory;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
-import com.google.android.apps.mytracks.io.mymaps.MapsFacadeImpl;
+import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants;
import com.google.android.apps.mytracks.io.sendtogoogle.ResultDialogFactory;
import com.google.android.apps.mytracks.io.sendtogoogle.SendDialog;
@@ -607,7 +607,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
Track selectedTrack = providerUtils.getTrack(selectedTrackId);
if (selectedTrack != null) {
if (!TextUtils.isEmpty(selectedTrack.getMapId())) {
- shareLinkToMap(MapsFacadeImpl.buildMapUrl(selectedTrack.getMapId()));
+ shareLinkToMap(MapsFacade.buildMapUrl(selectedTrack.getMapId()));
} else if (!TextUtils.isEmpty(selectedTrack.getTableId())) {
shareLinkToMap(getFusionTablesUrl(selectedTrackId));
} else {
@@ -1226,7 +1226,7 @@ public class MyTracks extends TabActivity implements OnTouchListener,
String url = null;
if (sentToMyMaps && sendToMyMapsSuccess) {
// Prefer a link to My Maps
- url = MapsFacadeImpl.buildMapUrl(sendToMyMapsMapId);
+ url = MapsFacade.buildMapUrl(sendToMyMapsMapId);
} else if (sentToFusionTables && sendToFusionTablesSuccess) {
// Otherwise try using the link to fusion tables
url = getFusionTablesUrl(sendToTrackId);
diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java b/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java
index bff49362a..3891b0322 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java
@@ -22,8 +22,6 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
-import com.google.android.apps.mytracks.io.mymaps.MapsFacade.WaypointData;
-import com.google.android.apps.mytracks.io.mymaps.MapsFacadeImpl;
import com.google.android.apps.mytracks.stats.DoubleBuffer;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.MyTracksUtils;
@@ -112,7 +110,7 @@ public class SendToMyMaps implements Runnable {
track.setDescription("
" + track.getDescription() + "
"
+ stringUtils.generateTrackDescription(track, null, null) + "
");
- mapsClient = new MapsFacadeImpl(context, auth);
+ mapsClient = new MapsFacade(context, auth);
// Create a new map if necessary:
boolean isNewMap = mapId.equals(NEW_MAP_ID);
@@ -149,11 +147,10 @@ public class SendToMyMaps implements Runnable {
if (c.getCount() > 1 && c.moveToFirst()) {
// This will skip the 1st waypoint (it carries the stats for the
// last segment).
- ArrayList waypoints = new ArrayList(c.getCount() - 1);
+ ArrayList waypoints = new ArrayList(c.getCount() - 1);
while (c.moveToNext()) {
Waypoint wpt = providerUtils.createWaypoint(c);
- waypoints.add(new WaypointData(
- wpt.getName(), wpt.getDescription(), wpt.getIcon(), wpt.getLocation()));
+ waypoints.add(wpt);
}
success = mapsClient.uploadWaypoints(mapId, waypoints);
diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsFacade.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsFacade.java
index e2a353899..86a92ec5c 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsFacade.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsFacade.java
@@ -2,17 +2,30 @@
package com.google.android.apps.mytracks.io.mymaps;
import com.google.android.apps.mytracks.content.Waypoint;
+import com.google.android.apps.mytracks.io.AuthManager;
+import com.google.android.maps.GeoPoint;
+import com.google.android.maps.mytracks.R;
+import com.google.wireless.gdata.client.HttpException;
+import com.google.wireless.gdata.data.Entry;
+import com.google.wireless.gdata.parser.GDataParser;
+import com.google.wireless.gdata.parser.ParseException;
+import android.content.Context;
import android.location.Location;
+import android.text.TextUtils;
+import android.util.Log;
+import java.io.IOException;
import java.util.Collection;
+import org.xmlpull.v1.XmlPullParserException;
+
/**
* Single interface which abstracts all access to the Google Maps service.
*
* @author Rodrigo Damazio
*/
-public interface MapsFacade {
+public class MapsFacade {
/**
* Interface for receiving data back from getMapsList.
@@ -23,13 +36,62 @@ public interface MapsFacade {
boolean isPublic);
}
+ private static final String END_ICON_URL =
+ "http://maps.google.com/mapfiles/ms/micons/red-dot.png";
+ private static final String START_ICON_URL =
+ "http://maps.google.com/mapfiles/ms/micons/green-dot.png";
+
+ private final Context context;
+ private final MyMapsGDataWrapper wrapper;
+ private final MyMapsGDataConverter gdataConverter;
+ private final String authToken;
+
+ public MapsFacade(Context context, AuthManager auth) {
+ this.context = context;
+ this.authToken = auth.getAuthToken();
+
+ wrapper = new MyMapsGDataWrapper(context, auth);
+ wrapper.setRetryOnAuthFailure(true);
+
+ try {
+ gdataConverter = new MyMapsGDataConverter();
+ } catch (XmlPullParserException e) {
+ throw new IllegalStateException("Unable to create maps data converter", e);
+ }
+ }
+
+ public static String buildMapUrl(String mapId) {
+ return MapsClient.buildMapUrl(mapId);
+ }
+
/**
* Returns a list of all maps for the current user.
*
* @param callback callback to call for each map returned
* @return true on success, false otherwise
*/
- boolean getMapsList(MapsListCallback callback);
+ public boolean getMapsList(final MapsListCallback callback) {
+ return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() {
+ @Override
+ public void query(MapsClient client) throws IOException, Exception {
+ GDataParser listParser = client.getParserForFeed(
+ MapFeatureEntry.class, MapsClient.getMapsFeed(), authToken);
+ listParser.init();
+ while (listParser.hasMoreData()) {
+ MapFeatureEntry entry =
+ (MapFeatureEntry) listParser.readNextEntry(null);
+ MyMapsMapMetadata metadata =
+ MyMapsGDataConverter.getMapMetadataForEntry(entry);
+ String mapId = MyMapsGDataConverter.getMapidForEntry(entry);
+
+ callback.onReceivedMapListing(
+ mapId, metadata.getTitle(), metadata.getDescription(), metadata.getSearchable());
+ }
+ listParser.close();
+ listParser = null;
+ }
+ });
+ }
/**
* Creates a new map for the current user.
@@ -41,8 +103,34 @@ public interface MapsFacade {
* @param mapIdBuilder builder to append the map ID to
* @return true on success, false otherwise
*/
- boolean createNewMap(String title, String category, String description,
- boolean isPublic, StringBuilder mapIdBuilder);
+ public boolean createNewMap(
+ final String title, final String category, final String description,
+ final boolean isPublic, final StringBuilder mapIdBuilder) {
+ if (mapIdBuilder.length() > 0) {
+ throw new IllegalArgumentException("mapIdBuilder should be empty");
+ }
+
+ return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() {
+ @Override
+ public void query(MapsClient client) throws IOException, Exception {
+ Log.d(MyMapsConstants.TAG, "Creating a new map.");
+ String mapFeed = MapsClient.getMapsFeed();
+ Log.d(MyMapsConstants.TAG, "Map feed is " + mapFeed);
+ MyMapsMapMetadata metaData = new MyMapsMapMetadata();
+ metaData.setTitle(title);
+ metaData.setDescription(description + " - "
+ + category + " - " + context.getString(R.string.new_map_description));
+ metaData.setSearchable(isPublic);
+ Entry entry = MyMapsGDataConverter.getMapEntryForMetadata(metaData);
+ Log.d(MyMapsConstants.TAG, "Title: " + entry.getTitle());
+ Entry map = client.createEntry(mapFeed, authToken, entry);
+
+ String mapId = MapsClient.getMapIdFromMapEntryId(map.getId());
+ mapIdBuilder.append(mapId);
+ Log.d(MyMapsConstants.TAG, "New map id is: " + mapId);
+ }
+ });
+ }
/**
* Uploads a single start or end marker to the given map.
@@ -54,8 +142,92 @@ public interface MapsFacade {
* @param isStart true to add a start marker, false to add an end marker
* @return true on success, false otherwise
*/
- boolean uploadMarker(String mapId, String trackName, String trackDescription,
- Location location, boolean isStart);
+ public boolean uploadMarker(final String mapId, final String trackName,
+ final String trackDescription, final Location loc, final boolean isStart) {
+ return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() {
+ @Override
+ public void query(MapsClient client)
+ throws IOException, Exception {
+ String featureFeed = MapsClient.getFeaturesFeed(mapId);
+ GeoPoint geoPoint = getGeoPoint(loc);
+ insertMarker(client, featureFeed, trackName, trackDescription, geoPoint, isStart);
+ }
+ });
+ }
+
+ /**
+ * Inserts a place mark. Second try if 1st try fails. Will throw exception on
+ * 2nd failure.
+ */
+ private void insertMarker(MapsClient client,
+ String featureFeed,
+ String trackName, String trackDescription,
+ GeoPoint geoPoint,
+ boolean isStart) throws IOException, Exception {
+ MyMapsFeature feature =
+ buildMyMapsPlacemarkFeature(trackName, trackDescription, geoPoint, isStart);
+ Entry entry = gdataConverter.getEntryForFeature(feature);
+ Log.d(MyMapsConstants.TAG, "SendToMyMaps: Creating placemark "
+ + entry.getTitle());
+ try {
+ client.createEntry(featureFeed, authToken, entry);
+ Log.d(MyMapsConstants.TAG, "SendToMyMaps: createEntry success!");
+ } catch (IOException e) {
+ Log.w(MyMapsConstants.TAG,
+ "SendToMyMaps: createEntry 1st try failed. Trying again.");
+ // Retry once (often IOException is thrown on a timeout):
+ client.createEntry(featureFeed, authToken, entry);
+ Log.d(MyMapsConstants.TAG,
+ "SendToMyMaps: createEntry success on 2nd try!");
+ }
+ }
+
+ /**
+ * Builds a placemark MyMapsFeature from a track.
+ *
+ * @param track the track
+ * @param isStart true if it's the start of the track, or false for end
+ * @return a MyMapsFeature
+ */
+ private MyMapsFeature buildMyMapsPlacemarkFeature(
+ String trackName, String trackDescription,
+ GeoPoint geoPoint, boolean isStart) {
+ String iconUrl;
+ if (isStart) {
+ iconUrl = START_ICON_URL;
+ } else {
+ iconUrl = END_ICON_URL;
+ }
+ String title = trackName + " "
+ + (isStart ? context.getString(R.string.start)
+ : context.getString(R.string.end));
+ String description = isStart ? "" : trackDescription;
+ return buildMyMapsPlacemarkFeature(title, description, iconUrl, geoPoint);
+ }
+
+ /**
+ * Builds a MyMapsFeature from a track.
+ *
+ * @param wpt the waypoint
+ * @return a MyMapsFeature
+ */
+ private static MyMapsFeature buildMyMapsPlacemarkFeature(
+ String title, String description, String iconUrl, GeoPoint geoPoint) {
+ MyMapsFeature myMapsFeature = new MyMapsFeature();
+ myMapsFeature.generateAndroidId();
+ myMapsFeature.setType(MyMapsFeature.MARKER);
+ myMapsFeature.setIconUrl(iconUrl);
+ myMapsFeature.setDescription(description);
+ myMapsFeature.addPoint(geoPoint);
+ if (TextUtils.isEmpty(title)) {
+ // Features must have a name (otherwise GData upload may fail):
+ myMapsFeature.setTitle("-");
+ } else {
+ myMapsFeature.setTitle(title);
+ }
+ myMapsFeature.setDescription(description.replaceAll("\n", "
"));
+ return myMapsFeature;
+ }
/**
* Uploads a series of waypoints to the given map.
@@ -64,7 +236,49 @@ public interface MapsFacade {
* @param waypoints the waypoints to upload
* @return true on success, false otherwise
*/
- boolean uploadWaypoints(String mapId, Iterable waypoints);
+ public boolean uploadWaypoints(
+ final String mapId, final Iterable waypoints) {
+ return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() {
+ public void query(MapsClient client) {
+ // TODO(rdamazio): Stream through the waypoints in chunks.
+ // I am leaving the number of waypoints very high which should not be a
+ // problem because we don't try to load them into objects all at the
+ // same time.
+ String featureFeed = MapsClient.getFeaturesFeed(mapId);
+
+ try {
+ for (Waypoint waypoint : waypoints) {
+ MyMapsFeature feature = buildMyMapsPlacemarkFeature(
+ waypoint.getName(), waypoint.getDescription(), waypoint.getIcon(),
+ getGeoPoint(waypoint.getLocation()));
+ Entry entry = gdataConverter.getEntryForFeature(feature);
+
+ Log.d(MyMapsConstants.TAG,
+ "SendToMyMaps: Creating waypoint.");
+ try {
+ client.createEntry(featureFeed, authToken, entry);
+ Log.d(MyMapsConstants.TAG,
+ "SendToMyMaps: createEntry success!");
+ } catch (IOException e) {
+ Log.w(MyMapsConstants.TAG,
+ "SendToMyMaps: createEntry 1st try failed. Retrying.");
+
+ // Retry once (often IOException is thrown on a timeout):
+ client.createEntry(featureFeed, authToken, entry);
+ Log.d(MyMapsConstants.TAG,
+ "SendToMyMaps: createEntry success on 2nd try!");
+ }
+ }
+ } catch (ParseException e) {
+ Log.w(MyMapsConstants.TAG, "ParseException caught.", e);
+ } catch (HttpException e) {
+ Log.w(MyMapsConstants.TAG, "HttpException caught.", e);
+ } catch (IOException e) {
+ Log.w(MyMapsConstants.TAG, "IOException caught.", e);
+ }
+ }
+ });
+ }
/**
* Uploads a series of points to the given map.
@@ -74,12 +288,85 @@ public interface MapsFacade {
* @param locations the locations to upload
* @return true on success, false otherwise
*/
- boolean uploadTrackPoints(String mapId, String trackName,
- Collection locations);
+ public boolean uploadTrackPoints(
+ final String mapId, final String trackName, final Collection locations) {
+ return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() {
+ @Override
+ public void query(MapsClient client)
+ throws IOException, Exception {
+ String featureFeed = MapsClient.getFeaturesFeed(mapId);
+ Log.d(MyMapsConstants.TAG, "Feature feed url: " + featureFeed);
+ uploadTrackPoints(client, featureFeed, trackName, locations);
+ }
+ });
+ }
+
+ private boolean uploadTrackPoints(
+ MapsClient client,
+ String featureFeed,
+ String trackName, Collection locations)
+ throws IOException, Exception {
+ Entry entry = null;
+ int numLocations = locations.size();
+ if (numLocations < 2) {
+ // Need at least two points for a polyline:
+ Log.w(MyMapsConstants.TAG, "Not uploading too few points");
+ return true;
+ }
+
+ // Put the line:
+ entry = gdataConverter.getEntryForFeature(
+ buildMyMapsLineFeature(trackName, locations));
+ Log.d(MyMapsConstants.TAG,
+ "SendToMyMaps: Creating line " + entry.getTitle());
+ try {
+ client.createEntry(featureFeed, authToken, entry);
+ Log.d(MyMapsConstants.TAG, "SendToMyMaps: createEntry success!");
+ } catch (IOException e) {
+ Log.w(MyMapsConstants.TAG,
+ "SendToMyMaps: createEntry 1st try failed. Trying again.");
+ // Retry once (often IOException is thrown on a timeout):
+ client.createEntry(featureFeed, authToken, entry);
+ Log.d(MyMapsConstants.TAG,
+ "SendToMyMaps: createEntry success on 2nd try!");
+ }
+ return true;
+ }
+
+ /**
+ * Builds a MyMapsFeature from a track.
+ *
+ * @param track the track
+ * @return a MyMapsFeature
+ */
+ private static MyMapsFeature buildMyMapsLineFeature(String trackName,
+ Iterable locations) {
+ MyMapsFeature myMapsFeature = new MyMapsFeature();
+ myMapsFeature.generateAndroidId();
+ myMapsFeature.setType(MyMapsFeature.LINE);
+ if (TextUtils.isEmpty(trackName)) {
+ // Features must have a name (otherwise GData upload may fail):
+ myMapsFeature.setTitle("-");
+ } else {
+ myMapsFeature.setTitle(trackName);
+ }
+ myMapsFeature.setColor(0x80FF0000);
+ for (Location loc : locations) {
+ myMapsFeature.addPoint(getGeoPoint(loc));
+ }
+ return myMapsFeature;
+ }
/**
* Cleans up after a series of uploads.
* This closes the connection to Maps and resets retry counters.
*/
- void cleanUp();
+ public void cleanUp() {
+ wrapper.cleanUp();
+ }
+
+ private static GeoPoint getGeoPoint(Location location) {
+ return new GeoPoint((int) (location.getLatitude() * 1E6),
+ (int) (location.getLongitude() * 1E6));
+ }
}
diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsFacadeImpl.java b/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsFacadeImpl.java
deleted file mode 100644
index 011ac04e2..000000000
--- a/MyTracks/src/com/google/android/apps/mytracks/io/mymaps/MapsFacadeImpl.java
+++ /dev/null
@@ -1,338 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-package com.google.android.apps.mytracks.io.mymaps;
-
-import com.google.android.apps.mytracks.content.Waypoint;
-import com.google.android.apps.mytracks.io.AuthManager;
-import com.google.android.maps.GeoPoint;
-import com.google.android.maps.mytracks.R;
-import com.google.wireless.gdata.client.HttpException;
-import com.google.wireless.gdata.data.Entry;
-import com.google.wireless.gdata.parser.GDataParser;
-import com.google.wireless.gdata.parser.ParseException;
-
-import android.content.Context;
-import android.location.Location;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.IOException;
-import java.util.Collection;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-/**
- * Implementation of the Maps access abstraction.
- *
- * @author Rodrigo Damazio
- */
-public class MapsFacadeImpl implements MapsFacade {
- private static final String END_ICON_URL =
- "http://maps.google.com/mapfiles/ms/micons/red-dot.png";
- private static final String START_ICON_URL =
- "http://maps.google.com/mapfiles/ms/micons/green-dot.png";
-
- private final Context context;
- private final MyMapsGDataWrapper wrapper;
- private final MyMapsGDataConverter gdataConverter;
- private final String authToken;
-
- public MapsFacadeImpl(Context context, AuthManager auth) {
- this.context = context;
- this.authToken = auth.getAuthToken();
-
- wrapper = new MyMapsGDataWrapper(context, auth);
- wrapper.setRetryOnAuthFailure(true);
-
- try {
- gdataConverter = new MyMapsGDataConverter();
- } catch (XmlPullParserException e) {
- throw new IllegalStateException("Unable to create maps data converter", e);
- }
- }
-
- public static String buildMapUrl(String mapId) {
- return MapsClient.buildMapUrl(mapId);
- }
-
- @Override
- public boolean getMapsList(final MapsListCallback callback) {
- return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() {
- @Override
- public void query(MapsClient client) throws IOException, Exception {
- GDataParser listParser = client.getParserForFeed(
- MapFeatureEntry.class, MapsClient.getMapsFeed(), authToken);
- listParser.init();
- while (listParser.hasMoreData()) {
- MapFeatureEntry entry =
- (MapFeatureEntry) listParser.readNextEntry(null);
- MyMapsMapMetadata metadata =
- MyMapsGDataConverter.getMapMetadataForEntry(entry);
- String mapId = MyMapsGDataConverter.getMapidForEntry(entry);
-
- callback.onReceivedMapListing(
- mapId, metadata.getTitle(), metadata.getDescription(), metadata.getSearchable());
- }
- listParser.close();
- listParser = null;
- }
- });
- }
-
- /**
- * Creates a new map for the given track.
- *
- * @param track The track that will be uploaded to this map
- * @return True on success
- */
- @Override
- public boolean createNewMap(
- final String title, final String category, final String description,
- final boolean isPublic, final StringBuilder mapIdBuilder) {
- if (mapIdBuilder.length() > 0) {
- throw new IllegalArgumentException("mapIdBuilder should be empty");
- }
-
- return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() {
- @Override
- public void query(MapsClient client) throws IOException, Exception {
- Log.d(MyMapsConstants.TAG, "Creating a new map.");
- String mapFeed = MapsClient.getMapsFeed();
- Log.d(MyMapsConstants.TAG, "Map feed is " + mapFeed);
- MyMapsMapMetadata metaData = new MyMapsMapMetadata();
- metaData.setTitle(title);
- metaData.setDescription(description + " - "
- + category + " - " + context.getString(R.string.new_map_description));
- metaData.setSearchable(isPublic);
- Entry entry = MyMapsGDataConverter.getMapEntryForMetadata(metaData);
- Log.d(MyMapsConstants.TAG, "Title: " + entry.getTitle());
- Entry map = client.createEntry(mapFeed, authToken, entry);
-
- String mapId = MapsClient.getMapIdFromMapEntryId(map.getId());
- mapIdBuilder.append(mapId);
- Log.d(MyMapsConstants.TAG, "New map id is: " + mapId);
- }
- });
- }
-
- @Override
- public boolean uploadMarker(final String mapId, final String trackName,
- final String trackDescription, final Location loc, final boolean isStart) {
- return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() {
- @Override
- public void query(MapsClient client)
- throws IOException, Exception {
- String featureFeed = MapsClient.getFeaturesFeed(mapId);
- GeoPoint geoPoint = getGeoPoint(loc);
- insertMarker(client, featureFeed, trackName, trackDescription, geoPoint, isStart);
- }
- });
- }
-
- /**
- * Inserts a place mark. Second try if 1st try fails. Will throw exception on
- * 2nd failure.
- */
- private void insertMarker(MapsClient client,
- String featureFeed,
- String trackName, String trackDescription,
- GeoPoint geoPoint,
- boolean isStart) throws IOException, Exception {
- MyMapsFeature feature =
- buildMyMapsPlacemarkFeature(trackName, trackDescription, geoPoint, isStart);
- Entry entry = gdataConverter.getEntryForFeature(feature);
- Log.d(MyMapsConstants.TAG, "SendToMyMaps: Creating placemark "
- + entry.getTitle());
- try {
- client.createEntry(featureFeed, authToken, entry);
- Log.d(MyMapsConstants.TAG, "SendToMyMaps: createEntry success!");
- } catch (IOException e) {
- Log.w(MyMapsConstants.TAG,
- "SendToMyMaps: createEntry 1st try failed. Trying again.");
- // Retry once (often IOException is thrown on a timeout):
- client.createEntry(featureFeed, authToken, entry);
- Log.d(MyMapsConstants.TAG,
- "SendToMyMaps: createEntry success on 2nd try!");
- }
- }
-
- /**
- * Builds a placemark MyMapsFeature from a track.
- *
- * @param track the track
- * @param isStart true if it's the start of the track, or false for end
- * @return a MyMapsFeature
- */
- private MyMapsFeature buildMyMapsPlacemarkFeature(
- String trackName, String trackDescription,
- GeoPoint geoPoint, boolean isStart) {
- String iconUrl;
- if (isStart) {
- iconUrl = START_ICON_URL;
- } else {
- iconUrl = END_ICON_URL;
- }
- String title = trackName + " "
- + (isStart ? context.getString(R.string.start)
- : context.getString(R.string.end));
- String description = isStart ? "" : trackDescription;
- return buildMyMapsPlacemarkFeature(title, description, iconUrl, geoPoint);
- }
-
- /**
- * Builds a MyMapsFeature from a track.
- *
- * @param wpt the waypoint
- * @return a MyMapsFeature
- */
- private static MyMapsFeature buildMyMapsPlacemarkFeature(
- String title, String description, String iconUrl, GeoPoint geoPoint) {
- MyMapsFeature myMapsFeature = new MyMapsFeature();
- myMapsFeature.generateAndroidId();
- myMapsFeature.setType(MyMapsFeature.MARKER);
- myMapsFeature.setIconUrl(iconUrl);
- myMapsFeature.setDescription(description);
- myMapsFeature.addPoint(geoPoint);
- if (TextUtils.isEmpty(title)) {
- // Features must have a name (otherwise GData upload may fail):
- myMapsFeature.setTitle("-");
- } else {
- myMapsFeature.setTitle(title);
- }
- myMapsFeature.setDescription(description.replaceAll("\n", "
"));
- return myMapsFeature;
- }
-
- /**
- * Uploads all of the waypoints associated with this track to map.
- *
- * @param track The track to upload waypoints for
- * @return True on success
- */
- @Override
- public boolean uploadWaypoints(
- final String mapId, final Iterable waypoints) {
- return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() {
- public void query(MapsClient client) {
- // TODO(rdamazio): Stream through the waypoints in chunks.
- // I am leaving the number of waypoints very high which should not be a
- // problem because we don't try to load them into objects all at the
- // same time.
- String featureFeed = MapsClient.getFeaturesFeed(mapId);
-
- try {
- for (Waypoint waypoint : waypoints) {
- MyMapsFeature feature = buildMyMapsPlacemarkFeature(
- waypoint.getName(), waypoint.getDescription(), waypoint.getIcon(),
- getGeoPoint(waypoint.getLocation()));
- Entry entry = gdataConverter.getEntryForFeature(feature);
-
- Log.d(MyMapsConstants.TAG,
- "SendToMyMaps: Creating waypoint.");
- try {
- client.createEntry(featureFeed, authToken, entry);
- Log.d(MyMapsConstants.TAG,
- "SendToMyMaps: createEntry success!");
- } catch (IOException e) {
- Log.w(MyMapsConstants.TAG,
- "SendToMyMaps: createEntry 1st try failed. Retrying.");
-
- // Retry once (often IOException is thrown on a timeout):
- client.createEntry(featureFeed, authToken, entry);
- Log.d(MyMapsConstants.TAG,
- "SendToMyMaps: createEntry success on 2nd try!");
- }
- }
- } catch (ParseException e) {
- Log.w(MyMapsConstants.TAG, "ParseException caught.", e);
- } catch (HttpException e) {
- Log.w(MyMapsConstants.TAG, "HttpException caught.", e);
- } catch (IOException e) {
- Log.w(MyMapsConstants.TAG, "IOException caught.", e);
- }
- }
- });
- }
-
- /**
- * Uploads a given list of tracks to Google MyMaps using the maps GData feed.
- */
- @Override
- public boolean uploadTrackPoints(
- final String mapId, final String trackName, final Collection locations) {
- return wrapper.runQuery(new MyMapsGDataWrapper.QueryFunction() {
- @Override
- public void query(MapsClient client)
- throws IOException, Exception {
- String featureFeed = MapsClient.getFeaturesFeed(mapId);
- Log.d(MyMapsConstants.TAG, "Feature feed url: " + featureFeed);
- uploadTrackPoints(client, featureFeed, trackName, locations);
- }
- });
- }
-
- private boolean uploadTrackPoints(
- MapsClient client,
- String featureFeed,
- String trackName, Collection locations)
- throws IOException, Exception {
- Entry entry = null;
- int numLocations = locations.size();
- if (numLocations < 2) {
- // Need at least two points for a polyline:
- Log.w(MyMapsConstants.TAG, "Not uploading too few points");
- return true;
- }
-
- // Put the line:
- entry = gdataConverter.getEntryForFeature(
- buildMyMapsLineFeature(trackName, locations));
- Log.d(MyMapsConstants.TAG,
- "SendToMyMaps: Creating line " + entry.getTitle());
- try {
- client.createEntry(featureFeed, authToken, entry);
- Log.d(MyMapsConstants.TAG, "SendToMyMaps: createEntry success!");
- } catch (IOException e) {
- Log.w(MyMapsConstants.TAG,
- "SendToMyMaps: createEntry 1st try failed. Trying again.");
- // Retry once (often IOException is thrown on a timeout):
- client.createEntry(featureFeed, authToken, entry);
- Log.d(MyMapsConstants.TAG,
- "SendToMyMaps: createEntry success on 2nd try!");
- }
- return true;
- }
-
- /**
- * Builds a MyMapsFeature from a track.
- *
- * @param track the track
- * @return a MyMapsFeature
- */
- private static MyMapsFeature buildMyMapsLineFeature(String trackName,
- Iterable locations) {
- MyMapsFeature myMapsFeature = new MyMapsFeature();
- myMapsFeature.generateAndroidId();
- myMapsFeature.setType(MyMapsFeature.LINE);
- if (TextUtils.isEmpty(trackName)) {
- // Features must have a name (otherwise GData upload may fail):
- myMapsFeature.setTitle("-");
- } else {
- myMapsFeature.setTitle(trackName);
- }
- myMapsFeature.setColor(0x80FF0000);
- for (Location loc : locations) {
- myMapsFeature.addPoint(getGeoPoint(loc));
- }
- return myMapsFeature;
- }
-
- @Override
- public void cleanUp() {
- wrapper.cleanUp();
- }
-
- private static GeoPoint getGeoPoint(Location location) {
- return new GeoPoint((int) (location.getLatitude() * 1E6),
- (int) (location.getLongitude() * 1E6));
- }
-}