Skip to content

Commit

Permalink
ActivityType non-localized: store in database.
Browse files Browse the repository at this point in the history
Includes migration of existing data from ActivityType localized or icon.

Part of #1608.
  • Loading branch information
dennisguse committed Oct 8, 2023
1 parent 1f96283 commit e69bf31
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public static Track createTrack(Cursor cursor) {
int uuidIndex = cursor.getColumnIndexOrThrow(TracksColumns.UUID);
int nameIndex = cursor.getColumnIndexOrThrow(TracksColumns.NAME);
int descriptionIndex = cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION);
int activityTypeIndex = cursor.getColumnIndexOrThrow(TracksColumns.ACTIVITY_TYPE);
int activityTypeLocalizedIndex = cursor.getColumnIndexOrThrow(TracksColumns.ACTIVITY_TYPE_LOCALIZED);
int startTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME);
int startTimeOffsetIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME_OFFSET);
Expand All @@ -113,7 +114,6 @@ public static Track createTrack(Cursor cursor) {
int maxAltitudeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAX_ALTITUDE);
int altitudeGainIndex = cursor.getColumnIndexOrThrow(TracksColumns.ALTITUDE_GAIN);
int altitudeLossIndex = cursor.getColumnIndexOrThrow(TracksColumns.ALTITUDE_LOSS);
int iconIndex = cursor.getColumnIndexOrThrow(TracksColumns.ICON);

Track track = new Track(ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex)));
TrackStatistics trackStatistics = track.getTrackStatistics();
Expand All @@ -129,6 +129,9 @@ public static Track createTrack(Cursor cursor) {
if (!cursor.isNull(descriptionIndex)) {
track.setDescription(cursor.getString(descriptionIndex));
}
if (!cursor.isNull(activityTypeIndex)) {
track.setActivityType(ActivityType.findBy(cursor.getString(activityTypeIndex)));
}
if (!cursor.isNull(activityTypeLocalizedIndex)) {
track.setActivityTypeLocalized(cursor.getString(activityTypeLocalizedIndex));
}
Expand Down Expand Up @@ -163,9 +166,7 @@ public static Track createTrack(Cursor cursor) {
if (!cursor.isNull(altitudeLossIndex)) {
trackStatistics.setTotalAltitudeLoss(cursor.getFloat(altitudeLossIndex));
}
if (!cursor.isNull(iconIndex)) {
track.setActivityType(ActivityType.findBy(cursor.getString(iconIndex)));
}

return track;
}

Expand Down Expand Up @@ -230,13 +231,18 @@ public List<Track> getTracks(ContentProviderSelectionInterface selection) {

public Cursor searchTracks(String searchQuery) {
// 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,
TracksColumns.DESCRIPTION, TracksColumns.ACTIVITY_TYPE_LOCALIZED, TracksColumns.STARTTIME,
TracksColumns.STARTTIME_OFFSET, TracksColumns.STOPTIME, TracksColumns.MARKER_COUNT,
TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.MOVINGTIME,
TracksColumns.AVGSPEED, TracksColumns.AVGMOVINGSPEED, TracksColumns.MAXSPEED,
TracksColumns.MIN_ALTITUDE, TracksColumns.MAX_ALTITUDE, TracksColumns.ALTITUDE_GAIN,
TracksColumns.ALTITUDE_LOSS, TracksColumns.ICON
// Used only be TrackListAdapter
final String[] PROJECTION = new String[]{
TracksColumns._ID,
TracksColumns.NAME,
TracksColumns.DESCRIPTION, //TODO Needed?
TracksColumns.ACTIVITY_TYPE,
TracksColumns.ACTIVITY_TYPE_LOCALIZED,
TracksColumns.STARTTIME,
TracksColumns.STARTTIME_OFFSET,
TracksColumns.TOTALDISTANCE,
TracksColumns.TOTALTIME,
TracksColumns.MARKER_COUNT,
};

String selection = null;
Expand Down Expand Up @@ -316,6 +322,7 @@ private ContentValues createContentValues(Track track) {
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid()));
values.put(TracksColumns.NAME, track.getName());
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.STARTTIME_OFFSET, track.getZoneOffset().getTotalSeconds());
if (trackStatistics.getStartTime() != null) {
Expand All @@ -334,7 +341,6 @@ private ContentValues createContentValues(Track track) {
values.put(TracksColumns.MAX_ALTITUDE, trackStatistics.getMaxAltitude());
values.put(TracksColumns.ALTITUDE_GAIN, trackStatistics.getTotalAltitudeGain());
values.put(TracksColumns.ALTITUDE_LOSS, trackStatistics.getTotalAltitudeLoss());
values.put(TracksColumns.ICON, track.getActivityType() != null ? track.getActivityType().getIconId() : "");

return values;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.zone.ZoneRules;
import java.util.Map;
import java.util.UUID;

import de.dennisguse.opentracks.Startup;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.tables.MarkerColumns;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
Expand All @@ -28,7 +30,9 @@ public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {

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) {
this(context, ((Startup) context.getApplicationContext()).getDatabaseName());
Expand All @@ -37,11 +41,13 @@ public CustomSQLiteOpenHelper(Context context) {
@VisibleForTesting
public CustomSQLiteOpenHelper(Context context, String databaseName) {
super(context, databaseName, null, DATABASE_VERSION);
this.context = context;
}

@VisibleForTesting
public CustomSQLiteOpenHelper(Context context, String databaseName, int databaseVersion) {
super(context, databaseName, null, databaseVersion);
this.context = context;
}

@Override
Expand Down Expand Up @@ -75,6 +81,7 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
case 34 -> upgradeFrom33to34(db);
case 35 -> upgradeFrom34to35(db);
case 36 -> upgradeFrom35to36(db);
case 37 -> upgradeFrom36to37(db);
default -> throw new RuntimeException("Not implemented: upgrade to " + toVersion);
}
}
Expand All @@ -98,6 +105,7 @@ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
case 33 -> downgradeFrom34to33(db);
case 34 -> downgradeFrom35to34(db);
case 35 -> downgradeFrom36to35(db);
case 36 -> downgradeFrom37to36(db);
default -> throw new RuntimeException("Not implemented: downgrade to " + toVersion);
}
}
Expand Down Expand Up @@ -170,7 +178,7 @@ private void upgradeFrom25to26(SQLiteDatabase db) {
db.beginTransaction();

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()) {
int trackIdIndex = cursor.getColumnIndexOrThrow("_id");
do {
Expand Down Expand Up @@ -445,7 +453,7 @@ private void upgradeFrom32to33(SQLiteDatabase db) {

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()) {
int trackIdIndex = cursor.getColumnIndexOrThrow("_id");
int startTimeIndex = cursor.getColumnIndexOrThrow("starttime");
Expand Down Expand Up @@ -564,4 +572,77 @@ private void downgradeFrom36to35(SQLiteDatabase db) {
db.setTransactionSuccessful();
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();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,8 @@

import de.dennisguse.opentracks.R;

public enum 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);
public class ActivityIcon {

@Deprecated //TODO should be removed.
final String iconId;
final int iconDrawableId;
static final int ICON_UNKNOWN = R.drawable.ic_logo_24dp;

ActivityIcon(String iconId, int iconDrawableId) {
this.iconId = iconId;
this.iconDrawableId = iconDrawableId;
}
}
Loading

0 comments on commit e69bf31

Please sign in to comment.