From 43cf0659fd209bf0f93b962a69fde32162798bf8 Mon Sep 17 00:00:00 2001 From: Jimmy Shih Date: Mon, 9 Jan 2012 12:50:53 -0800 Subject: [PATCH] Add support to choose the ISO 8601 date format as the default track name. Note using the "yyyy-MM-dd HH:mm" format so it is readable for users. However, the colon, ":", is not a valid FAT32 filename character. So when saving to the SD card, the filename becomes "yyyy-MM-dd HH_mm". --- .../res/values/arrays_do_not_translate.xml | 12 ++++ MyTracks/res/values/do_not_translate.xml | 3 + MyTracks/res/values/keys.xml | 2 +- MyTracks/res/values/strings.xml | 55 +++++++++------ MyTracks/res/xml/preferences.xml | 12 ++-- .../services/DefaultTrackNameFactory.java | 46 ++++++++----- .../services/TrackRecordingService.java | 2 +- .../android/apps/mytracks/util/FileUtils.java | 42 +++++++++++- .../services/DefaultTrackNameFactoryTest.java | 68 ++++++++++--------- .../apps/mytracks/util/FileUtilsTest.java | 36 +++++++++- 10 files changed, 196 insertions(+), 82 deletions(-) diff --git a/MyTracks/res/values/arrays_do_not_translate.xml b/MyTracks/res/values/arrays_do_not_translate.xml index 6c2f997e5..9f4c74502 100644 --- a/MyTracks/res/values/arrays_do_not_translate.xml +++ b/MyTracks/res/values/arrays_do_not_translate.xml @@ -200,6 +200,18 @@ limitations under the License. @string/sensor_type_value_zephyr + + @string/settings_recording_track_name_date_local_option + @string/settings_recording_track_name_date_iso_8601_option + @string/settings_recording_track_name_number_option + + + + @string/settings_recording_track_name_date_local_value + @string/settings_recording_track_name_date_iso_8601_value + @string/settings_recording_track_name_number_value + + @string/waypoint_type_atm @string/waypoint_type_bank diff --git a/MyTracks/res/values/do_not_translate.xml b/MyTracks/res/values/do_not_translate.xml index b208219c1..bf6d60df8 100644 --- a/MyTracks/res/values/do_not_translate.xml +++ b/MyTracks/res/values/do_not_translate.xml @@ -49,6 +49,9 @@ limitations under the License. POLAR SRM_ANT_BRIDGE ZEPHYR + DATE_ISO_8601 + DATE_LOCAL + NUMBER com.google.android.apps.mytracks.END_CURRENT_TRACK android.intent.action.SAVE com.google.android.apps.mytracks.START_NEW_TRACK diff --git a/MyTracks/res/values/keys.xml b/MyTracks/res/values/keys.xml index 08f619ddf..ceb8e6be4 100644 --- a/MyTracks/res/values/keys.xml +++ b/MyTracks/res/values/keys.xml @@ -36,9 +36,9 @@ limitations under the License. sendToFusionTables sendToMaps sensorType + settingsRecordingTrackName shareUrlOnly splitFrequency - timestampTrackName trackColorModeDynamicVariation trackColorModeFixedMediumDisplay diff --git a/MyTracks/res/values/strings.xml b/MyTracks/res/values/strings.xml index 012e85517..88ff0558e 100644 --- a/MyTracks/res/values/strings.xml +++ b/MyTracks/res/values/strings.xml @@ -1677,28 +1677,6 @@ limitations under the License. Screenshot: settings_recording_top.png"> Time/distance after which a new marker will be inserted. - - Use timestamp - - - Use a number as the default track name. - - - Use the track\'s start time as the default track name. - + Track name + + + Date (ISO 8601) + + + Date (local) + + + Number + + + Default track name + - + 127 || character == '-') { + if (Character.isLetterOrDigit(character) || codePoint > 127 || isSpecialFat32(character)) { buffer.appendCodePoint(codePoint); } else { buffer.append("_"); @@ -157,6 +157,42 @@ public class FileUtils { String result = buffer.toString(); return result.replaceAll("_+", "_"); } + + /** + * Returns true if it is a special FAT32 character. + * + * @param character the character + */ + private boolean isSpecialFat32(char character) { + switch (character) { + case '$': + case '%': + case '\'': + case '-': + case '_': + case '@': + case '~': + case '`': + case '!': + case '(': + case ')': + case '{': + case '}': + case '^': + case '#': + case '&': + case '+': + case ',': + case ';': + case '=': + case '[': + case ']': + case ' ': + return true; + default: + return false; + } + } /** * Truncates the name if necessary so the filename path length (directory + diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/DefaultTrackNameFactoryTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/DefaultTrackNameFactoryTest.java index 4789f81f0..7462b6426 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/DefaultTrackNameFactoryTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/services/DefaultTrackNameFactoryTest.java @@ -16,49 +16,55 @@ package com.google.android.apps.mytracks.services; import com.google.android.apps.mytracks.util.StringUtils; +import com.google.android.maps.mytracks.R; -import android.content.Context; import android.test.AndroidTestCase; +import java.text.SimpleDateFormat; +import java.util.Date; + /** * Tests {@link DefaultTrackNameFactory} - * + * * @author Matthew Simmons */ public class DefaultTrackNameFactoryTest extends AndroidTestCase { - /** - * A version of the factory which allows us to supply our own answer as to - * whether a timestamp-based track name should be used. - */ - private static class MockDefaultTrackNameFactory - extends DefaultTrackNameFactory { - private final boolean useTimestamp; - MockDefaultTrackNameFactory(Context context, boolean useTimestamp) { - super(context); - this.useTimestamp = useTimestamp; - } - - @Override - protected boolean useTimestampTrackName() { - return useTimestamp; - } + private static final int TRACK_ID = 1; + private static final long START_TIME = 1288213406000L; + + public void testDefaultTrackName_date_local() { + DefaultTrackNameFactory defaultTrackNameFactory = new DefaultTrackNameFactory(getContext()) { + @Override + String getTrackNameSetting() { + return getContext().getString(R.string.settings_recording_track_name_date_local_value); + } + }; + assertEquals(StringUtils.formatDateTime(getContext(), START_TIME), + defaultTrackNameFactory.getDefaultTrackName(TRACK_ID, START_TIME)); } - - private static final long TIMESTAMP = 1288213406000L; - public void testTimestampTrackName() { - DefaultTrackNameFactory factory = - new MockDefaultTrackNameFactory(getContext(), true); + public void testDefaultTrackName_date_iso_8601() { + DefaultTrackNameFactory defaultTrackNameFactory = new DefaultTrackNameFactory(getContext()) { + @Override + String getTrackNameSetting() { + return getContext().getString(R.string.settings_recording_track_name_date_iso_8601_value); + } + }; + SimpleDateFormat simpleDateFormat = new SimpleDateFormat( + DefaultTrackNameFactory.ISO_8601_FORMAT); + assertEquals(simpleDateFormat.format(new Date(START_TIME)), + defaultTrackNameFactory.getDefaultTrackName(TRACK_ID, START_TIME)); + } + public void testDefaultTrackName_number() { + DefaultTrackNameFactory defaultTrackNameFactory = new DefaultTrackNameFactory(getContext()) { + @Override + String getTrackNameSetting() { + return getContext().getString(R.string.settings_recording_track_name_number_value); + } + }; assertEquals( - StringUtils.formatDateTime(getContext(), TIMESTAMP), factory.newTrackName(1, TIMESTAMP)); - } - - public void testIncrementingTrackName() { - DefaultTrackNameFactory factory = - new MockDefaultTrackNameFactory(getContext(), false); - - assertEquals("Track 1", factory.newTrackName(1, TIMESTAMP)); + "Track " + TRACK_ID, defaultTrackNameFactory.getDefaultTrackName(TRACK_ID, START_TIME)); } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/util/FileUtilsTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/util/FileUtilsTest.java index aa1765f3d..8adda2946 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/util/FileUtilsTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/util/FileUtilsTest.java @@ -62,13 +62,45 @@ public class FileUtilsTest extends TestCase { assertEquals(expectedName, dirName); } + /** + * Tests sanitize filename. + */ public void testSanitizeFileName() { - String name = "Swim\10ming-^across: the/ pacific (ocean).您好-привет_"; - String expected = "Swim_ming-_across_the_pacific_ocean_您好-привет_"; + String name = "Swim\10ming-^across:/the/ pacific (ocean)."; + String expected = "Swim_ming-^across_the_ pacific (ocean)_"; + assertEquals(expected, fileUtils.sanitizeFileName(name)); + } + + /** + * Tests characters in other languages, like Chinese and Russian, are allowed. + */ + public void testSanitizeFileName_i18n() { + String name = "您好-привет"; + String expected = "您好-привет"; + + assertEquals(expected, fileUtils.sanitizeFileName(name)); + } + + /** + * Tests special FAT32 characters are allowed. + */ + public void testSanitizeFileName_special_characters() { + String name = "$%'-_@~`!(){}^#&+,;=[] "; + String expected = "$%'-_@~`!(){}^#&+,;=[] "; assertEquals(expected, fileUtils.sanitizeFileName(name)); } + /** + * Testing collapsing multiple underscores characters. + */ + public void testSanitizeFileName_collapse() { + String name = "hello//there"; + String expected = "hello_there"; + + assertEquals(expected, fileUtils.sanitizeFileName(name)); + } + public void testTruncateFileName() { File directory = new File("/dir1/dir2/"); String suffix = ".gpx";