Introduced ActivityType is now non-localized (i.e., English) value
This commit is contained in:
Dennis Guse
2023-10-10 20:10:16 +02:00
committed by GitHub
25 changed files with 316 additions and 254 deletions
+9
View File
@@ -51,4 +51,13 @@
</xsd:documentation> </xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:element> </xsd:element>
<xsd:element name="typeTranslated"
type="xsd:string">
<xsd:annotation>
<xsd:documentation xml:lang="en">
User-defined translation of GPX's <![CDATA[<type>]]>.
Only used in GPX.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:schema> </xsd:schema>
@@ -47,7 +47,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.content.data.TestDataUtil; import de.dennisguse.opentracks.content.data.TestDataUtil;
import de.dennisguse.opentracks.content.data.TestSensorDataUtil; import de.dennisguse.opentracks.content.data.TestSensorDataUtil;
@@ -860,7 +859,7 @@ public class CustomContentProviderUtilsTest {
List<TrackPoint.Id> trackpointIds = track.second.stream() List<TrackPoint.Id> trackpointIds = track.second.stream()
.map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.getId()))) .map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.getId())))
.map(TrackPoint.Id::new).collect(Collectors.toList()); .map(TrackPoint.Id::new).toList();
// when // when
try (Cursor cursor = contentProviderUtils.getTrackPointCursor(trackId, trackpointIds.get(8))) { try (Cursor cursor = contentProviderUtils.getTrackPointCursor(trackId, trackpointIds.get(8))) {
@@ -878,7 +877,7 @@ public class CustomContentProviderUtilsTest {
List<TrackPoint.Id> trackpointIds = track.second.stream() List<TrackPoint.Id> trackpointIds = track.second.stream()
.map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.getId()))) .map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.getId())))
.map(TrackPoint.Id::new).collect(Collectors.toList()); .map(TrackPoint.Id::new).toList();
TrackPoint.Id startTrackPointId = trackpointIds.get(0); TrackPoint.Id startTrackPointId = trackpointIds.get(0);
@@ -309,10 +309,10 @@ public class ExportImportTest {
// 1. track // 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals(track.getActivityType(), importedTrack.getActivityType());
assertEquals(track.getActivityTypeLocalized(), importedTrack.getActivityTypeLocalized()); assertEquals(track.getActivityTypeLocalized(), importedTrack.getActivityTypeLocalized());
assertEquals(track.getDescription(), importedTrack.getDescription()); assertEquals(track.getDescription(), importedTrack.getDescription());
assertEquals(track.getName(), importedTrack.getName()); assertEquals(track.getName(), importedTrack.getName());
assertEquals(track.getActivityType(), importedTrack.getActivityType());
// 2. trackpoints // 2. trackpoints
TrackPointAssert a = new TrackPointAssert(); TrackPointAssert a = new TrackPointAssert();
@@ -380,13 +380,11 @@ public class ExportImportTest {
// 1. track // 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals(track.getActivityType(), importedTrack.getActivityType());
assertEquals(track.getActivityTypeLocalized(), importedTrack.getActivityTypeLocalized()); assertEquals(track.getActivityTypeLocalized(), importedTrack.getActivityTypeLocalized());
assertEquals(track.getDescription(), importedTrack.getDescription()); assertEquals(track.getDescription(), importedTrack.getDescription());
assertEquals(track.getName(), importedTrack.getName()); assertEquals(track.getName(), importedTrack.getName());
//TODO exporting and importing a track icon is not yet supported by GpxTrackWriter.
//assertEquals(track.getIcon(), importedTrack.getIcon());
// 2. trackpoints // 2. trackpoints
// The GPX exporter does not support exporting TrackPoints without lat/lng. // The GPX exporter does not support exporting TrackPoints without lat/lng.
// Therefore, the track segmentation is changes. // Therefore, the track segmentation is changes.
@@ -80,6 +80,7 @@ public class GPXTrackImporterTest {
// 2. track // 2. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
assertEquals("the category", importedTrack.getActivityTypeLocalized()); assertEquals("the category", importedTrack.getActivityTypeLocalized());
assertEquals("the description", importedTrack.getDescription()); assertEquals("the description", importedTrack.getDescription());
assertEquals("2021-01-07 22:51", importedTrack.getName()); assertEquals("2021-01-07 22:51", importedTrack.getName());
+2 -1
View File
@@ -21,10 +21,11 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/
<trk> <trk>
<name><![CDATA[2021-01-07 22:51]]></name> <name><![CDATA[2021-01-07 22:51]]></name>
<desc><![CDATA[the description]]></desc> <desc><![CDATA[the description]]></desc>
<type><![CDATA[the category]]></type> <type><![CDATA[unknown]]></type>
<extensions> <extensions>
<topografix:color>c0c0c0</topografix:color> <topografix:color>c0c0c0</topografix:color>
<opentracks:trackid>7002101e-4198-4613-8c24-544e01ca3981</opentracks:trackid> <opentracks:trackid>7002101e-4198-4613-8c24-544e01ca3981</opentracks:trackid>
<opentracks:typeTranslated><![CDATA[unknown]]></opentracks:typeTranslated>
<gpxtrkx:TrackStatsExtension> <gpxtrkx:TrackStatsExtension>
<gpxtrkx:Distance>0.0</gpxtrkx:Distance> <gpxtrkx:Distance>0.0</gpxtrkx:Distance>
<gpxtrkx:TimerTime>0</gpxtrkx:TimerTime> <gpxtrkx:TimerTime>0</gpxtrkx:TimerTime>
@@ -101,6 +101,7 @@ public class ContentProviderUtils {
int uuidIndex = cursor.getColumnIndexOrThrow(TracksColumns.UUID); int uuidIndex = cursor.getColumnIndexOrThrow(TracksColumns.UUID);
int nameIndex = cursor.getColumnIndexOrThrow(TracksColumns.NAME); int nameIndex = cursor.getColumnIndexOrThrow(TracksColumns.NAME);
int descriptionIndex = cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION); int descriptionIndex = cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION);
int activityTypeIndex = cursor.getColumnIndexOrThrow(TracksColumns.ACTIVITY_TYPE);
int activityTypeLocalizedIndex = cursor.getColumnIndexOrThrow(TracksColumns.ACTIVITY_TYPE_LOCALIZED); int activityTypeLocalizedIndex = cursor.getColumnIndexOrThrow(TracksColumns.ACTIVITY_TYPE_LOCALIZED);
int startTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME); int startTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME);
int startTimeOffsetIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME_OFFSET); int startTimeOffsetIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME_OFFSET);
@@ -113,7 +114,6 @@ public class ContentProviderUtils {
int maxAltitudeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAX_ALTITUDE); int maxAltitudeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAX_ALTITUDE);
int altitudeGainIndex = cursor.getColumnIndexOrThrow(TracksColumns.ALTITUDE_GAIN); int altitudeGainIndex = cursor.getColumnIndexOrThrow(TracksColumns.ALTITUDE_GAIN);
int altitudeLossIndex = cursor.getColumnIndexOrThrow(TracksColumns.ALTITUDE_LOSS); int altitudeLossIndex = cursor.getColumnIndexOrThrow(TracksColumns.ALTITUDE_LOSS);
int iconIndex = cursor.getColumnIndexOrThrow(TracksColumns.ICON);
Track track = new Track(ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex))); Track track = new Track(ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex)));
TrackStatistics trackStatistics = track.getTrackStatistics(); TrackStatistics trackStatistics = track.getTrackStatistics();
@@ -129,6 +129,9 @@ public class ContentProviderUtils {
if (!cursor.isNull(descriptionIndex)) { if (!cursor.isNull(descriptionIndex)) {
track.setDescription(cursor.getString(descriptionIndex)); track.setDescription(cursor.getString(descriptionIndex));
} }
if (!cursor.isNull(activityTypeIndex)) {
track.setActivityType(ActivityType.findBy(cursor.getString(activityTypeIndex)));
}
if (!cursor.isNull(activityTypeLocalizedIndex)) { if (!cursor.isNull(activityTypeLocalizedIndex)) {
track.setActivityTypeLocalized(cursor.getString(activityTypeLocalizedIndex)); track.setActivityTypeLocalized(cursor.getString(activityTypeLocalizedIndex));
} }
@@ -163,9 +166,7 @@ public class ContentProviderUtils {
if (!cursor.isNull(altitudeLossIndex)) { if (!cursor.isNull(altitudeLossIndex)) {
trackStatistics.setTotalAltitudeLoss(cursor.getFloat(altitudeLossIndex)); trackStatistics.setTotalAltitudeLoss(cursor.getFloat(altitudeLossIndex));
} }
if (!cursor.isNull(iconIndex)) {
track.setActivityType(ActivityType.findBy(cursor.getString(iconIndex)));
}
return track; return track;
} }
@@ -230,13 +231,18 @@ public class ContentProviderUtils {
public Cursor searchTracks(String searchQuery) { public Cursor searchTracks(String searchQuery) {
// Needed, because MARKER_COUNT is a virtual column and has to be explicitly requested. // Needed, because MARKER_COUNT is a virtual column and has to be explicitly requested.
final String[] PROJECTION = new String[]{TracksColumns._ID, TracksColumns.UUID, TracksColumns.NAME, // Used only be TrackListAdapter
TracksColumns.DESCRIPTION, TracksColumns.ACTIVITY_TYPE_LOCALIZED, TracksColumns.STARTTIME, final String[] PROJECTION = new String[]{
TracksColumns.STARTTIME_OFFSET, TracksColumns.STOPTIME, TracksColumns.MARKER_COUNT, TracksColumns._ID,
TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.MOVINGTIME, TracksColumns.NAME,
TracksColumns.AVGSPEED, TracksColumns.AVGMOVINGSPEED, TracksColumns.MAXSPEED, TracksColumns.DESCRIPTION, //TODO Needed?
TracksColumns.MIN_ALTITUDE, TracksColumns.MAX_ALTITUDE, TracksColumns.ALTITUDE_GAIN, TracksColumns.ACTIVITY_TYPE,
TracksColumns.ALTITUDE_LOSS, TracksColumns.ICON TracksColumns.ACTIVITY_TYPE_LOCALIZED,
TracksColumns.STARTTIME,
TracksColumns.STARTTIME_OFFSET,
TracksColumns.TOTALDISTANCE,
TracksColumns.TOTALTIME,
TracksColumns.MARKER_COUNT,
}; };
String selection = null; String selection = null;
@@ -316,6 +322,7 @@ public class ContentProviderUtils {
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid())); values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid()));
values.put(TracksColumns.NAME, track.getName()); values.put(TracksColumns.NAME, track.getName());
values.put(TracksColumns.DESCRIPTION, track.getDescription()); values.put(TracksColumns.DESCRIPTION, track.getDescription());
values.put(TracksColumns.ACTIVITY_TYPE, track.getActivityType() != null ? track.getActivityType().getId() : null);
values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.getActivityTypeLocalized()); values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.getActivityTypeLocalized());
values.put(TracksColumns.STARTTIME_OFFSET, track.getZoneOffset().getTotalSeconds()); values.put(TracksColumns.STARTTIME_OFFSET, track.getZoneOffset().getTotalSeconds());
if (trackStatistics.getStartTime() != null) { if (trackStatistics.getStartTime() != null) {
@@ -334,7 +341,6 @@ public class ContentProviderUtils {
values.put(TracksColumns.MAX_ALTITUDE, trackStatistics.getMaxAltitude()); values.put(TracksColumns.MAX_ALTITUDE, trackStatistics.getMaxAltitude());
values.put(TracksColumns.ALTITUDE_GAIN, trackStatistics.getTotalAltitudeGain()); values.put(TracksColumns.ALTITUDE_GAIN, trackStatistics.getTotalAltitudeGain());
values.put(TracksColumns.ALTITUDE_LOSS, trackStatistics.getTotalAltitudeLoss()); values.put(TracksColumns.ALTITUDE_LOSS, trackStatistics.getTotalAltitudeLoss());
values.put(TracksColumns.ICON, track.getActivityType() != null ? track.getActivityType().getIconId() : "");
return values; return values;
} }
@@ -12,9 +12,11 @@ import androidx.annotation.VisibleForTesting;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.zone.ZoneRules; import java.time.zone.ZoneRules;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import de.dennisguse.opentracks.Startup; import de.dennisguse.opentracks.Startup;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.tables.MarkerColumns; import de.dennisguse.opentracks.data.tables.MarkerColumns;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns; import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
@@ -28,7 +30,9 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
private static final String TAG = CustomSQLiteOpenHelper.class.getSimpleName(); private static final String TAG = CustomSQLiteOpenHelper.class.getSimpleName();
private static final int DATABASE_VERSION = 36; private static final int DATABASE_VERSION = 37;
private final Context context;
public CustomSQLiteOpenHelper(Context context) { public CustomSQLiteOpenHelper(Context context) {
this(context, ((Startup) context.getApplicationContext()).getDatabaseName()); this(context, ((Startup) context.getApplicationContext()).getDatabaseName());
@@ -37,11 +41,13 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
@VisibleForTesting @VisibleForTesting
public CustomSQLiteOpenHelper(Context context, String databaseName) { public CustomSQLiteOpenHelper(Context context, String databaseName) {
super(context, databaseName, null, DATABASE_VERSION); super(context, databaseName, null, DATABASE_VERSION);
this.context = context;
} }
@VisibleForTesting @VisibleForTesting
public CustomSQLiteOpenHelper(Context context, String databaseName, int databaseVersion) { public CustomSQLiteOpenHelper(Context context, String databaseName, int databaseVersion) {
super(context, databaseName, null, databaseVersion); super(context, databaseName, null, databaseVersion);
this.context = context;
} }
@Override @Override
@@ -75,6 +81,7 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
case 34 -> upgradeFrom33to34(db); case 34 -> upgradeFrom33to34(db);
case 35 -> upgradeFrom34to35(db); case 35 -> upgradeFrom34to35(db);
case 36 -> upgradeFrom35to36(db); case 36 -> upgradeFrom35to36(db);
case 37 -> upgradeFrom36to37(db);
default -> throw new RuntimeException("Not implemented: upgrade to " + toVersion); default -> throw new RuntimeException("Not implemented: upgrade to " + toVersion);
} }
} }
@@ -98,6 +105,7 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
case 33 -> downgradeFrom34to33(db); case 33 -> downgradeFrom34to33(db);
case 34 -> downgradeFrom35to34(db); case 34 -> downgradeFrom35to34(db);
case 35 -> downgradeFrom36to35(db); case 35 -> downgradeFrom36to35(db);
case 36 -> downgradeFrom37to36(db);
default -> throw new RuntimeException("Not implemented: downgrade to " + toVersion); default -> throw new RuntimeException("Not implemented: downgrade to " + toVersion);
} }
} }
@@ -170,7 +178,7 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
db.beginTransaction(); db.beginTransaction();
db.execSQL("ALTER TABLE tracks ADD COLUMN uuid BLOB"); db.execSQL("ALTER TABLE tracks ADD COLUMN uuid BLOB");
try (Cursor cursor = db.query("tracks", new String[]{"_id" }, null, null, null, null, null)) { try (Cursor cursor = db.query("tracks", new String[]{"_id"}, null, null, null, null, null)) {
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
int trackIdIndex = cursor.getColumnIndexOrThrow("_id"); int trackIdIndex = cursor.getColumnIndexOrThrow("_id");
do { do {
@@ -445,7 +453,7 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
ZoneRules zoneRules = ZoneOffset.systemDefault().getRules(); ZoneRules zoneRules = ZoneOffset.systemDefault().getRules();
try (Cursor cursor = db.query("tracks", new String[]{"_id", "starttime" }, null, null, null, null, null)) { try (Cursor cursor = db.query("tracks", new String[]{"_id", "starttime"}, null, null, null, null, null)) {
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
int trackIdIndex = cursor.getColumnIndexOrThrow("_id"); int trackIdIndex = cursor.getColumnIndexOrThrow("_id");
int startTimeIndex = cursor.getColumnIndexOrThrow("starttime"); int startTimeIndex = cursor.getColumnIndexOrThrow("starttime");
@@ -564,4 +572,77 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
db.setTransactionSuccessful(); db.setTransactionSuccessful();
db.endTransaction(); db.endTransaction();
} }
private void upgradeFrom36to37(SQLiteDatabase db) {
Map<String, String> activityIcon2ActivityTypeId = Map.ofEntries(
Map.entry("AIRPLANE", "airplane"),
Map.entry("BIKE", "biking"),
Map.entry("MOUNTAIN_BIKE", "mountain biking"),
Map.entry("MOTOR_BIKE", "motor bike"),
Map.entry("KAYAK", "kayaking"),
Map.entry("BOAT", "boat"),
Map.entry("SAILING", "sailing"),
Map.entry("DRIVE", "driving"),
Map.entry("RUN", "running"),
Map.entry("SKI", "skiing"),
Map.entry("SNOW_BOARDING", "snowboarding"),
Map.entry("WALK", "walking"),
Map.entry("ESCOOTER", "escooter"),
Map.entry("KICKSCOOTER", "kickscooter"),
Map.entry("INLINES_SKATING", "inline skating"),
Map.entry("SKATE_BOARDING", "skateboarding"),
Map.entry("CLIMBING", "climbing"),
Map.entry("SWIMMING", "swimming"),
Map.entry("SWIMMING_OPEN", "swimming in open water"),
Map.entry("WORKOUT", "workout"),
Map.entry("UNKNOWN", "unknown")
);
db.beginTransaction();
db.execSQL("ALTER TABLE tracks ADD COLUMN activity_type TEXT");
try (Cursor cursor = db.query("tracks", new String[]{"_id", "icon", "category"}, null, null, null, null, null)) {
if (cursor.moveToFirst()) {
int trackIdIndex = cursor.getColumnIndexOrThrow("_id");
int iconIndex = cursor.getColumnIndexOrThrow("icon");
int activityTypeLocalizedIndex = cursor.getColumnIndexOrThrow("category");
do {
Track.Id trackId = new Track.Id(cursor.getLong(trackIdIndex));
String iconId = cursor.getString(iconIndex);
String activityTypeLocalized = cursor.getString(activityTypeLocalizedIndex);
ActivityType activityType = ActivityType.findByLocalizedString(context, activityTypeLocalized);
if (activityType.equals(ActivityType.UNKNOWN)) {
String activityTypeId = activityIcon2ActivityTypeId.get(iconId);
activityType = ActivityType.findBy(activityTypeId);
}
ContentValues cv = new ContentValues();
cv.put("activity_type", activityType.getId());
db.update("tracks", cv, "_id = ?", new String[]{String.valueOf(trackId.id())});
} while (cursor.moveToNext());
}
}
db.setTransactionSuccessful();
db.endTransaction();
}
private void downgradeFrom37to36(SQLiteDatabase db) {
db.beginTransaction();
db.execSQL("DROP INDEX tracks_uuid_index");
db.execSQL("ALTER TABLE tracks RENAME TO tracks_old");
db.execSQL("CREATE TABLE tracks (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, category TEXT, starttime INTEGER, stoptime INTEGER, numpoints INTEGER, totaldistance FLOAT, totaltime INTEGER, movingtime INTEGER, avgspeed FLOAT, avgmovingspeed FLOAT, maxspeed FLOAT, minelevation FLOAT, maxelevation FLOAT, elevationgain FLOAT, icon TEXT, uuid BLOB, elevationloss FLOAT, starttime_offset INTEGER)");
db.execSQL("INSERT INTO tracks SELECT _id, name, description, category, starttime, stoptime, numpoints, totaldistance, totaltime, movingtime, avgspeed, avgmovingspeed, maxspeed, minelevation, maxelevation, elevationgain, icon, uuid, elevationloss, starttime_offset FROM tracks_old");
db.execSQL("DROP TABLE tracks_old");
db.execSQL("CREATE UNIQUE INDEX tracks_uuid_index ON tracks(uuid)");
db.setTransactionSuccessful();
db.endTransaction();
}
} }
@@ -2,35 +2,8 @@ package de.dennisguse.opentracks.data.models;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
public enum ActivityIcon { public class ActivityIcon {
AIRPLANE("AIRPLANE", R.drawable.ic_activity_flight_24dp),
BIKE("BIKE", R.drawable.ic_activity_bike_24dp),
MOUNTAIN_BIKE("MOUNTAIN_BIKE", R.drawable.ic_activity_mtb_24dp),
MOTOR_BIKE("MOTOR_BIKE", R.drawable.ic_activity_motorbike_24dp),
KAYAK("KAYAK", R.drawable.ic_activity_kayaking_24dp),
BOAT("BOAT", R.drawable.ic_activity_boat_24dp),
SAILING("SAILING", R.drawable.ic_activity_sailing_24dp),
DRIVE("DRIVE", R.drawable.ic_activity_drive_24dp),
RUN("RUN", R.drawable.ic_activity_run_24dp),
SKI("SKI", R.drawable.ic_activity_skiing_24dp),
SNOW_BOARDING("SNOW_BOARDING", R.drawable.ic_activity_snowboarding_24dp),
UNKNOWN("UNKNOWN", R.drawable.ic_logo_24dp),
WALK("WALK", R.drawable.ic_activity_walk_24dp),
ESCOOTER("ESCOOTER", R.drawable.ic_activity_escooter_24dp),
KICKSCOOTER("KICKSCOOTER", R.drawable.ic_activity_scooter_24dp),
INLINE_SKATING("INLINES_SKATING", R.drawable.ic_activity_inline_skating_24dp),
SKATE_BOARDING("SKATE_BOARDING", R.drawable.ic_activity_skateboarding_24dp),
CLIMBING("CLIMBING", R.drawable.ic_activity_climbing_24dp),
SWIMMING("SWIMMING", R.drawable.ic_activity_swimming_24dp),
SWIMMING_OPEN("SWIMMING_OPEN", R.drawable.ic_activity_swimming_open_24dp),
WORKOUT("WORKOUT", R.drawable.ic_activity_workout_24dp);
@Deprecated //TODO should be removed. static final int ICON_UNKNOWN = R.drawable.ic_logo_24dp;
final String iconId;
final int iconDrawableId;
ActivityIcon(String iconId, int iconDrawableId) {
this.iconId = iconId;
this.iconDrawableId = iconDrawableId;
}
} }
@@ -7,94 +7,93 @@ import androidx.annotation.NonNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
public enum ActivityType { public enum ActivityType {
AIRPLANE("airplane", R.string.activity_type_airplane, ActivityIcon.AIRPLANE, true), AIRPLANE("airplane", R.string.activity_type_airplane, R.drawable.ic_activity_flight_24dp, true),
ATV("ATV", R.string.activity_type_atv, ActivityIcon.DRIVE, true), ATV("ATV", R.string.activity_type_atv, R.drawable.ic_activity_drive_24dp, true),
BIKING("biking", R.string.activity_type_biking, ActivityIcon.BIKE, true), BIKING("biking", R.string.activity_type_biking, R.drawable.ic_activity_bike_24dp, true),
BLIMP("blimp", R.string.activity_type_blimp, ActivityIcon.UNKNOWN, true), BLIMP("blimp", R.string.activity_type_blimp, ActivityIcon.ICON_UNKNOWN, true),
BOAT("boat", R.string.activity_type_boat, ActivityIcon.BOAT, true), BOAT("boat", R.string.activity_type_boat, R.drawable.ic_activity_boat_24dp, true),
CLIMBING("climbing", R.string.activity_type_climbing, ActivityIcon.CLIMBING, false), CLIMBING("climbing", R.string.activity_type_climbing, R.drawable.ic_activity_climbing_24dp, false),
COMMERCIAL_AIRPLANE("commercial airplane", R.string.activity_type_commercial_airplane, ActivityIcon.AIRPLANE, true), COMMERCIAL_AIRPLANE("commercial airplane", R.string.activity_type_commercial_airplane, R.drawable.ic_activity_flight_24dp, true),
CROSS_COUNTRY_SKIING("cross-country skiing", R.string.activity_type_cross_country_skiing, ActivityIcon.SKI, true), CROSS_COUNTRY_SKIING("cross-country skiing", R.string.activity_type_cross_country_skiing, R.drawable.ic_activity_skiing_24dp, true),
CYCLING("cycling", R.string.activity_type_cycling, ActivityIcon.BIKE, true), CYCLING("cycling", R.string.activity_type_cycling, R.drawable.ic_activity_bike_24dp, true),
DIRT_BIKE("dirt bike", R.string.activity_type_dirt_bike, ActivityIcon.MOTOR_BIKE, true), DIRT_BIKE("dirt bike", R.string.activity_type_dirt_bike, R.drawable.ic_activity_mtb_24dp, true),
DONKEY_BACK_RIDING("donkey back riding", R.string.activity_type_donkey_back_riding, ActivityIcon.UNKNOWN, true), DONKEY_BACK_RIDING("donkey back riding", R.string.activity_type_donkey_back_riding, ActivityIcon.ICON_UNKNOWN, true),
DRIVING("driving", R.string.activity_type_driving, ActivityIcon.DRIVE, true), DRIVING("driving", R.string.activity_type_driving, R.drawable.ic_activity_drive_24dp, true),
DRIVING_BUS("driving bus", R.string.activity_type_driving_bus, ActivityIcon.DRIVE, true), DRIVING_BUS("driving bus", R.string.activity_type_driving_bus, R.drawable.ic_activity_drive_24dp, true),
DRIVING_CAR("driving car", R.string.activity_type_driving_car, ActivityIcon.DRIVE, true), DRIVING_CAR("driving car", R.string.activity_type_driving_car, R.drawable.ic_activity_drive_24dp, true),
ESCOOTER("escooter", R.string.activity_type_escooter, ActivityIcon.ESCOOTER, true), ESCOOTER("escooter", R.string.activity_type_escooter, R.drawable.ic_activity_escooter_24dp, true),
FERRY("ferry", R.string.activity_type_ferry, ActivityIcon.BOAT, true), FERRY("ferry", R.string.activity_type_ferry, R.drawable.ic_activity_boat_24dp, true),
FRISBEE("frisbee", R.string.activity_type_frisbee, ActivityIcon.UNKNOWN, true), FRISBEE("frisbee", R.string.activity_type_frisbee, ActivityIcon.ICON_UNKNOWN, true),
GLIDING("gliding", R.string.activity_type_gliding, ActivityIcon.UNKNOWN, true), GLIDING("gliding", R.string.activity_type_gliding, ActivityIcon.ICON_UNKNOWN, true),
HANG_GLIDING("hang gliding", R.string.activity_type_hang_gliding, ActivityIcon.UNKNOWN, true), HANG_GLIDING("hang gliding", R.string.activity_type_hang_gliding, ActivityIcon.ICON_UNKNOWN, true),
HELICOPTER("helicopter", R.string.activity_type_helicopter, ActivityIcon.UNKNOWN, true), HELICOPTER("helicopter", R.string.activity_type_helicopter, ActivityIcon.ICON_UNKNOWN, true),
HIKING("hiking", R.string.activity_type_hiking, ActivityIcon.WALK, false), HIKING("hiking", R.string.activity_type_hiking, R.drawable.ic_activity_walk_24dp, false),
HORSE_BACK_RIDING("horse back riding", R.string.activity_type_horse_back_riding, ActivityIcon.UNKNOWN, true), HORSE_BACK_RIDING("horse back riding", R.string.activity_type_horse_back_riding, ActivityIcon.ICON_UNKNOWN, true),
HOT_AIR_BALLOON("hot air balloon", R.string.activity_type_hot_air_balloon, ActivityIcon.UNKNOWN, true), HOT_AIR_BALLOON("hot air balloon", R.string.activity_type_hot_air_balloon, ActivityIcon.ICON_UNKNOWN, true),
ICE_SAILING("ice sailing", R.string.activity_type_ice_sailing, ActivityIcon.UNKNOWN, true), ICE_SAILING("ice sailing", R.string.activity_type_ice_sailing, ActivityIcon.ICON_UNKNOWN, true),
INLINE_SKATING("inline skating", R.string.activity_type_inline_skating, ActivityIcon.INLINE_SKATING, true), INLINE_SKATING("inline skating", R.string.activity_type_inline_skating, R.drawable.ic_activity_inline_skating_24dp, true),
KAYAKING("kayaking", R.string.activity_type_kayaking, ActivityIcon.KAYAK, true), KAYAKING("kayaking", R.string.activity_type_kayaking, R.drawable.ic_activity_mtb_24dp, true),
KITE_SURFING("kite surfing", R.string.activity_type_kite_surfing, ActivityIcon.UNKNOWN, true), KITE_SURFING("kite surfing", R.string.activity_type_kite_surfing, ActivityIcon.ICON_UNKNOWN, true),
LAND_SAILING("land sailing", R.string.activity_type_land_sailing, ActivityIcon.UNKNOWN, true), LAND_SAILING("land sailing", R.string.activity_type_land_sailing, ActivityIcon.ICON_UNKNOWN, true),
MIXED_TYPE("mixed type", R.string.activity_type_mixed_type, ActivityIcon.UNKNOWN, true), MIXED_TYPE("mixed type", R.string.activity_type_mixed_type, ActivityIcon.ICON_UNKNOWN, true),
MOTOR_BIKE("motor bike", R.string.activity_type_motor_bike, ActivityIcon.MOTOR_BIKE, true), MOTOR_BIKE("motor bike", R.string.activity_type_motor_bike, R.drawable.ic_activity_mtb_24dp, true),
MOTOR_BOATING("motor boating", R.string.activity_type_motor_boating, ActivityIcon.BOAT, true), MOTOR_BOATING("motor boating", R.string.activity_type_motor_boating, R.drawable.ic_activity_boat_24dp, true),
MOUNTAIN_BIKING("mountain biking", R.string.activity_type_mountain_biking, ActivityIcon.MOUNTAIN_BIKE, true), MOUNTAIN_BIKING("mountain biking", R.string.activity_type_mountain_biking, R.drawable.ic_activity_mtb_24dp, true),
OFF_TRAIL_HIKING("off trail hiking", R.string.activity_type_hiking, ActivityIcon.WALK, false), OFF_TRAIL_HIKING("off trail hiking", R.string.activity_type_hiking, R.drawable.ic_activity_walk_24dp, false),
OTHER("other", R.string.activity_type_other, ActivityIcon.UNKNOWN, true), OTHER("other", R.string.activity_type_other, ActivityIcon.ICON_UNKNOWN, true),
PADDLING("paddling", R.string.activity_type_paddling, ActivityIcon.UNKNOWN, true), PADDLING("paddling", R.string.activity_type_paddling, ActivityIcon.ICON_UNKNOWN, true),
PARA_GLIDING("para gliding", R.string.activity_type_para_gliding, ActivityIcon.UNKNOWN, true), PARA_GLIDING("para gliding", R.string.activity_type_para_gliding, ActivityIcon.ICON_UNKNOWN, true),
RC_AIRPLANE("RC airplane", R.string.activity_type_rc_airplane, ActivityIcon.AIRPLANE, true), RC_AIRPLANE("RC airplane", R.string.activity_type_rc_airplane, R.drawable.ic_activity_flight_24dp, true),
RC_BOAT("RC boat", R.string.activity_type_rc_boat, ActivityIcon.BOAT, true), RC_BOAT("RC boat", R.string.activity_type_rc_boat, R.drawable.ic_activity_boat_24dp, true),
RC_HELICOPTER("RC helicopter", R.string.activity_type_rc_helicopter, ActivityIcon.UNKNOWN, true), RC_HELICOPTER("RC helicopter", R.string.activity_type_rc_helicopter, ActivityIcon.ICON_UNKNOWN, true),
RIDING("riding", R.string.activity_type_horse_back_riding, ActivityIcon.UNKNOWN, true), RIDING("riding", R.string.activity_type_horse_back_riding, ActivityIcon.ICON_UNKNOWN, true),
ROAD_BIKING("road biking", R.string.activity_type_road_biking, ActivityIcon.BIKE, true), ROAD_BIKING("road biking", R.string.activity_type_road_biking, R.drawable.ic_activity_bike_24dp, true),
ROLLER_SKIING("roller skiing", R.string.activity_type_roller_skiing, ActivityIcon.UNKNOWN, true), ROLLER_SKIING("roller skiing", R.string.activity_type_roller_skiing, ActivityIcon.ICON_UNKNOWN, true),
ROWING("rowing", R.string.activity_type_rowing, ActivityIcon.UNKNOWN, true), ROWING("rowing", R.string.activity_type_rowing, ActivityIcon.ICON_UNKNOWN, true),
RUNNING("running", R.string.activity_type_running, ActivityIcon.RUN, false), RUNNING("running", R.string.activity_type_running, R.drawable.ic_activity_run_24dp, false),
SAILING("sailing", R.string.activity_type_sailing, ActivityIcon.SAILING, true), SAILING("sailing", R.string.activity_type_sailing, R.drawable.ic_activity_sailing_24dp, true),
KICKSCOOTER("kickscooter", R.string.activity_type_kickscooter, ActivityIcon.KICKSCOOTER, true), KICKSCOOTER("kickscooter", R.string.activity_type_kickscooter, R.drawable.ic_activity_scooter_24dp, true),
SEAPLANE("seaplane", R.string.activity_type_seaplane, ActivityIcon.AIRPLANE, true), SEAPLANE("seaplane", R.string.activity_type_seaplane, R.drawable.ic_activity_flight_24dp, true),
SKATE_BOARDING("skate boarding", R.string.activity_type_skate_boarding, ActivityIcon.SKATE_BOARDING, true), SKATE_BOARDING("skateboarding", R.string.activity_type_skate_boarding, R.drawable.ic_activity_skateboarding_24dp, true),
SKATING("skating", R.string.activity_type_skating, ActivityIcon.UNKNOWN, true), SKATING("skating", R.string.activity_type_skating, ActivityIcon.ICON_UNKNOWN, true),
SKIING("skiing", R.string.activity_type_skiing, ActivityIcon.SKI, true), SKIING("skiing", R.string.activity_type_skiing, R.drawable.ic_activity_skiing_24dp, true),
SKY_JUMPING("sky jumping", R.string.activity_type_sky_jumping, ActivityIcon.UNKNOWN, true), SKY_JUMPING("sky jumping", R.string.activity_type_sky_jumping, ActivityIcon.ICON_UNKNOWN, true),
SLED("sled", R.string.activity_type_sled, ActivityIcon.UNKNOWN, true), SLED("sled", R.string.activity_type_sled, ActivityIcon.ICON_UNKNOWN, true),
SNOW_BOARDING("snow boarding", R.string.activity_type_snow_boarding, ActivityIcon.SNOW_BOARDING, true), SNOW_BOARDING("snowboarding", R.string.activity_type_snow_boarding, R.drawable.ic_activity_snowboarding_24dp, true),
SNOW_SHOEING("snow shoeing", R.string.activity_type_snow_shoeing, ActivityIcon.UNKNOWN, true), SNOW_SHOEING("snow shoeing", R.string.activity_type_snow_shoeing, ActivityIcon.ICON_UNKNOWN, true),
SPEED_WALKING("speed walking", R.string.activity_type_speed_walking, ActivityIcon.WALK, false), SPEED_WALKING("speed walking", R.string.activity_type_speed_walking, R.drawable.ic_activity_walk_24dp, false),
STREET_RUNNING("street running", R.string.activity_type_street_running, ActivityIcon.RUN, false), STREET_RUNNING("street running", R.string.activity_type_street_running, R.drawable.ic_activity_run_24dp, false),
SURFING("surfing", R.string.activity_type_surfing, ActivityIcon.UNKNOWN, true), SURFING("surfing", R.string.activity_type_surfing, ActivityIcon.ICON_UNKNOWN, true),
TRACK_CYCLING("track cycling", R.string.activity_type_track_cycling, ActivityIcon.BIKE, true), TRACK_CYCLING("track cycling", R.string.activity_type_track_cycling, R.drawable.ic_activity_bike_24dp, true),
TRACK_RUNNING("track running", R.string.activity_type_trail_running, ActivityIcon.RUN, false), TRACK_RUNNING("track running", R.string.activity_type_trail_running, R.drawable.ic_activity_run_24dp, false),
TRAIL_HIKING("trail hiking", R.string.activity_type_trail_hiking, ActivityIcon.WALK, false), TRAIL_HIKING("trail hiking", R.string.activity_type_trail_hiking, R.drawable.ic_activity_walk_24dp, false),
TRAIL_RUNNING("trail running", R.string.activity_type_trail_running, ActivityIcon.RUN, false), TRAIL_RUNNING("trail running", R.string.activity_type_trail_running, R.drawable.ic_activity_run_24dp, false),
TRAIN("train", R.string.activity_type_train, ActivityIcon.UNKNOWN, true), TRAIN("train", R.string.activity_type_train, ActivityIcon.ICON_UNKNOWN, true),
ULTIMATE_FRISBEE("ultimate frisbee", R.string.activity_type_ultimate_frisbee, ActivityIcon.UNKNOWN, true), ULTIMATE_FRISBEE("ultimate frisbee", R.string.activity_type_ultimate_frisbee, ActivityIcon.ICON_UNKNOWN, true),
WAKEBOARDING("wakeboarding", R.string.activity_type_wakeboarding, ActivityIcon.UNKNOWN, true), WAKEBOARDING("wakeboarding", R.string.activity_type_wakeboarding, ActivityIcon.ICON_UNKNOWN, true),
WALKING("walking", R.string.activity_type_walking, ActivityIcon.WALK, false), WALKING("walking", R.string.activity_type_walking, R.drawable.ic_activity_walk_24dp, false),
WATER_SKIING("water skiing", R.string.activity_type_water_skiing, ActivityIcon.UNKNOWN, true), WATER_SKIING("water skiing", R.string.activity_type_water_skiing, ActivityIcon.ICON_UNKNOWN, true),
WIND_SURFING("wind surfing", R.string.activity_type_wind_surfing, ActivityIcon.UNKNOWN, true), WIND_SURFING("wind surfing", R.string.activity_type_wind_surfing, ActivityIcon.ICON_UNKNOWN, true),
SWIMMING("swimming", R.string.activity_type_swimming, ActivityIcon.SWIMMING, false), SWIMMING("swimming", R.string.activity_type_swimming, R.drawable.ic_activity_swimming_24dp, false),
SWIMMING_OPEN("swimming in open water", R.string.activity_type_swimming_open, ActivityIcon.SWIMMING_OPEN, false), SWIMMING_OPEN("swimming in open water", R.string.activity_type_swimming_open, R.drawable.ic_activity_swimming_open_24dp, false),
WORKOUT("workout", R.string.activity_type_workout, ActivityIcon.WORKOUT, false), WORKOUT("workout", R.string.activity_type_workout, R.drawable.ic_activity_workout_24dp, false),
UNKNOWN("unknown", R.string.activity_type_unknown, ActivityIcon.UNKNOWN, true); UNKNOWN("unknown", R.string.activity_type_unknown, ActivityIcon.ICON_UNKNOWN, true);
final String id; final String id;
final ActivityIcon icon; final int iconDrawableId;
final boolean showSpeedPreferred; final boolean showSpeedPreferred;
final int localizedStringId; final int localizedStringId;
ActivityType(String id, int localizedStringId, ActivityIcon icon, boolean showSpeedPreferred) { ActivityType(String id, int localizedStringId, int iconDrawableId, boolean showSpeedPreferred) {
this.id = id; this.id = id;
this.localizedStringId = localizedStringId; this.localizedStringId = localizedStringId;
this.icon = icon; this.iconDrawableId = iconDrawableId;
this.showSpeedPreferred = showSpeedPreferred; this.showSpeedPreferred = showSpeedPreferred;
} }
@@ -102,13 +101,8 @@ public enum ActivityType {
return id; return id;
} }
@Deprecated
public String getIconId() {
return icon.iconId;
}
public int getIconDrawableId() { public int getIconDrawableId() {
return icon.iconDrawableId; return iconDrawableId;
} }
public int getLocalizedStringId() { public int getLocalizedStringId() {
@@ -123,16 +117,13 @@ public enum ActivityType {
return Arrays.stream(values()) return Arrays.stream(values())
.map(ActivityType::getLocalizedStringId) .map(ActivityType::getLocalizedStringId)
.map(context::getString) .map(context::getString)
.collect(Collectors.toList()); .toList();
} }
@NonNull @NonNull
public static ActivityType findBy(String iconId) { public static ActivityType findBy(String activityTypeId) {
if (ActivityIcon.UNKNOWN.iconId.equals(iconId)) {
return ActivityType.UNKNOWN;
}
return Arrays.stream(ActivityType.values()).filter( return Arrays.stream(ActivityType.values()).filter(
it -> it.icon.iconId.equals(iconId) it -> it.id.equals(activityTypeId)
).findFirst() ).findFirst()
.orElse(ActivityType.UNKNOWN); .orElse(ActivityType.UNKNOWN);
} }
@@ -101,8 +101,8 @@ public class Track {
return activityTypeLocalized; return activityTypeLocalized;
} }
public void setActivityTypeLocalized(String activityType) { public void setActivityTypeLocalized(String activityTypeLocalized) {
this.activityTypeLocalized = activityType; this.activityTypeLocalized = activityTypeLocalized;
} }
public ActivityType getActivityType() { public ActivityType getActivityType() {
@@ -39,7 +39,11 @@ public interface TracksColumns extends BaseColumns {
String UUID = "uuid"; // identifier to make tracks globally unique (prevent re-import) String UUID = "uuid"; // identifier to make tracks globally unique (prevent re-import)
String NAME = "name"; // track name String NAME = "name"; // track name
String DESCRIPTION = "description"; // track description String DESCRIPTION = "description"; // track description
/** see {@link de.dennisguse.opentracks.data.models.ActivityType}.id */
String ACTIVITY_TYPE = "activity_type";
String ACTIVITY_TYPE_LOCALIZED = "category"; // track activity type String ACTIVITY_TYPE_LOCALIZED = "category"; // track activity type
@Deprecated
String ICON = "icon"; // track activity type icon
String STARTTIME = "starttime"; // track start time String STARTTIME = "starttime"; // track start time
String STARTTIME_OFFSET = "starttime_offset"; // in plus/minus in seconds String STARTTIME_OFFSET = "starttime_offset"; // in plus/minus in seconds
String STOPTIME = "stoptime"; // track stop time String STOPTIME = "stoptime"; // track stop time
@@ -57,7 +61,6 @@ public interface TracksColumns extends BaseColumns {
String MAX_ALTITUDE = "maxelevation"; // maximum altitude //TODO RENAME column String MAX_ALTITUDE = "maxelevation"; // maximum altitude //TODO RENAME column
String ALTITUDE_GAIN = "elevationgain"; // altitude gain //TODO RENAME column String ALTITUDE_GAIN = "elevationgain"; // altitude gain //TODO RENAME column
String ALTITUDE_LOSS = "elevationloss"; // altitude loss //TODO RENAME column String ALTITUDE_LOSS = "elevationloss"; // altitude loss //TODO RENAME column
String ICON = "icon"; // track activity type icon //TODO DEPRECATED
String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " ("
+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
@@ -79,7 +82,8 @@ public interface TracksColumns extends BaseColumns {
+ ICON + " TEXT, " + ICON + " TEXT, "
+ UUID + " BLOB, " + UUID + " BLOB, "
+ ALTITUDE_LOSS + " FLOAT, " + ALTITUDE_LOSS + " FLOAT, "
+ STARTTIME_OFFSET + " INTEGER)"; + STARTTIME_OFFSET + " INTEGER, "
+ ACTIVITY_TYPE + " TEXT)";
String CREATE_TABLE_INDEX = "CREATE UNIQUE INDEX " + TABLE_NAME + "_" + UUID + "_index ON " + TABLE_NAME + "(" + UUID + ")"; String CREATE_TABLE_INDEX = "CREATE UNIQUE INDEX " + TABLE_NAME + "_" + UUID + "_index ON " + TABLE_NAME + "(" + UUID + ")";
@@ -188,10 +188,9 @@ public class StatisticsRecordedFragment extends Fragment {
{ {
Context context = getContext(); Context context = getContext();
String localizedActivityType = track.getActivityTypeLocalized(); String localizedActivityType = track.getActivityTypeLocalized();
String trackIconValue = ActivityType.findByLocalizedString(context, localizedActivityType) int iconDrawableId = ActivityType.findByLocalizedString(context, localizedActivityType)
.getIconId(); .getIconDrawableId();
viewBinding.statsActivityTypeIcon.setImageDrawable(ContextCompat.getDrawable(getContext(), ActivityType.findBy(trackIconValue) viewBinding.statsActivityTypeIcon.setImageDrawable(ContextCompat.getDrawable(getContext(), iconDrawableId));
.getIconDrawableId()));
} }
// Set time and start datetime // Set time and start datetime
@@ -32,7 +32,6 @@ import androidx.fragment.app.FragmentActivity;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
@@ -231,9 +230,9 @@ public class ExportActivity extends FragmentActivity implements ExportService.Ex
exportTasks = new ArrayList<>(); exportTasks = new ArrayList<>();
if (allInOneFile) { if (allInOneFile) {
String filename = "OpenTracks-Backup"; String filename = "OpenTracks-Backup";
exportTasks.add(new ExportTask(filename, trackFileFormat, tracks.stream().map(Track::getId).collect(Collectors.toList()))); exportTasks.add(new ExportTask(filename, trackFileFormat, tracks.stream().map(Track::getId).toList()));
} else { } else {
exportTasks.addAll(tracks.stream().map(it -> new ExportTask(null, trackFileFormat, List.of(it.getId()))).collect(Collectors.toList())); exportTasks.addAll(tracks.stream().map(it -> new ExportTask(null, trackFileFormat, List.of(it.getId()))).toList());
} }
trackExportTotalCount = exportTasks.size(); trackExportTotalCount = exportTasks.size();
} }
@@ -261,7 +261,7 @@ public class GPXTrackExporter implements TrackExporter {
printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(marker.getTime(), zoneOffset) + "</time>"); printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(marker.getTime(), zoneOffset) + "</time>");
printWriter.println("<name>" + StringUtils.formatCData(marker.getName()) + "</name>"); printWriter.println("<name>" + StringUtils.formatCData(marker.getName()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(marker.getDescription()) + "</desc>"); printWriter.println("<desc>" + StringUtils.formatCData(marker.getDescription()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(marker.getCategory()) + "</type>"); printWriter.println("<type>" + StringUtils.formatCData(marker.getCategory()) + "</type>"); //TODO This is localized; may be better to export in English only. See #1608
printWriter.println("</wpt>"); printWriter.println("</wpt>");
} }
@@ -269,12 +269,16 @@ public class GPXTrackExporter implements TrackExporter {
printWriter.println("<trk>"); printWriter.println("<trk>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>"); printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>"); printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "</type>"); printWriter.println("<type>" + StringUtils.formatCData(track.getActivityType().getId()) + "</type>");
printWriter.println("<extensions>"); printWriter.println("<extensions>");
printWriter.println("<topografix:color>c0c0c0</topografix:color>"); printWriter.println("<topografix:color>c0c0c0</topografix:color>");
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>"); printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");
if (track.getActivityTypeLocalized() != null || !track.getActivityTypeLocalized().isBlank()) {
printWriter.println("<opentracks:typeTranslated>" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "</opentracks:typeTranslated>");
}
TrackStatistics trackStatistics = track.getTrackStatistics(); TrackStatistics trackStatistics = track.getTrackStatistics();
printWriter.println("<gpxtrkx:TrackStatsExtension>"); printWriter.println("<gpxtrkx:TrackStatsExtension>");
printWriter.println("<gpxtrkx:Distance>" + trackStatistics.getTotalDistance().toM() + "</gpxtrkx:Distance>"); printWriter.println("<gpxtrkx:Distance>" + trackStatistics.getTotalDistance().toM() + "</gpxtrkx:Distance>");
@@ -37,6 +37,7 @@ import java.util.Objects;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.TrackPointIterator; import de.dennisguse.opentracks.data.TrackPointIterator;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
@@ -59,7 +60,8 @@ public class KMLTrackExporter implements TrackExporter {
private static final String TRACK_STYLE = "track"; private static final String TRACK_STYLE = "track";
private static final String SCHEMA_ID = "schema"; private static final String SCHEMA_ID = "schema";
public static final String EXTENDED_DATA_TYPE_ACTIVITYTYPE = "type"; public static final String EXTENDED_DATA_TYPE_LOCALIZED = "type";
public static final String EXTENDED_DATA_ACTIVITY_TYPE = "activityType";
public static final String EXTENDED_DATA_TYPE_TRACKPOINT = "trackpoint_type"; public static final String EXTENDED_DATA_TYPE_TRACKPOINT = "trackpoint_type";
public static final String EXTENDED_DATA_TYPE_SPEED = "speed"; public static final String EXTENDED_DATA_TYPE_SPEED = "speed";
@@ -295,17 +297,16 @@ public class KMLTrackExporter implements TrackExporter {
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>"); printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<description>" + StringUtils.formatCData(track.getDescription()) + "</description>"); printWriter.println("<description>" + StringUtils.formatCData(track.getDescription()) + "</description>");
printWriter.println("<icon>" + StringUtils.formatCData(track.getActivityType().getIconId()) + "</icon>");
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>"); printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");
printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>"); printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>");
writeActivityType(track.getActivityTypeLocalized()); writeActivityType(track.getActivityType());
writeTypeLocalized(track.getActivityTypeLocalized());
printWriter.println("<MultiTrack>"); printWriter.println("<MultiTrack>");
printWriter.println("<altitudeMode>absolute</altitudeMode>"); printWriter.println("<altitudeMode>absolute</altitudeMode>");
printWriter.println("<interpolate>1</interpolate>"); printWriter.println("<interpolate>1</interpolate>");
} }
private void writeEndTrack() { private void writeEndTrack() {
printWriter.println("</MultiTrack>"); printWriter.println("</MultiTrack>");
printWriter.println("</Placemark>"); printWriter.println("</Placemark>");
@@ -417,7 +418,7 @@ public class KMLTrackExporter implements TrackExporter {
printWriter.println("<description>" + StringUtils.formatCData(description) + "</description>"); printWriter.println("<description>" + StringUtils.formatCData(description) + "</description>");
printWriter.println("<TimeStamp><when>" + getTime(zoneOffset, location) + "</when></TimeStamp>"); printWriter.println("<TimeStamp><when>" + getTime(zoneOffset, location) + "</when></TimeStamp>");
printWriter.println("<styleUrl>#" + KMLTrackExporter.MARKER_STYLE + "</styleUrl>"); printWriter.println("<styleUrl>#" + KMLTrackExporter.MARKER_STYLE + "</styleUrl>");
writeActivityType(activityType); writeTypeLocalized(activityType);
printWriter.println("<Point>"); printWriter.println("<Point>");
printWriter.println("<coordinates>" + getCoordinates(location, ",") + "</coordinates>"); printWriter.println("<coordinates>" + getCoordinates(location, ",") + "</coordinates>");
printWriter.println("</Point>"); printWriter.println("</Point>");
@@ -438,7 +439,7 @@ public class KMLTrackExporter implements TrackExporter {
printWriter.println("</Camera>"); printWriter.println("</Camera>");
printWriter.println("<TimeStamp><when>" + getTime(zoneOffset, marker.getLocation()) + "</when></TimeStamp>"); printWriter.println("<TimeStamp><when>" + getTime(zoneOffset, marker.getLocation()) + "</when></TimeStamp>");
printWriter.println("<styleUrl>#" + MARKER_STYLE + "</styleUrl>"); printWriter.println("<styleUrl>#" + MARKER_STYLE + "</styleUrl>");
writeActivityType(marker.getCategory()); writeTypeLocalized(marker.getCategory());
if (exportPhotos) { if (exportPhotos) {
printWriter.println("<Icon><href>" + KmzTrackExporter.buildKmzImageFilePath(marker) + "</href></Icon>"); printWriter.println("<Icon><href>" + KmzTrackExporter.buildKmzImageFilePath(marker) + "</href></Icon>");
@@ -493,12 +494,21 @@ public class KMLTrackExporter implements TrackExporter {
return result; return result;
} }
private void writeActivityType(String activityTypeLocalized) { private void writeTypeLocalized(String localizedValue) {
if (activityTypeLocalized == null || "".equals(activityTypeLocalized)) { if (localizedValue == null || localizedValue.equals("")) {
return; return;
} }
printWriter.println("<ExtendedData>"); printWriter.println("<ExtendedData>");
printWriter.println("<Data name=\"" + EXTENDED_DATA_TYPE_ACTIVITYTYPE + "\"><value>" + StringUtils.formatCData(activityTypeLocalized) + "</value></Data>"); printWriter.println("<Data name=\"" + EXTENDED_DATA_TYPE_LOCALIZED + "\"><value>" + StringUtils.formatCData(localizedValue) + "</value></Data>");
printWriter.println("</ExtendedData>");
}
private void writeActivityType(ActivityType value) {
if (value == null) {
return;
}
printWriter.println("<ExtendedData>");
printWriter.println("<Data name=\"" + EXTENDED_DATA_ACTIVITY_TYPE + "\"><value>" + StringUtils.formatCData(value.getId()) + "</value></Data>");
printWriter.println("</ExtendedData>"); printWriter.println("</ExtendedData>");
} }
@@ -55,7 +55,6 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
private static final String TAG = GpxTrackImporter.class.getSimpleName(); private static final String TAG = GpxTrackImporter.class.getSimpleName();
private static final String TAG_DESCRIPTION = "desc"; private static final String TAG_DESCRIPTION = "desc";
private static final String TAG_COMMENT = "cmt";
private static final String TAG_ALTITUDE = "ele"; private static final String TAG_ALTITUDE = "ele";
private static final String TAG_GPX = "gpx"; private static final String TAG_GPX = "gpx";
private static final String TAG_NAME = "name"; private static final String TAG_NAME = "name";
@@ -64,6 +63,7 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
private static final String TAG_TRACK_POINT = "trkpt"; private static final String TAG_TRACK_POINT = "trkpt";
private static final String TAG_TRACK_SEGMENT = "trkseg"; private static final String TAG_TRACK_SEGMENT = "trkseg";
private static final String TAG_TYPE = "type"; private static final String TAG_TYPE = "type";
private static final String TAG_TYPE_LOCALIZED = "opentracks:typeTranslated";
private static final String TAG_MARKER = "wpt"; private static final String TAG_MARKER = "wpt";
private static final String TAG_ID = "opentracks:trackid"; private static final String TAG_ID = "opentracks:trackid";
@@ -99,6 +99,7 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
private String name; private String name;
private String description; private String description;
private String activityType; private String activityType;
private String activityTypeLocalized;
private String latitude; private String latitude;
private String longitude; private String longitude;
private String altitude; private String altitude;
@@ -159,7 +160,11 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
case TAG_GPX -> onFileEnd(); case TAG_GPX -> onFileEnd();
case TAG_MARKER -> onMarkerEnd(); case TAG_MARKER -> onMarkerEnd();
case TAG_TRACK -> { case TAG_TRACK -> {
trackImporter.setTrack(context, name, uuid, description, activityType, null, zoneOffset); if (activityTypeLocalized == null ) {
// Backward compatibility: up v4.9.1 as <type> contained localized content.
activityTypeLocalized = activityType;
}
trackImporter.setTrack(context, name, uuid, description, activityTypeLocalized, activityType, zoneOffset);
zoneOffset = null; zoneOffset = null;
} }
case TAG_TRACK_SEGMENT -> onTrackSegmentEnd(); case TAG_TRACK_SEGMENT -> onTrackSegmentEnd();
@@ -174,9 +179,16 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
description = content.trim(); description = content.trim();
} }
} }
case TAG_TYPE -> { case TAG_TYPE -> { //Track or Marker/WPT
if (content != null) { if (content != null) {
// In older version this might be localized content.
activityType = content.trim(); activityType = content.trim();
markerType = content.trim();
}
}
case TAG_TYPE_LOCALIZED -> {
if (content != null) {
activityTypeLocalized = content.trim();
} }
} }
case TAG_TIME -> { case TAG_TIME -> {
@@ -189,11 +201,6 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
altitude = content.trim(); altitude = content.trim();
} }
} }
case TAG_COMMENT -> {
if (content != null) {
markerType = content.trim();
}
}
case TAG_EXTENSION_SPEED, TAG_EXTENSION_SPEED_COMPAT -> { case TAG_EXTENSION_SPEED, TAG_EXTENSION_SPEED_COMPAT -> {
if (content != null) { if (content != null) {
speed = content.trim(); speed = content.trim();
@@ -385,7 +392,6 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
private void onMarkerStart(Attributes attributes) { private void onMarkerStart(Attributes attributes) {
name = null; name = null;
description = null; description = null;
activityType = null;
photoUrl = null; photoUrl = null;
latitude = attributes.getValue(ATTRIBUTE_LAT); latitude = attributes.getValue(ATTRIBUTE_LAT);
longitude = attributes.getValue(ATTRIBUTE_LON); longitude = attributes.getValue(ATTRIBUTE_LON);
@@ -415,8 +421,8 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
if (description != null) { if (description != null) {
marker.setDescription(description); marker.setDescription(description);
} }
if (activityType != null) { if (markerType != null) {
marker.setCategory(activityType); marker.setCategory(markerType);
} }
if (photoUrl != null) { if (photoUrl != null) {
@@ -32,7 +32,6 @@ import androidx.lifecycle.ViewModelProvider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.TrackRecordedActivity; import de.dennisguse.opentracks.TrackRecordedActivity;
@@ -100,7 +99,7 @@ public class ImportActivity extends FragmentActivity {
documentFiles = new ArrayList<>(); documentFiles = new ArrayList<>();
documentFiles.add(DocumentFile.fromTreeUri(this, documentUris.get(0))); documentFiles.add(DocumentFile.fromTreeUri(this, documentUris.get(0)));
} else { } else {
documentFiles = documentUris.stream().map(it -> DocumentFile.fromSingleUri(this, it)).collect(Collectors.toList()); documentFiles = documentUris.stream().map(it -> DocumentFile.fromSingleUri(this, it)).toList();
} }
initViews(); initViews();
@@ -12,7 +12,6 @@ import androidx.lifecycle.MutableLiveData;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
@@ -50,7 +49,7 @@ public class ImportViewModel extends AndroidViewModel implements ImportServiceRe
List<ArrayList<DocumentFile>> nestedFileList = documentFiles.stream() List<ArrayList<DocumentFile>> nestedFileList = documentFiles.stream()
.map(FileUtils::getFiles) .map(FileUtils::getFiles)
// TODO flatMap(Collection::stream) fails with ClassCastException; try in the future again // TODO flatMap(Collection::stream) fails with ClassCastException; try in the future again
.collect(Collectors.toList()); .toList();
List<DocumentFile> fileList = new ArrayList<>(); List<DocumentFile> fileList = new ArrayList<>();
nestedFileList.forEach(fileList::addAll); nestedFileList.forEach(fileList::addAll);
@@ -53,7 +53,6 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
private static final String TAG_COORDINATES = "coordinates"; private static final String TAG_COORDINATES = "coordinates";
private static final String TAG_DESCRIPTION = "description"; private static final String TAG_DESCRIPTION = "description";
private static final String TAG_ICON = "icon";
private static final String TAG_COORD = "coord"; private static final String TAG_COORD = "coord";
private static final String TAG_KML22_COORD = "gx:coord"; private static final String TAG_KML22_COORD = "gx:coord";
@@ -61,7 +60,7 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
private static final String TAG_MULTI_TRACK = "MultiTrack"; private static final String TAG_MULTI_TRACK = "MultiTrack";
private static final String TAG_KML22_MULTI_TRACK = "gx:MultiTrack"; private static final String TAG_KML22_MULTI_TRACK = "gx:MultiTrack";
private static final String TAG_DATA_ACTIVITYTYPE = "Data"; private static final String TAG_EXTENDED_DATA = "Data";
private static final String TAG_SIMPLE_ARRAY_DATA = "SimpleArrayData"; private static final String TAG_SIMPLE_ARRAY_DATA = "SimpleArrayData";
private static final String TAG_KML22_SIMPLE_ARRAY_DATA = "gx:SimpleArrayData"; private static final String TAG_KML22_SIMPLE_ARRAY_DATA = "gx:SimpleArrayData";
@@ -94,7 +93,7 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
private final ArrayList<Instant> whenList = new ArrayList<>(); private final ArrayList<Instant> whenList = new ArrayList<>();
private final ArrayList<Location> locationList = new ArrayList<>(); private final ArrayList<Location> locationList = new ArrayList<>();
private String dataType; //Could be converted to an ENUM private String dataType;
private final ArrayList<String> trackpointTypeList = new ArrayList<>(); private final ArrayList<String> trackpointTypeList = new ArrayList<>();
private final ArrayList<Float> sensorSpeedList = new ArrayList<>(); private final ArrayList<Float> sensorSpeedList = new ArrayList<>();
@@ -112,10 +111,10 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
// The current element content // The current element content
private String content = ""; private String content = "";
private String icon;
private String name; private String name;
private String description; private String description;
private String activityType; private String activityType;
private String activityTypeLocalized;
private String latitude; private String latitude;
private String longitude; private String longitude;
private String altitude; private String altitude;
@@ -148,7 +147,7 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
} }
onTrackSegmentStart(); onTrackSegmentStart();
} }
case TAG_DATA_ACTIVITYTYPE, TAG_SIMPLE_ARRAY_DATA, TAG_KML22_SIMPLE_ARRAY_DATA -> case TAG_EXTENDED_DATA, TAG_SIMPLE_ARRAY_DATA, TAG_KML22_SIMPLE_ARRAY_DATA ->
dataType = attributes.getValue(ATTRIBUTE_NAME); dataType = attributes.getValue(ATTRIBUTE_NAME);
} }
} }
@@ -167,18 +166,24 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
onMarkerEnd(); onMarkerEnd();
case TAG_COORDINATES -> onMarkerLocationEnd(); case TAG_COORDINATES -> onMarkerLocationEnd();
case TAG_MULTI_TRACK, TAG_KML22_MULTI_TRACK -> { case TAG_MULTI_TRACK, TAG_KML22_MULTI_TRACK -> {
trackImporter.setTrack(context, name, uuid, description, activityType, icon, zoneOffset); trackImporter.setTrack(context, name, uuid, description, activityTypeLocalized, activityType, zoneOffset);
zoneOffset = null; zoneOffset = null;
} }
case TAG_TRACK, TAG_KML22_TRACK -> onTrackSegmentEnd(); case TAG_TRACK, TAG_KML22_TRACK -> onTrackSegmentEnd();
case TAG_COORD, TAG_KML22_COORD -> onCoordEnded(); case TAG_COORD, TAG_KML22_COORD -> onCoordEnded();
case TAG_VALUE, TAG_KML22_VALUE -> { case TAG_VALUE, TAG_KML22_VALUE -> {
if (KMLTrackExporter.EXTENDED_DATA_TYPE_ACTIVITYTYPE.equals(dataType)) { switch (dataType) {
if (content != null) { case KMLTrackExporter.EXTENDED_DATA_ACTIVITY_TYPE -> {
activityType = content.trim(); if (content != null) {
activityType = content.trim();
}
} }
} else { case KMLTrackExporter.EXTENDED_DATA_TYPE_LOCALIZED -> {
onExtendedDataValueEnd(); if (content != null) {
activityTypeLocalized = content.trim();
}
}
default -> onExtendedDataValueEnd();
} }
} }
case TAG_NAME -> { case TAG_NAME -> {
@@ -196,11 +201,6 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
description = content.trim(); description = content.trim();
} }
} }
case TAG_ICON -> {
if (content != null) {
icon = content.trim();
}
}
case TAG_WHEN -> { case TAG_WHEN -> {
if (content != null) { if (content != null) {
try { try {
@@ -233,9 +233,8 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
private void onMarkerStart() { private void onMarkerStart() {
// Reset all Placemark variables // Reset all Placemark variables
name = null; name = null;
icon = null;
description = null; description = null;
activityType = null; activityTypeLocalized = null;
photoUrl = null; photoUrl = null;
latitude = null; latitude = null;
longitude = null; longitude = null;
@@ -262,13 +261,13 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
Marker marker = new Marker(null, new TrackPoint(TrackPoint.Type.TRACKPOINT, location, whenList.get(0))); //TODO Creating marker without need Marker marker = new Marker(null, new TrackPoint(TrackPoint.Type.TRACKPOINT, location, whenList.get(0))); //TODO Creating marker without need
marker.setName(name != null ? name : ""); marker.setName(name != null ? name : "");
marker.setDescription(description != null ? description : ""); marker.setDescription(description != null ? description : "");
marker.setCategory(activityType != null ? activityType : ""); marker.setCategory(activityTypeLocalized != null ? activityTypeLocalized : "");
marker.setPhotoUrl(photoUrl); marker.setPhotoUrl(photoUrl);
markers.add(marker); markers.add(marker);
name = null; name = null;
description = null; description = null;
activityType = null; activityTypeLocalized = null;
photoUrl = null; photoUrl = null;
whenList.clear(); whenList.clear();
} }
@@ -16,7 +16,6 @@ import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
@@ -106,10 +105,9 @@ public class TrackImporter {
if (activityTypeLocalized != null) { if (activityTypeLocalized != null) {
track.setActivityTypeLocalized(activityTypeLocalized); track.setActivityTypeLocalized(activityTypeLocalized);
} }
ActivityType activityType; ActivityType activityType;
if (activityTypeId == null) { if (activityTypeId == null) {
activityType = ActivityType.findByLocalizedString(context, activityTypeId); activityType = ActivityType.findByLocalizedString(context, activityTypeLocalized);
} else { } else {
activityType = ActivityType.findBy(activityTypeId); activityType = ActivityType.findBy(activityTypeId);
} }
@@ -223,7 +221,7 @@ public class TrackImporter {
private void matchMarkers2TrackPoints(Track.Id trackId) { private void matchMarkers2TrackPoints(Track.Id trackId) {
List<TrackPoint> trackPointsWithLocation = trackPoints.stream() List<TrackPoint> trackPointsWithLocation = trackPoints.stream()
.filter(TrackPoint::hasLocation) .filter(TrackPoint::hasLocation)
.collect(Collectors.toList()); .toList();
List<Marker> todoMarkers = new LinkedList<>(markers); List<Marker> todoMarkers = new LinkedList<>(markers);
List<Marker> doneMarkers = new LinkedList<>(); List<Marker> doneMarkers = new LinkedList<>();
@@ -241,7 +239,7 @@ public class TrackImporter {
&& trackPoint.getLongitude() == it.getLongitude() && trackPoint.getLongitude() == it.getLongitude()
&& trackPoint.getTime().equals(it.getTime()) && trackPoint.getTime().equals(it.getTime())
) )
.collect(Collectors.toList()); .toList();
TrackStatistics statistics = updater.getTrackStatistics(); TrackStatistics statistics = updater.getTrackStatistics();
for (Marker marker : matchedMarkers) { for (Marker marker : matchedMarkers) {
@@ -729,7 +729,7 @@ public class PreferencesUtils {
R.array.stats_custom_layout_fields_default_value_16, R.array.stats_custom_layout_fields_default_value_16,
R.array.stats_custom_layout_fields_default_value_17, R.array.stats_custom_layout_fields_default_value_17,
R.array.stats_custom_layout_fields_default_value_18 R.array.stats_custom_layout_fields_default_value_18
).map(id -> resources.obtainTypedArray(id)).collect(Collectors.toList()); ).map(id -> resources.obtainTypedArray(id)).toList();
} }
@SuppressLint("ResourceType") @SuppressLint("ResourceType")
@@ -804,7 +804,7 @@ public class PreferencesUtils {
} }
public static List<String> getAllCustomLayoutNames() { public static List<String> getAllCustomLayoutNames() {
return getAllCustomLayouts().stream().map(RecordingLayout::getName).collect(Collectors.toList()); return getAllCustomLayouts().stream().map(RecordingLayout::getName).toList();
} }
public static void resetCustomLayoutPreferences() { public static void resetCustomLayoutPreferences() {
@@ -23,7 +23,6 @@ import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.sensors.BluetoothUtils; import de.dennisguse.opentracks.sensors.BluetoothUtils;
@@ -136,7 +135,7 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
b.putParcelableArrayList(ARG_BLE_SERVICE_UUIDS, new ArrayList<>(sensorUUIDs.stream() b.putParcelableArrayList(ARG_BLE_SERVICE_UUIDS, new ArrayList<>(sensorUUIDs.stream()
.map(ServiceMeasurementUUID::serviceUUID) .map(ServiceMeasurementUUID::serviceUUID)
.map(ParcelUuid::new) .map(ParcelUuid::new)
.collect(Collectors.toList()))); .toList()));
fragment.setArguments(b); fragment.setArguments(b);
return fragment; return fragment;
} }
@@ -202,7 +201,7 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference {
if (PreferencesUtils.getBluetoothFilterEnabled()) { if (PreferencesUtils.getBluetoothFilterEnabled()) {
scanFilter = serviceUUIDs.stream() scanFilter = serviceUUIDs.stream()
.map(it -> new ScanFilter.Builder().setServiceUuid(it).build()) .map(it -> new ScanFilter.Builder().setServiceUuid(it).build())
.collect(Collectors.toList()); .toList();
} }
ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder(); ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
@@ -46,7 +46,7 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
private final SparseBooleanArray selection = new SparseBooleanArray(); private final SparseBooleanArray selection = new SparseBooleanArray();
private RecordingStatus recordingStatus; private RecordingStatus recordingStatus;
private UnitSystem unitSystem; private UnitSystem unitSystem;
private Cursor tracks; private Cursor cursor;
private boolean selectionMode = false; private boolean selectionMode = false;
private ActivityUtils.ContextualActionModeCallback actionModeCallback; private ActivityUtils.ContextualActionModeCallback actionModeCallback;
private ActionMode actionMode; private ActionMode actionMode;
@@ -73,20 +73,20 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ViewHolder viewHolder = (ViewHolder) holder; ViewHolder viewHolder = (ViewHolder) holder;
tracks.moveToPosition(position); cursor.moveToPosition(position);
viewHolder.bind(tracks); viewHolder.bind(cursor);
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
if (tracks == null) { if (cursor == null) {
return 0; return 0;
} }
return tracks.getCount(); return cursor.getCount();
} }
public void swapData(Cursor tracks) { public void swapData(Cursor cursor) {
this.tracks = tracks; this.cursor = cursor;
this.notifyDataSetChanged(); this.notifyDataSetChanged();
} }
@@ -131,12 +131,12 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
public void setAllSelected(boolean isSelected) { public void setAllSelected(boolean isSelected) {
if (isSelected) { if (isSelected) {
final int idIndex = tracks.getColumnIndexOrThrow(TracksColumns._ID); final int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
tracks.moveToFirst(); cursor.moveToFirst();
do { do {
selection.put((int) tracks.getLong(idIndex), true); selection.put((int) cursor.getLong(idIndex), true);
} while (tracks.moveToNext()); } while (cursor.moveToNext());
} else { } else {
selection.clear(); selection.clear();
} }
@@ -164,15 +164,6 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
private final TrackListItemBinding viewBinding; private final TrackListItemBinding viewBinding;
private final View view; private final View view;
private ActivityType activityType;
private String name;
private int markerCount;
private Duration totalTime;
private Distance totalDistance;
private Instant startTime;
private ZoneOffset zoneOffset;
private String activityTypeLocalized;
private String description;
private Track.Id trackId; private Track.Id trackId;
public ViewHolder(@NonNull View itemView) { public ViewHolder(@NonNull View itemView) {
@@ -185,33 +176,29 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
view.setOnLongClickListener(this); view.setOnLongClickListener(this);
} }
private void getData(Cursor track) {
final int idIndex = track.getColumnIndexOrThrow(TracksColumns._ID);
final int nameIndex = track.getColumnIndexOrThrow(TracksColumns.NAME);
final int descriptionIndex = track.getColumnIndexOrThrow(TracksColumns.DESCRIPTION);
final int activityTypeLocalizedIndex = track.getColumnIndexOrThrow(TracksColumns.ACTIVITY_TYPE_LOCALIZED);
final int startTimeIndex = track.getColumnIndexOrThrow(TracksColumns.STARTTIME);
final int startTimeOffsetIndex = track.getColumnIndexOrThrow(TracksColumns.STARTTIME_OFFSET);
final int totalDistanceIndex = track.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
final int totalTimeIndex = track.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
final int iconIndex = track.getColumnIndexOrThrow(TracksColumns.ICON);
final int markerCountIndex = track.getColumnIndexOrThrow(TracksColumns.MARKER_COUNT);
activityType = ActivityType.findBy(track.getString(iconIndex)); public void bind(Cursor cursor) {
name = track.getString(nameIndex); final int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
markerCount = track.getInt(markerCountIndex); final int nameIndex = cursor.getColumnIndexOrThrow(TracksColumns.NAME);
totalTime = Duration.ofMillis(track.getLong(totalTimeIndex)); final int descriptionIndex = cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION);
totalDistance = Distance.of(track.getFloat(totalDistanceIndex)); final int activityTypeIndex = cursor.getColumnIndexOrThrow(TracksColumns.ACTIVITY_TYPE);
startTime = Instant.ofEpochMilli(track.getLong(startTimeIndex)); final int activityTypeLocalizedIndex = cursor.getColumnIndexOrThrow(TracksColumns.ACTIVITY_TYPE_LOCALIZED);
zoneOffset = ZoneOffset.ofTotalSeconds(track.getInt(startTimeOffsetIndex)); final int startTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME);
activityTypeLocalized = track.getString(activityTypeLocalizedIndex); final int startTimeOffsetIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME_OFFSET);
description = track.getString(descriptionIndex); final int totalDistanceIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
trackId = new Track.Id(track.getLong(idIndex)); final int totalTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
} final int markerCountIndex = cursor.getColumnIndexOrThrow(TracksColumns.MARKER_COUNT);
public void bind(Cursor track) { ActivityType activityType = ActivityType.findBy(cursor.getString(activityTypeIndex));
String name = cursor.getString(nameIndex);
getData(track); int markerCount = cursor.getInt(markerCountIndex);
Duration totalTime = Duration.ofMillis(cursor.getLong(totalTimeIndex));
Distance totalDistance = Distance.of(cursor.getFloat(totalDistanceIndex));
Instant startTime = Instant.ofEpochMilli(cursor.getLong(startTimeIndex));
ZoneOffset zoneOffset = ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex));
String activityTypeLocalized = cursor.getString(activityTypeLocalizedIndex);
String description = cursor.getString(descriptionIndex);
trackId = new Track.Id(cursor.getLong(idIndex));
int iconId = activityType.getIconDrawableId(); int iconId = activityType.getIconDrawableId();
int iconDesc = R.string.image_track; int iconDesc = R.string.image_track;
@@ -240,6 +227,7 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
viewBinding.trackListItemTime.setText(null); viewBinding.trackListItemTime.setText(null);
} }
//TODO Check if this is needed or a leftover from the MarkerList migration
String category = activityType == null ? activityTypeLocalized : null; String category = activityType == null ? activityTypeLocalized : null;
String categoryDescription = StringUtils.getCategoryDescription(category, description); String categoryDescription = StringUtils.getCategoryDescription(category, description);
viewBinding.trackListItemCategoryDescription.setText(categoryDescription); viewBinding.trackListItemCategoryDescription.setText(categoryDescription);
@@ -68,7 +68,7 @@ public class RecordingLayout implements Parcelable {
public RecordingLayout toRecordingLayout(boolean visibility) { public RecordingLayout toRecordingLayout(boolean visibility) {
RecordingLayout result = new RecordingLayout(this.getName()); RecordingLayout result = new RecordingLayout(this.getName());
result.addFields(dataFields.stream().filter(f -> f.isVisible() == visibility).collect(Collectors.toList())); result.addFields(dataFields.stream().filter(f -> f.isVisible() == visibility).toList());
return result; return result;
} }
@@ -16,7 +16,6 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
@@ -54,7 +53,7 @@ public class ExportUtils {
public static void exportTrack(Context context, DocumentFile directory, ExportTask exportTask) { public static void exportTrack(Context context, DocumentFile directory, ExportTask exportTask) {
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context); ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context);
List<Track> tracks = exportTask.getTrackIds().stream().map(contentProviderUtils::getTrack).collect(Collectors.toList()); List<Track> tracks = exportTask.getTrackIds().stream().map(contentProviderUtils::getTrack).toList();
Uri exportDocumentFileUri; Uri exportDocumentFileUri;
if (tracks.size() == 1) { if (tracks.size() == 1) {
exportDocumentFileUri = getExportDocumentFileUri(context, tracks.get(0), exportTask.getTrackFileFormat(), directory); exportDocumentFileUri = getExportDocumentFileUri(context, tracks.get(0), exportTask.getTrackFileFormat(), directory);