diff --git a/MyTracks/res/drawable-hdpi/track_run.png b/MyTracks/res/drawable-hdpi/track_run.png index bd3c873e0..8ca86ad23 100755 Binary files a/MyTracks/res/drawable-hdpi/track_run.png and b/MyTracks/res/drawable-hdpi/track_run.png differ diff --git a/MyTracks/res/drawable-mdpi/track_run.png b/MyTracks/res/drawable-mdpi/track_run.png index 61439d736..c84476f43 100755 Binary files a/MyTracks/res/drawable-mdpi/track_run.png and b/MyTracks/res/drawable-mdpi/track_run.png differ diff --git a/MyTracks/res/drawable-xhdpi/track_run.png b/MyTracks/res/drawable-xhdpi/track_run.png index 0a888debb..403d4d11d 100755 Binary files a/MyTracks/res/drawable-xhdpi/track_run.png and b/MyTracks/res/drawable-xhdpi/track_run.png differ diff --git a/MyTracks/res/values/keys.xml b/MyTracks/res/values/keys.xml index d760c71c6..ebf2d632d 100644 --- a/MyTracks/res/values/keys.xml +++ b/MyTracks/res/values/keys.xml @@ -47,9 +47,7 @@ limitations under the License. sendToFusionTables sendToMaps sensorType - showCheckUnitsDialog showConfrimSharingDialog - showWelcomeDialog splitFrequency statsShowCoordinate statsShowElevation diff --git a/MyTracks/src/com/google/android/apps/mytracks/TrackListActivity.java b/MyTracks/src/com/google/android/apps/mytracks/TrackListActivity.java index e3527df64..8261ad858 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/TrackListActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/TrackListActivity.java @@ -278,23 +278,21 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac * Shows start up dialogs. */ public void showStartupDialogs() { - if (!EulaUtils.getEulaValue(this)) { + if (!EulaUtils.getAcceptEula(this)) { Fragment fragment = getSupportFragmentManager() .findFragmentByTag(EulaDialogFragment.EULA_DIALOG_TAG); if (fragment == null) { EulaDialogFragment.newInstance(false) .show(getSupportFragmentManager(), EulaDialogFragment.EULA_DIALOG_TAG); } - } else if (PreferencesUtils.getBoolean( - this, R.string.show_welcome_dialog_key, PreferencesUtils.SHOW_WELCOME_DIALOG_DEFAULT)) { + } else if (EulaUtils.getShowWelcome(this)) { Fragment fragment = getSupportFragmentManager() .findFragmentByTag(WelcomeDialogFragment.WELCOME_DIALOG_TAG); if (fragment == null) { new WelcomeDialogFragment().show( getSupportFragmentManager(), WelcomeDialogFragment.WELCOME_DIALOG_TAG); } - } else if (PreferencesUtils.getBoolean(this, R.string.show_check_units_dialog_key, - PreferencesUtils.SHOW_CHECK_UNITS_DIALOG_DEFAULT)) { + } else if (EulaUtils.getShowCheckUnits(this)) { Fragment fragment = getSupportFragmentManager() .findFragmentByTag(CheckUnitsDialogFragment.CHECK_UNITS_DIALOG_TAG); if (fragment == null) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/fragments/CheckUnitsDialogFragment.java b/MyTracks/src/com/google/android/apps/mytracks/fragments/CheckUnitsDialogFragment.java index 41953a8c8..68fa93ba4 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/fragments/CheckUnitsDialogFragment.java +++ b/MyTracks/src/com/google/android/apps/mytracks/fragments/CheckUnitsDialogFragment.java @@ -17,6 +17,7 @@ package com.google.android.apps.mytracks.fragments; import com.google.android.apps.mytracks.TrackListActivity; +import com.google.android.apps.mytracks.util.EulaUtils; import com.google.android.apps.mytracks.util.PreferencesUtils; import com.google.android.maps.mytracks.R; @@ -69,7 +70,7 @@ public class CheckUnitsDialogFragment extends DialogFragment { * Tasks to perform when done. */ private void onDone() { - PreferencesUtils.setBoolean(getActivity(), R.string.show_check_units_dialog_key, false); + EulaUtils.setShowCheckUnits(getActivity()); TrackListActivity trackListActivity = (TrackListActivity) getActivity(); trackListActivity.showStartupDialogs(); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/fragments/EulaDialogFragment.java b/MyTracks/src/com/google/android/apps/mytracks/fragments/EulaDialogFragment.java index 6c1affb84..65c255193 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/fragments/EulaDialogFragment.java +++ b/MyTracks/src/com/google/android/apps/mytracks/fragments/EulaDialogFragment.java @@ -77,7 +77,7 @@ public class EulaDialogFragment extends DialogFragment { .setPositiveButton(R.string.eula_accept, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - EulaUtils.setEulaValue(getActivity()); + EulaUtils.setAcceptEula(getActivity()); TrackListActivity trackListActivity = (TrackListActivity) getActivity(); trackListActivity.showStartupDialogs(); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/fragments/WelcomeDialogFragment.java b/MyTracks/src/com/google/android/apps/mytracks/fragments/WelcomeDialogFragment.java index c1d72d99e..92bcec677 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/fragments/WelcomeDialogFragment.java +++ b/MyTracks/src/com/google/android/apps/mytracks/fragments/WelcomeDialogFragment.java @@ -17,7 +17,7 @@ package com.google.android.apps.mytracks.fragments; import com.google.android.apps.mytracks.TrackListActivity; -import com.google.android.apps.mytracks.util.PreferencesUtils; +import com.google.android.apps.mytracks.util.EulaUtils; import com.google.android.maps.mytracks.R; import android.app.AlertDialog; @@ -55,7 +55,7 @@ public class WelcomeDialogFragment extends DialogFragment { } private void onDone() { - PreferencesUtils.setBoolean(getActivity(), R.string.show_welcome_dialog_key, false); + EulaUtils.setShowWelcome(getActivity()); TrackListActivity trackListActivity = (TrackListActivity) getActivity(); trackListActivity.showStartupDialogs(); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxImporter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxImporter.java index 7fe573a8d..06f155df2 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxImporter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/GpxImporter.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; @@ -42,19 +43,15 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** - * Imports GPX XML files to the my tracks provider. - * - * TODO: Show progress indication to the user. - * + * Imports GPX file to My Tracks. + * * @author Leif Hendrik Wilden * @author Steffen Horlacher * @author Rodrigo Damazio */ public class GpxImporter extends DefaultHandler { - /* - * GPX-XML tag names and attributes. - */ + // GPX tag names and attributes. private static final String TAG_TRACK = "trk"; private static final String TAG_TRACK_POINT = "trkpt"; private static final Object TAG_TRACK_SEGMENT = "trkseg"; @@ -66,20 +63,21 @@ public class GpxImporter extends DefaultHandler { private static final String ATT_LON = "lon"; /** - * The maximum number of locations to buffer for bulk-insertion into the database. + * The maximum number of locations to buffer for bulk-insertion into the + * database. */ private static final int MAX_BUFFERED_LOCATIONS = 512; /** - * Utilities for accessing the contnet provider. + * Utilities for accessing the content provider. */ - private final MyTracksProviderUtils providerUtils; + private final MyTracksProviderUtils myTracksProviderUtils; /** * List of track ids written in the database. Only contains successfully * written tracks. */ - private final List tracksWritten; + private final List tracksIds; /** * Contains the current elements content. @@ -87,15 +85,20 @@ public class GpxImporter extends DefaultHandler { private String content; /** - * Currently reading location. + * Currently location. */ private Location location; /** - * Previous location, required for calculations. + * Last location. */ private Location lastLocation; - + + /** + * Last segment location. + */ + private Location lastSegmentLocation; + /** * Currently reading track. */ @@ -104,7 +107,7 @@ public class GpxImporter extends DefaultHandler { /** * Statistics builder for the current track. */ - private TripStatisticsBuilder statsBuilder; + private TripStatisticsBuilder tripStatisticsBuilder; /** * Buffer of locations to be bulk-inserted into the database. @@ -115,82 +118,79 @@ public class GpxImporter extends DefaultHandler { * Number of locations buffered to be inserted into the database. */ private int numBufferedPointInserts = 0; - + /** * Number of locations already processed. */ - private int numberOfLocations; + private int numberOfLocations = 0; /** * Number of segments already processed. */ - private int numberOfSegments; + private int numberOfSegments = 0; /** * Used to identify if a track was written to the database but not yet * finished successfully. */ - private boolean isCurrentTrackRollbackable; + private boolean isCurrentTrackRollbackable = false; /** - * Flag to indicate if we're inside a track's xml element. - * Some sub elements like name may be used in other parts of the gpx file, - * and we use this to ignore them. + * Flag to indicate if we're inside a track's xml element. Some sub elements + * like name may be used in other parts of the GPX file, and we use this to + * ignore them. */ - private boolean isInTrackElement; + private boolean isInTrackElement = false; /** - * Counter to find out which child level of track we are processing. + * Counter to find out which child level of the track we are processing. */ - private int trackChildDepth; + private int trackChildDepth = 0; /** - * SAX-Locator to get current line information. + * SAX locator to get the current line information. */ private Locator locator; - private Location lastSegmentLocation; /** * Reads GPS tracks from a GPX file and writes tracks and their coordinates to * the database. * - * @param is a input steam with gpx-xml data - * @return long[] array of track ids written in the database - * @throws SAXException a parsing error - * @throws ParserConfigurationException internal error - * @throws IOException a file reading problem + * @param inputStream an input stream for the GPX file + * @param myTracksProviderUtils my tracks provider utils + * @return long[] array of track ids written to the database. */ - public static long[] importGPXFile(final InputStream is, - final MyTracksProviderUtils providerUtils) + public static long[] importGPXFile( + final InputStream inputStream, final MyTracksProviderUtils myTracksProviderUtils) throws ParserConfigurationException, SAXException, IOException { - SAXParserFactory factory = SAXParserFactory.newInstance(); - GpxImporter handler = new GpxImporter(providerUtils); - SAXParser parser = factory.newSAXParser(); - long[] trackIds = null; + SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + SAXParser saxParser = saxParserFactory.newSAXParser(); + GpxImporter gpxImporter = new GpxImporter(myTracksProviderUtils); + long[] trackIds = new long[0]; try { long start = System.currentTimeMillis(); - parser.parse(is, handler); + saxParser.parse(inputStream, gpxImporter); long end = System.currentTimeMillis(); Log.d(Constants.TAG, "Total import time: " + (end - start) + "ms"); - trackIds = handler.getImportedTrackIds(); + trackIds = gpxImporter.getImportedTrackIds(); + if (trackIds.length == 0) { + throw new IOException("No track imported."); + } } finally { - // delete track if not finished - handler.rollbackUnfinishedTracks(); + // Delete track if not finished + gpxImporter.rollbackUnfinishedTracks(); } return trackIds; } - /** - * Constructor, requires providerUtils for writing tracks the database. - */ - public GpxImporter(MyTracksProviderUtils providerUtils) { - this.providerUtils = providerUtils; - tracksWritten = new ArrayList(); + public GpxImporter(MyTracksProviderUtils myTracksProviderUtils) { + this.myTracksProviderUtils = myTracksProviderUtils; + tracksIds = new ArrayList(); } @Override @@ -199,16 +199,18 @@ public class GpxImporter extends DefaultHandler { if (content == null) { content = newContent; } else { - // In 99% of the cases, a single call to this method will be made for each - // sequence of characters we're interested in, so we'll rarely be - // concatenating strings, thus not justifying the use of a StringBuilder. + /* + * In 99% of the cases, a single call to this method will be made for each + * sequence of characters we're interested in, so we'll rarely be + * concatenating strings, thus not justifying the use of a StringBuilder. + */ content += newContent; } } @Override - public void startElement(String uri, String localName, String name, - Attributes attributes) throws SAXException { + public void startElement(String uri, String localName, String name, Attributes attributes) + throws SAXException { if (isInTrackElement) { trackChildDepth++; if (localName.equals(TAG_TRACK_POINT)) { @@ -216,8 +218,7 @@ public class GpxImporter extends DefaultHandler { } else if (localName.equals(TAG_TRACK_SEGMENT)) { onTrackSegmentElementStart(); } else if (localName.equals(TAG_TRACK)) { - String msg = createErrorMessage("Invalid GPX-XML detected"); - throw new SAXException(msg); + throw new SAXException(createErrorMessage("Invalid GPX detected.")); } } else if (localName.equals(TAG_TRACK)) { isInTrackElement = true; @@ -227,8 +228,7 @@ public class GpxImporter extends DefaultHandler { } @Override - public void endElement(String uri, String localName, String name) - throws SAXException { + public void endElement(String uri, String localName, String name) throws SAXException { if (!isInTrackElement) { content = null; return; @@ -270,33 +270,58 @@ public class GpxImporter extends DefaultHandler { } /** - * Create a new Track object and insert empty track in database. Track will be - * updated with missing values later. + * Rolls back last track if possible. + */ + public void rollbackUnfinishedTracks() { + if (isCurrentTrackRollbackable) { + myTracksProviderUtils.deleteTrack(track.getId()); + isCurrentTrackRollbackable = false; + } + } + + /** + * On track element start. */ private void onTrackElementStart() { track = new Track(); numberOfLocations = 0; - Uri trackUri = providerUtils.insertTrack(track); - long trackId = Long.parseLong(trackUri.getLastPathSegment()); + Uri uri = myTracksProviderUtils.insertTrack(track); + long trackId = Long.parseLong(uri.getLastPathSegment()); track.setId(trackId); isCurrentTrackRollbackable = true; } - private void onDescriptionElementEnd() { - track.setDescription(content.toString().trim()); - } + /** + * On track element end. + */ + private void onTrackElementEnd() { + if (lastLocation != null) { + flushPoints(); - private void onNameElementEnd() { - track.setName(content.toString().trim()); + // Calculate statistics for the imported track + tripStatisticsBuilder.pauseAt(lastLocation.getTime()); + track.setStopId(getLastPointId()); + } else { + tripStatisticsBuilder = new TripStatisticsBuilder(0); + tripStatisticsBuilder.pauseAt(0); + } + track.setTripStatistics(tripStatisticsBuilder.getStatistics()); + track.setNumberOfPoints(numberOfLocations); + myTracksProviderUtils.updateTrack(track); + tracksIds.add(track.getId()); + isCurrentTrackRollbackable = false; + lastSegmentLocation = null; + lastLocation = null; + tripStatisticsBuilder = null; } /** - * Track segment started. + * On track segment start. */ private void onTrackSegmentElementStart() { if (numberOfSegments > 0) { - // Add a segment separator: + // Add a segment separator location = new Location(LocationManager.GPS_PROVIDER); location.setLatitude(100.0); location.setLongitude(100.0); @@ -304,73 +329,61 @@ public class GpxImporter extends DefaultHandler { if (lastLocation != null) { location.setTime(lastLocation.getTime()); } - insertTrackPoint(location); + insertPoint(location); lastLocation = location; lastSegmentLocation = null; location = null; } - numberOfSegments++; } /** - * Reads trackpoint attributes and assigns them to the current location. - * - * @param attributes xml attributes + * On track segment element end. + */ + private void onTrackSegmentElementEnd() { + // Nothing to be done + } + + /** + * On track point element start. + * + * @param attributes the attributes */ private void onTrackPointElementStart(Attributes attributes) throws SAXException { if (location != null) { - String errorMsg = createErrorMessage("Found a track point inside another one."); - throw new SAXException(errorMsg); + throw new SAXException(createErrorMessage("Found a track point inside another one.")); } - - location = createLocationFromAttributes(attributes); - } - - /** - * Creates and returns a location with the position parsed from the given - * attributes. - * - * @param attributes the attributes to parse - * @return the created location - * @throws SAXException if the attributes cannot be parsed - */ - private Location createLocationFromAttributes(Attributes attributes) throws SAXException { String latitude = attributes.getValue(ATT_LAT); String longitude = attributes.getValue(ATT_LON); - + if (latitude == null || longitude == null) { - throw new SAXException(createErrorMessage("Point with no longitude or latitude")); + throw new SAXException(createErrorMessage("Point with no longitude or latitude.")); } - - // create new location and set attributes - Location loc = new Location(LocationManager.GPS_PROVIDER); + + Location newLocation = new Location(LocationManager.GPS_PROVIDER); try { - loc.setLatitude(Double.parseDouble(latitude)); - loc.setLongitude(Double.parseDouble(longitude)); + newLocation.setLatitude(Double.parseDouble(latitude)); + newLocation.setLongitude(Double.parseDouble(longitude)); } catch (NumberFormatException e) { - String msg = createErrorMessage( - "Unable to parse lat/long: " + latitude + "/" + longitude); - throw new SAXException(msg, e); + throw new SAXException(createErrorMessage( + "Unable to parse latitude/longitude: " + latitude + "/" + longitude), e); } - return loc; + location = newLocation; } /** - * Track point finished, write in database. - * - * @throws SAXException - thrown if track point is invalid + * On track point element end. */ private void onTrackPointElementEnd() throws SAXException { if (LocationUtils.isValidLocation(location)) { - if (statsBuilder == null) { + if (tripStatisticsBuilder == null) { // first point did not have a time, start stats builder without it - statsBuilder = new TripStatisticsBuilder(0); + tripStatisticsBuilder = new TripStatisticsBuilder(0); } - statsBuilder.addLocation(location, location.getTime()); + tripStatisticsBuilder.addLocation(location, location.getTime()); // insert in db - insertTrackPoint(location); + insertPoint(location); // first track point? if (lastLocation == null && numberOfSegments == 1) { @@ -382,78 +395,31 @@ public class GpxImporter extends DefaultHandler { location = null; } else { // invalid location - abort import - String msg = createErrorMessage("Invalid location detected: " + location); - throw new SAXException(msg); - } - } - - private void insertTrackPoint(Location loc) { - bufferedPointInserts[numBufferedPointInserts] = loc; - numBufferedPointInserts++; - numberOfLocations++; - - if (numBufferedPointInserts >= MAX_BUFFERED_LOCATIONS) { - flushPointInserts(); - } - } - - private void flushPointInserts() { - if (numBufferedPointInserts <= 0) { return; } - - providerUtils.bulkInsertTrackPoints(bufferedPointInserts, numBufferedPointInserts, track.getId()); - numBufferedPointInserts = 0; - } - - /** - * Track segment finished. - */ - private void onTrackSegmentElementEnd() { - // Nothing to be done - } - - /** - * Track finished - update in database. - */ - private void onTrackElementEnd() { - if (lastLocation != null) { - flushPointInserts(); - - // Calculate statistics for the imported track and update - statsBuilder.pauseAt(lastLocation.getTime()); - track.setStopId(getLastPointId()); - track.setNumberOfPoints(numberOfLocations); - track.setTripStatistics(statsBuilder.getStatistics()); - providerUtils.updateTrack(track); - tracksWritten.add(track.getId()); - isCurrentTrackRollbackable = false; - lastSegmentLocation = null; - lastLocation = null; - statsBuilder = null; - } else { - // track contains no track points makes no real - // sense to import it as we have no location - // information -> roll back - rollbackUnfinishedTracks(); + throw new SAXException(createErrorMessage("Invalid location detected: " + location)); } } /** - * Setting time and doing additional calculations as this is the last value - * required. Also sets the start time for track and statistics as there is no - * start time in the track root element. - * - * @throws SAXException on parsing errors + * On time element end. Sets location time and doing additional calculations + * as this is the last value required for the location. Also sets the start time + * for the trip statistics builder as there is no start time in the track root + * element. */ private void onTimeElementEnd() throws SAXException { - if (location == null) { return; } + if (location == null) { + return; + } + if (content == null) { + return; + } + // Parse the time long time; try { time = StringUtils.getTime(content.trim()); } catch (IllegalArgumentException e) { - String msg = createErrorMessage("Unable to parse time: " + content); - throw new SAXException(msg, e); + throw new SAXException(createErrorMessage("Unable to parse time: " + content), e); } // Calculate derived attributes from previous point @@ -465,11 +431,12 @@ public class GpxImporter extends DefaultHandler { Log.w(Constants.TAG, "Found negative time change."); } else { - // We don't have a speed and bearing in GPX, make something up from - // the last two points. - // TODO GPS points tend to have some inherent imprecision, - // speed and bearing will likely be off, so the statistics for things like - // max speed will also be off. + /* + * We don't have a speed and bearing in GPX, make something up from the + * last two points. GPS points tend to have some inherent imprecision, + * speed and bearing will likely be off, so the statistics for things + * like max speed will also be off. + */ float speed = location.distanceTo(lastLocation) * 1000.0f / timeDifference; location.setSpeed(speed); location.setBearing(lastSegmentLocation.bearingTo(location)); @@ -480,69 +447,96 @@ public class GpxImporter extends DefaultHandler { location.setTime(time); // initialize start time with time of first track point - if (statsBuilder == null) { - statsBuilder = new TripStatisticsBuilder(time); + if (tripStatisticsBuilder == null) { + tripStatisticsBuilder = new TripStatisticsBuilder(time); } } + /** + * On altitude element end. + */ private void onAltitudeElementEnd() throws SAXException { - if (location != null) { + if (location != null && content != null) { try { location.setAltitude(Double.parseDouble(content)); } catch (NumberFormatException e) { - String msg = createErrorMessage("Unable to parse altitude: " + content); - throw new SAXException(msg, e); + throw new SAXException(createErrorMessage("Unable to parse altitude: " + content), e); } } } /** - * Deletes the last track if it was not completely imported. + * On name element end. */ - public void rollbackUnfinishedTracks() { - if (isCurrentTrackRollbackable) { - providerUtils.deleteTrack(track.getId()); - isCurrentTrackRollbackable = false; + private void onNameElementEnd() { + if (content != null) { + track.setName(content.toString().trim()); } } /** - * Get all track ids of the tracks created by this importer run. + * On description element end. + */ + private void onDescriptionElementEnd() { + if (content != null) { + track.setDescription(content.toString().trim()); + } + } + + /** + * Inserts a point. * - * @return array of track ids + * @param newLocation the location + */ + private void insertPoint(Location newLocation) { + bufferedPointInserts[numBufferedPointInserts] = newLocation; + numBufferedPointInserts++; + numberOfLocations++; + + if (numBufferedPointInserts >= MAX_BUFFERED_LOCATIONS) { + flushPoints(); + } + } + + /** + * Flushes the points to the database. + */ + private void flushPoints() { + if (numBufferedPointInserts <= 0) { + return; + } + myTracksProviderUtils.bulkInsertTrackPoints( + bufferedPointInserts, numBufferedPointInserts, track.getId()); + numBufferedPointInserts = 0; + } + + /** + * Gets the imported track ids. + * */ private long[] getImportedTrackIds() { - // Convert from java.lang.Long for convenience - long[] result = new long[tracksWritten.size()]; + long[] result = new long[tracksIds.size()]; for (int i = 0; i < result.length; i++) { - result[i] = tracksWritten.get(i); + result[i] = tracksIds.get(i); } return result; } /** - * Returns the ID of the last point inserted into the database. + * Gets the last point id inserted into the database. */ private long getLastPointId() { - flushPointInserts(); - - return providerUtils.getLastLocationId(track.getId()); + flushPoints(); + return myTracksProviderUtils.getLastLocationId(track.getId()); } /** - * Builds a parsing error message with current line information. + * Creates an error message. * - * @param details details about the error, will be appended - * @return error message string with current line information + * @param message the message */ - private String createErrorMessage(String details) { - StringBuffer msg = new StringBuffer(); - msg.append("Parsing error at line: "); - msg.append(locator.getLineNumber()); - msg.append(" column: "); - msg.append(locator.getColumnNumber()); - msg.append(". "); - msg.append(details); - return msg.toString(); + private String createErrorMessage(String message) { + return String.format(Locale.US, "Parsing error at line: %d column: %d. %s", + locator.getLineNumber(), locator.getColumnNumber(), message); } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java index 8fbf20975..e7fe59768 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java @@ -318,7 +318,9 @@ class TrackWriterImpl implements TrackWriter { locationFactory); try { if (!it.hasNext()) { - Log.w(Constants.TAG, "Unable to get any points to write"); + // Writes an empty track + writer.writeBeginTrack(null); + writer.writeEndTrack(null); return; } int pointNumber = 0; diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/EulaUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/EulaUtils.java index 8c683a3ff..29269a459 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/EulaUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/EulaUtils.java @@ -29,21 +29,47 @@ public class EulaUtils { private static final String EULA_PREFERENCE_FILE = "eula"; // Accepting Google mobile terms of service - private static final String EULA_PREFERENCE_KEY = "eula.google_mobile_tos_accepted"; - + private static final String ACCEPT_EULA_PREFERENCE_KEY = "eula.google_mobile_tos_accepted"; + private static final String SHOW_WELCOME_PREFERENCE_KEY = "showWelcome"; + private static final String SHOW_CHECK_UNITS_PREFERENCE_KEY = "showCheckUnits"; + private EulaUtils() {} - public static boolean getEulaValue(Context context) { - SharedPreferences sharedPreferences = context.getSharedPreferences( - EULA_PREFERENCE_FILE, Context.MODE_PRIVATE); - return sharedPreferences.getBoolean(EULA_PREFERENCE_KEY, false); + public static boolean getAcceptEula(Context context) { + return getValue(context, ACCEPT_EULA_PREFERENCE_KEY, false); } - public static void setEulaValue(Context context) { + public static void setAcceptEula(Context context) { + setValue(context, ACCEPT_EULA_PREFERENCE_KEY, true); + } + + public static boolean getShowWelcome(Context context) { + return getValue(context, SHOW_WELCOME_PREFERENCE_KEY, true); + } + + public static void setShowWelcome(Context context) { + setValue(context, SHOW_WELCOME_PREFERENCE_KEY, false); + } + + public static boolean getShowCheckUnits(Context context) { + return getValue(context, SHOW_CHECK_UNITS_PREFERENCE_KEY, true); + } + + public static void setShowCheckUnits(Context context) { + setValue(context, SHOW_CHECK_UNITS_PREFERENCE_KEY, false); + } + + private static boolean getValue(Context context, String key, boolean defaultValue) { + SharedPreferences sharedPreferences = context.getSharedPreferences( + EULA_PREFERENCE_FILE, Context.MODE_PRIVATE); + return sharedPreferences.getBoolean(key, defaultValue); + } + + private static void setValue(Context context, String key, boolean value) { SharedPreferences sharedPreferences = context.getSharedPreferences( EULA_PREFERENCE_FILE, Context.MODE_PRIVATE); Editor editor = sharedPreferences.edit(); - editor.putBoolean(EULA_PREFERENCE_KEY, true); + editor.putBoolean(key, value); ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor); } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/PreferencesUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/PreferencesUtils.java index dc018bd5f..f13535c4f 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/PreferencesUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/PreferencesUtils.java @@ -73,9 +73,7 @@ public class PreferencesUtils { public static final boolean SEND_TO_DOCS_DEFAULT = true; public static final boolean SEND_TO_FUSION_TABLES_DEFAULT = true; public static final boolean SEND_TO_MAPS_DEFAULT = true; - public static final boolean SHOW_CHECK_UNITS_DIALOG_DEFAULT = true; public static final boolean SHOW_CONFIRM_SHARING_DIALOG_DEFAULT = true; - public static final boolean SHOW_WELCOME_DIALOG_DEFAULT = true; public static final int SPLIT_FREQUENCY_DEFAULT = 0; public static final boolean STATS_SHOW_COORDINATE_DEFAULT = false; diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java index 90684bc04..467221475 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java @@ -225,6 +225,8 @@ public class TrackWriterTest extends AndroidTestCase { // Set expected mock behavior formatWriter.writeHeader(); + formatWriter.writeBeginTrack(null); + formatWriter.writeEndTrack(null); formatWriter.writeFooter(); formatWriter.close(); diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java index d20d5e96b..8c8f02205 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java @@ -67,6 +67,7 @@ public class SendFusionTablesUtilsTest extends TestCase { */ public void testGetMapUrl_valid_track() { Track track = new Track(); + track.setNumberOfPoints(2); TripStatistics stats = new TripStatistics(); stats.setBounds((int) 100.E6, (int) 10.E6, (int) 50.E6, (int) 5.E6); track.setTripStatistics(stats);