From 77e6dc1b73d2ff3f597802e3064c4ae6054e6000 Mon Sep 17 00:00:00 2001 From: Jimmy Shih Date: Wed, 23 Jan 2013 13:06:28 -0800 Subject: [PATCH] Add columns driveid, modifiedtime, and sharedwithme Add tombstone when a track is deleted --- .../mytracks/content/MyTracksProvider.java | 89 +++++++++-- .../content/MyTracksProviderUtilsImpl.java | 15 ++ .../android/apps/mytracks/content/Track.java | 54 +++++-- .../apps/mytracks/content/TracksColumns.java | 142 ++++++++++-------- 4 files changed, 217 insertions(+), 83 deletions(-) diff --git a/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProvider.java b/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProvider.java index 29bf4ea4d..a767178fc 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProvider.java +++ b/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProvider.java @@ -37,6 +37,8 @@ import android.os.Process; import android.text.TextUtils; import android.util.Log; +import java.util.ArrayList; + /** * A {@link ContentProvider} that handles access to track points, tracks, and * waypoints tables. @@ -46,32 +48,35 @@ import android.util.Log; public class MyTracksProvider extends ContentProvider { private static final String TAG = MyTracksProvider.class.getSimpleName(); + private static final int DATABASE_VERSION = 21; + private static final String DRIVE_IDS_QUERY = TracksColumns.DRIVEID + " IS NOT NULL AND " + + TracksColumns.DRIVEID + "!=''"; + @VisibleForTesting static final String DATABASE_NAME = "mytracks.db"; - private static final int DATABASE_VERSION = 20; /** * Database helper for creating and upgrading the database. */ @VisibleForTesting static class DatabaseHelper extends SQLiteOpenHelper { - + public DatabaseHelper(Context context) { this(context, DATABASE_NAME); } - + @VisibleForTesting public DatabaseHelper(Context context, String databaseName) { super(context, databaseName, null, DATABASE_VERSION); } - + @Override public void onCreate(SQLiteDatabase db) { db.execSQL(TrackPointsColumns.CREATE_TABLE); db.execSQL(TracksColumns.CREATE_TABLE); db.execSQL(WaypointsColumns.CREATE_TABLE); } - + @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion); @@ -83,25 +88,40 @@ public class MyTracksProvider extends ContentProvider { onCreate(db); } else { // Incremental upgrades. One if statement per DB version. - + // Add track points SENSOR column if (oldVersion <= 17) { Log.w(TAG, "Upgrade DB: Adding sensor column."); db.execSQL("ALTER TABLE " + TrackPointsColumns.TABLE_NAME + " ADD " + TrackPointsColumns.SENSOR + " BLOB"); } + // Add tracks TABLEID column if (oldVersion <= 18) { Log.w(TAG, "Upgrade DB: Adding tableid column."); db.execSQL("ALTER TABLE " + TracksColumns.TABLE_NAME + " ADD " + TracksColumns.TABLEID + " STRING"); } + // Add tracks ICON column if (oldVersion <= 19) { Log.w(TAG, "Upgrade DB: Adding icon column."); db.execSQL( "ALTER TABLE " + TracksColumns.TABLE_NAME + " ADD " + TracksColumns.ICON + " STRING"); } + + // Add track DRIVEID, MODIFIEDTIME, and SHAREDWITHME columns + if (oldVersion <= 20) { + Log.w(TAG, "Upgrade DB: Adding driveid column."); + db.execSQL("ALTER TABLE " + TracksColumns.TABLE_NAME + " ADD " + TracksColumns.DRIVEID + + " STRING"); + Log.w(TAG, "Upgrade DB: Adding modifiedtime column."); + db.execSQL("ALTER TABLE " + TracksColumns.TABLE_NAME + " ADD " + + TracksColumns.MODIFIEDTIME + " INTEGER"); + Log.w(TAG, "Upgrade DB: Adding sharedwithme column."); + db.execSQL("ALTER TABLE " + TracksColumns.TABLE_NAME + " ADD " + + TracksColumns.SHAREDWITHME + " INTEGER"); + } } } } @@ -139,9 +159,10 @@ public class MyTracksProvider extends ContentProvider { public boolean onCreate() { return onCreate(getContext()); } - + /** * Helper method to make onCreate is testable. + * * @param context context to creates database * @return true means run successfully */ @@ -180,7 +201,18 @@ public class MyTracksProvider extends ContentProvider { default: throw new IllegalArgumentException("Unknown URL " + url); } - + + boolean driveSync = false; + String driveIds = ""; + if (table.equals(TracksColumns.TABLE_NAME)) { + driveSync = PreferencesUtils.getBoolean( + getContext(), R.string.drive_sync_key, PreferencesUtils.DRIVE_SYNC_DEFAULT); + if (driveSync) { + driveIds = where != null ? getDriveIds(null, where, selectionArgs) + : getDriveIds(new String[] { TracksColumns.DRIVEID }, DRIVE_IDS_QUERY, null); + } + } + Log.w(MyTracksProvider.TAG, "Deleting table " + table); int count; try { @@ -190,8 +222,20 @@ public class MyTracksProvider extends ContentProvider { } finally { db.endTransaction(); } + + if (driveSync && table.equals(TracksColumns.TABLE_NAME)) { + String driveDeletedList = PreferencesUtils.getString(getContext(), + R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT); + if (driveDeletedList.equals(PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT)) { + driveDeletedList = driveIds; + } else { + driveDeletedList += ";" + driveIds; + } + PreferencesUtils.setString(getContext(), R.string.drive_deleted_list_key, driveDeletedList); + } + getContext().getContentResolver().notifyChange(url, null, true); - + if (shouldVacuum) { // If a potentially large amount of data was deleted, reclaim its space. Log.i(TAG, "Vacuuming the database."); @@ -251,7 +295,7 @@ public class MyTracksProvider extends ContentProvider { try { // Use a transaction in order to make the insertions run as a single batch db.beginTransaction(); - + UrlType urlType = getUrlType(url); for (numInserted = 0; numInserted < valuesBulk.length; numInserted++) { ContentValues contentValues = valuesBulk[numInserted]; @@ -464,4 +508,29 @@ public class MyTracksProvider extends ContentProvider { } throw new SQLException("Failed to insert a waypoint " + url); } + + /** + * Gets a list of dirve ids. + * + * @param projection the projection + * @param where where + * @param selectionArgs selection args + */ + private String getDriveIds(String[] projection, String where, String[] selectionArgs) { + ArrayList driveIds = new ArrayList(); + Cursor cursor = query(TracksColumns.CONTENT_URI, projection, where, selectionArgs, null); + if (cursor != null) { + int index = cursor.getColumnIndex(TracksColumns.DRIVEID); + if (cursor.moveToFirst()) { + do { + String driveId = cursor.getString(index); + if (driveId != null && !driveId.equals("")) { + driveIds.add(driveId); + } + } while (cursor.moveToNext()); + } + cursor.close(); + } + return TextUtils.join(";", driveIds); + } } \ No newline at end of file diff --git a/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java b/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java index d5b95e18d..6f3a7bbb6 100644 --- a/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java +++ b/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java @@ -85,6 +85,9 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { int mapIdIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAPID); int tableIdIndex = cursor.getColumnIndexOrThrow(TracksColumns.TABLEID); int iconIndex = cursor.getColumnIndexOrThrow(TracksColumns.ICON); + int driveIdIndex = cursor.getColumnIndexOrThrow(TracksColumns.DRIVEID); + int modifiedTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MODIFIEDTIME); + int sharedWithMeIndex = cursor.getColumnIndexOrThrow(TracksColumns.SHAREDWITHME); Track track = new Track(); TripStatistics tripStatistics = track.getTripStatistics(); @@ -159,6 +162,15 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { if (!cursor.isNull(iconIndex)) { track.setIcon(cursor.getString(iconIndex)); } + if (!cursor.isNull(driveIdIndex)) { + track.setDriveId(cursor.getString(driveIdIndex)); + } + if (!cursor.isNull(modifiedTimeIndex)) { + track.setModifiedTime(cursor.getLong(modifiedTimeIndex)); + } + if (!cursor.isNull(sharedWithMeIndex)) { + track.setSharedWithMe(cursor.getInt(sharedWithMeIndex) == 1); + } return track; } @@ -302,6 +314,9 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { values.put(TracksColumns.MAPID, track.getMapId()); values.put(TracksColumns.TABLEID, track.getTableId()); values.put(TracksColumns.ICON, track.getIcon()); + values.put(TracksColumns.DRIVEID, track.getDriveId()); + values.put(TracksColumns.MODIFIEDTIME, track.getModifiedTime()); + values.put(TracksColumns.SHAREDWITHME, track.isSharedWithMe()); return values; } diff --git a/MyTracksLib/src/com/google/android/apps/mytracks/content/Track.java b/MyTracksLib/src/com/google/android/apps/mytracks/content/Track.java index d3656a64e..84e8d3c22 100644 --- a/MyTracksLib/src/com/google/android/apps/mytracks/content/Track.java +++ b/MyTracksLib/src/com/google/android/apps/mytracks/content/Track.java @@ -32,19 +32,24 @@ import java.util.ArrayList; */ public class Track implements Parcelable { - private long id = -1; + private long id = -1L; private String name = ""; private String description = ""; private String category = ""; - private long startId = -1; - private long stopId = -1; + private long startId = -1L; + private long stopId = -1L; - // The number of location points (present even if the points themselves are - // not loaded) + /* + * The number of location points (present even if the points themselves are + * not loaded) + */ private int numberOfPoints = 0; private String mapId = ""; private String tableId = ""; private String icon = ""; + private String driveId = ""; + private long modifiedTime = -1L; + private boolean sharedWithMe = false; private TripStatistics tripStatistics = new TripStatistics(); @@ -64,13 +69,16 @@ public class Track implements Parcelable { mapId = in.readString(); tableId = in.readString(); icon = in.readString(); + driveId = in.readString(); + modifiedTime = in.readLong(); + sharedWithMe = in.readByte() == 1; ClassLoader classLoader = getClass().getClassLoader(); tripStatistics = in.readParcelable(classLoader); for (int i = 0; i < numberOfPoints; ++i) { - Location loc = in.readParcelable(classLoader); - locations.add(loc); + Location location = in.readParcelable(classLoader); + locations.add(location); } } @@ -91,6 +99,10 @@ public class Track implements Parcelable { dest.writeString(mapId); dest.writeString(tableId); dest.writeString(icon); + dest.writeString(driveId); + dest.writeLong(modifiedTime); + dest.writeByte((byte) (sharedWithMe ? 1 : 0)); + dest.writeParcelable(tripStatistics, 0); for (int i = 0; i < numberOfPoints; ++i) { dest.writeParcelable(locations.get(i), 0); @@ -189,6 +201,30 @@ public class Track implements Parcelable { this.icon = icon; } + public String getDriveId() { + return driveId; + } + + public void setDriveId(String driveId) { + this.driveId = driveId; + } + + public long getModifiedTime() { + return modifiedTime; + } + + public void setModifiedTime(long modifiedTime) { + this.modifiedTime = modifiedTime; + } + + public boolean isSharedWithMe() { + return sharedWithMe; + } + + public void setSharedWithMe(boolean sharedWithMe) { + this.sharedWithMe = sharedWithMe; + } + public TripStatistics getTripStatistics() { return tripStatistics; } @@ -197,8 +233,8 @@ public class Track implements Parcelable { this.tripStatistics = tripStatistics; } - public void addLocation(Location l) { - locations.add(l); + public void addLocation(Location location) { + locations.add(location); } public ArrayList getLocations() { diff --git a/MyTracksLib/src/com/google/android/apps/mytracks/content/TracksColumns.java b/MyTracksLib/src/com/google/android/apps/mytracks/content/TracksColumns.java index 916485c50..8ed4d2c67 100644 --- a/MyTracksLib/src/com/google/android/apps/mytracks/content/TracksColumns.java +++ b/MyTracksLib/src/com/google/android/apps/mytracks/content/TracksColumns.java @@ -66,7 +66,9 @@ public interface TracksColumns extends BaseColumns { public static final String MINLON = "minlon"; // minimum longitude public static final String MAXLON = "maxlon"; // maximum longitude public static final String AVGSPEED = "avgspeed"; // average speed - public static final String AVGMOVINGSPEED = "avgmovingspeed"; // average moving speed + + // average moving speed + public static final String AVGMOVINGSPEED = "avgmovingspeed"; public static final String MAXSPEED = "maxspeed"; // maximum speed public static final String MINELEVATION = "minelevation"; // minimum elevation public static final String MAXELEVATION = "maxelevation"; // maximum elevation @@ -76,69 +78,78 @@ public interface TracksColumns extends BaseColumns { public static final String MAPID = "mapid"; // Google Maps id public static final String TABLEID = "tableid"; // Google Fusion Tables id public static final String ICON = "icon"; // track activity type icon - - public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" - + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + NAME + " STRING, " - + DESCRIPTION + " STRING, " - + CATEGORY + " STRING, " - + STARTID + " INTEGER, " - + STOPID + " INTEGER, " - + STARTTIME + " INTEGER, " - + STOPTIME + " INTEGER, " - + NUMPOINTS + " INTEGER, " - + TOTALDISTANCE + " FLOAT, " - + TOTALTIME + " INTEGER, " - + MOVINGTIME + " INTEGER, " - + MINLAT + " INTEGER, " - + MAXLAT + " INTEGER, " - + MINLON + " INTEGER, " - + MAXLON + " INTEGER, " - + AVGSPEED + " FLOAT, " - + AVGMOVINGSPEED + " FLOAT, " - + MAXSPEED + " FLOAT, " - + MINELEVATION + " FLOAT, " - + MAXELEVATION + " FLOAT, " - + ELEVATIONGAIN + " FLOAT, " - + MINGRADE + " FLOAT, " - + MAXGRADE + " FLOAT, " - + MAPID + " STRING, " - + TABLEID + " STRING, " - + ICON + " STRING" - + ");"; + public static final String DRIVEID = "driveid"; // Google Drive file id - public static final String[] COLUMNS = { - _ID, - NAME, - DESCRIPTION, - CATEGORY, - STARTID, - STOPID, - STARTTIME, - STOPTIME, - NUMPOINTS, - TOTALDISTANCE, - TOTALTIME, - MOVINGTIME, - MINLAT, - MAXLAT, - MINLON, - MAXLON, - AVGSPEED, - AVGMOVINGSPEED, - MAXSPEED, - MINELEVATION, - MAXELEVATION, - ELEVATIONGAIN, - MINGRADE, - MAXGRADE, - MAPID, - TABLEID, - ICON - }; + // Google drive file modified time + public static final String MODIFIEDTIME = "modifiedtime"; - public static final byte[] COLUMN_TYPES = { - ContentTypeIds.LONG_TYPE_ID, // id + // 1 if the Google Drive file is from the "Shared with me" directory + public static final String SHAREDWITHME = "sharedwithme"; + + public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" // table + + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " // id + + NAME + " STRING, " // name + + DESCRIPTION + " STRING, " // description + + CATEGORY + " STRING, " // category + + STARTID + " INTEGER, " // start id + + STOPID + " INTEGER, " // stop id + + STARTTIME + " INTEGER, " // start time + + STOPTIME + " INTEGER, " // stop time + + NUMPOINTS + " INTEGER, " // num points + + TOTALDISTANCE + " FLOAT, " // total distance + + TOTALTIME + " INTEGER, " // total time + + MOVINGTIME + " INTEGER, " // moving time + + MINLAT + " INTEGER, " // min latitude + + MAXLAT + " INTEGER, " // max latitude + + MINLON + " INTEGER, " // min longitude + + MAXLON + " INTEGER, " // max longitude + + AVGSPEED + " FLOAT, " // average speed + + AVGMOVINGSPEED + " FLOAT, " // average moving speed + + MAXSPEED + " FLOAT, " // max speed + + MINELEVATION + " FLOAT, " // min elevation + + MAXELEVATION + " FLOAT, " // max elevation + + ELEVATIONGAIN + " FLOAT, " // elevation gain + + MINGRADE + " FLOAT, " // min grade + + MAXGRADE + " FLOAT, " // max grade + + MAPID + " STRING, " // map id + + TABLEID + " STRING, " // table id + + ICON + " STRING, " // icon + + DRIVEID + " STRING, " // drive id + + MODIFIEDTIME + " INTEGER, " // modified time + + SHAREDWITHME + " INTEGER" + ");"; // shared with me + + public static final String[] COLUMNS = { _ID, // id + NAME, // name + DESCRIPTION, // description + CATEGORY, // category + STARTID, // start id + STOPID, // stop id + STARTTIME, // start time + STOPTIME, // stop time + NUMPOINTS, // num points + TOTALDISTANCE, // total distance + TOTALTIME, // total time + MOVINGTIME, // moving time + MINLAT, // min latitude + MAXLAT, // max latitude + MINLON, // min longitude + MAXLON, // max longitude + AVGSPEED, // average speed + AVGMOVINGSPEED, // average moving speed + MAXSPEED, // max speed + MINELEVATION, // min elevation + MAXELEVATION, // max elevation + ELEVATIONGAIN, // elevation gain + MINGRADE, // min grade + MAXGRADE, // max grade + MAPID, // map id + TABLEID, // table id + ICON, // icon + DRIVEID, // drive id + MODIFIEDTIME, // modified time + SHAREDWITHME }; // shared with me + + public static final byte[] COLUMN_TYPES = { ContentTypeIds.LONG_TYPE_ID, // id ContentTypeIds.STRING_TYPE_ID, // name ContentTypeIds.STRING_TYPE_ID, // description ContentTypeIds.STRING_TYPE_ID, // category @@ -164,6 +175,9 @@ public interface TracksColumns extends BaseColumns { ContentTypeIds.FLOAT_TYPE_ID, // max grade ContentTypeIds.STRING_TYPE_ID, // map id ContentTypeIds.STRING_TYPE_ID, // table id - ContentTypeIds.STRING_TYPE_ID // icon - }; + ContentTypeIds.STRING_TYPE_ID, // icon + ContentTypeIds.STRING_TYPE_ID, // drive id + ContentTypeIds.LONG_TYPE_ID, // modified time + ContentTypeIds.BOOLEAN_TYPE_ID // shared with me + }; }