From 9e5204934fd7c9f2ea3bc57e17c17e7cafc659d2 Mon Sep 17 00:00:00 2001 From: Jimmy Shih Date: Fri, 7 Oct 2011 16:23:59 -0700 Subject: [PATCH] Protect MyTracksProvider based on the MyTracks settings bit. Move MyTracksProvider to DatabaseProvider and protect the DatabaseProvider using the AndroidManifest.xml. Create a MyTracksProviderUtilFactory to create an instance of MyTracksProviderUtils that accesses the DatabaseProvider. Recreate MyTracksProvider by extending DatabaseProvider. The recreated provider checks access, changes the authority, and invokes the DatabaseProvider methods. --- MyTracks/AndroidManifest.xml | 6 + .../mytracks/AggregatedStatsActivity.java | 3 +- .../apps/mytracks/DeleteAllTracks.java | 4 +- .../android/apps/mytracks/DeleteTrack.java | 7 +- .../apps/mytracks/ExportAllTracks.java | 4 +- .../apps/mytracks/ImportAllTracks.java | 3 +- .../android/apps/mytracks/MapActivity.java | 5 +- .../android/apps/mytracks/MyTracks.java | 5 +- .../android/apps/mytracks/TrackDetails.java | 6 +- .../android/apps/mytracks/TrackList.java | 4 +- .../apps/mytracks/WaypointDetails.java | 6 +- .../android/apps/mytracks/WaypointsList.java | 9 +- .../mytracks/content/DataSourceManager.java | 7 +- .../mytracks/content/DatabaseProvider.java | 434 +++++++++++++++++ .../mytracks/content/MyTracksProvider.java | 452 +++--------------- .../content/MyTracksProviderUtilsFactory.java | 37 ++ .../apps/mytracks/content/TrackDataHub.java | 2 +- .../android/apps/mytracks/io/SendToDocs.java | 5 +- .../apps/mytracks/io/SendToFusionTables.java | 3 +- .../apps/mytracks/io/SendToMyMaps.java | 4 +- .../io/backup/ExternalFileBackup.java | 24 +- .../apps/mytracks/io/file/ImportActivity.java | 5 +- .../apps/mytracks/io/file/SaveActivity.java | 11 +- .../io/sendtogoogle/SendActivity.java | 10 +- .../maps/DynamicSpeedTrackPathDescriptor.java | 4 +- .../services/TrackRecordingService.java | 5 + .../mytracks/widgets/TrackWidgetProvider.java | 5 +- .../content/MyTracksProviderUtils.java | 9 +- .../content/MyTracksProviderUtilsImpl.java | 102 ++-- .../mytracks/content/TrackPointsColumns.java | 10 +- .../apps/mytracks/content/TracksColumns.java | 9 +- .../mytracks/content/WaypointsColumns.java | 9 +- .../android/apps/mytracks/MapOverlayTest.java | 4 - .../MyTracksProviderUtilsImplTest.java | 6 +- .../mytracks/content/TrackDataHubTest.java | 18 +- .../mytracks/io/file/GpxImporterTest.java | 5 +- .../mytracks/io/file/TrackWriterTest.java | 9 +- .../TrackPathDescriptorDynamicSpeedTest.java | 7 +- .../TrackPathDescriptorFixedSpeedTest.java | 4 - .../maps/TrackPathPainterFactoryTest.java | 7 +- .../maps/TrackPathPainterSingleColorTest.java | 4 - .../services/TrackRecordingServiceTest.java | 39 +- 42 files changed, 752 insertions(+), 560 deletions(-) create mode 100644 MyTracks/src/com/google/android/apps/mytracks/content/DatabaseProvider.java create mode 100644 MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsFactory.java diff --git a/MyTracks/AndroidManifest.xml b/MyTracks/AndroidManifest.xml index b928d7c8e..be4d8de86 100755 --- a/MyTracks/AndroidManifest.xml +++ b/MyTracks/AndroidManifest.xml @@ -34,6 +34,12 @@ limitations under the License. android:readPermission="com.google.android.apps.mytracks.READ_TRACK_DATA" android:writePermission="com.google.android.apps.mytracks.WRITE_TRACK_DATA" /> + + diff --git a/MyTracks/src/com/google/android/apps/mytracks/AggregatedStatsActivity.java b/MyTracks/src/com/google/android/apps/mytracks/AggregatedStatsActivity.java index 3e2767bf2..0a1128233 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/AggregatedStatsActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/AggregatedStatsActivity.java @@ -1,5 +1,6 @@ package com.google.android.apps.mytracks; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.stats.TripStatistics; @@ -57,7 +58,7 @@ public class AggregatedStatsActivity extends Activity implements protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - this.tracksProvider = MyTracksProviderUtils.Factory.get(this); + this.tracksProvider = MyTracksProviderUtilsFactory.get(this); // We don't need a window title bar: requestWindowFeature(Window.FEATURE_NO_TITLE); diff --git a/MyTracks/src/com/google/android/apps/mytracks/DeleteAllTracks.java b/MyTracks/src/com/google/android/apps/mytracks/DeleteAllTracks.java index 55516eb36..69791abde 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/DeleteAllTracks.java +++ b/MyTracks/src/com/google/android/apps/mytracks/DeleteAllTracks.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks; -import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.util.ApiFeatures; import com.google.android.maps.mytracks.R; @@ -59,7 +59,7 @@ public class DeleteAllTracks extends Handler { public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); Log.w(Constants.TAG, "deleting all!"); - MyTracksProviderUtils.Factory.get(context).deleteAllTracks(); + MyTracksProviderUtilsFactory.get(context).deleteAllTracks(); SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0); SharedPreferences.Editor editor = prefs.edit(); diff --git a/MyTracks/src/com/google/android/apps/mytracks/DeleteTrack.java b/MyTracks/src/com/google/android/apps/mytracks/DeleteTrack.java index 1b73e8f68..5c51628ab 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/DeleteTrack.java +++ b/MyTracks/src/com/google/android/apps/mytracks/DeleteTrack.java @@ -18,6 +18,7 @@ package com.google.android.apps.mytracks; import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.util.ApiFeatures; import com.google.android.apps.mytracks.util.UriUtils; @@ -53,13 +54,13 @@ public class DeleteTrack extends Activity protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - providerUtils = MyTracksProviderUtils.Factory.get(this); + providerUtils = MyTracksProviderUtilsFactory.get(this); Intent intent = getIntent(); String action = intent.getAction(); Uri data = intent.getData(); - if (!Intent.ACTION_DELETE.equals(action) || - !UriUtils.matchesContentUri(data, TracksColumns.CONTENT_URI)) { + if (!Intent.ACTION_DELETE.equals(action) + || !UriUtils.matchesContentUri(data, TracksColumns.DATABASE_CONTENT_URI)) { Log.e(TAG, "Got bad delete intent: " + intent); finish(); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java b/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java index e9aabc2e5..30db1e285 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java +++ b/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java @@ -15,6 +15,7 @@ */ package com.google.android.apps.mytracks; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.io.file.TrackWriter; @@ -148,8 +149,7 @@ public class ExportAllTracks { // Get a cursor over all tracks. Cursor cursor = null; try { - MyTracksProviderUtils providerUtils = - MyTracksProviderUtils.Factory.get(activity); + MyTracksProviderUtils providerUtils = MyTracksProviderUtilsFactory.get(activity); cursor = providerUtils.getTracksCursor(""); if (cursor == null) { return; diff --git a/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java b/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java index dfea7d5d5..9e9983e0d 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java +++ b/MyTracks/src/com/google/android/apps/mytracks/ImportAllTracks.java @@ -15,6 +15,7 @@ */ package com.google.android.apps.mytracks; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.io.file.GpxImporter; import com.google.android.apps.mytracks.util.FileUtils; @@ -132,7 +133,7 @@ public class ImportAllTracks { * been acquired. */ private void importAll() { - MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(activity); + MyTracksProviderUtils providerUtils = MyTracksProviderUtilsFactory.get(activity); if (!fileUtils.isSdCardAvailable()) { return; diff --git a/MyTracks/src/com/google/android/apps/mytracks/MapActivity.java b/MyTracks/src/com/google/android/apps/mytracks/MapActivity.java index d7f5b8ce8..0978c54ed 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MapActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MapActivity.java @@ -18,6 +18,7 @@ package com.google.android.apps.mytracks; import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.TrackDataHub; import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType; @@ -317,7 +318,7 @@ public class MapActivity extends com.google.android.maps.MapActivity * Zooms and pans the map so that the given waypoint is visible. */ public void showWaypoint(long waypointId) { - MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(this); + MyTracksProviderUtils providerUtils = MyTracksProviderUtilsFactory.get(this); Waypoint wpt = providerUtils.getWaypoint(waypointId); if (wpt != null && wpt.getLocation() != null) { keepMyLocationVisible = false; @@ -424,7 +425,7 @@ public class MapActivity extends com.google.android.maps.MapActivity } case Constants.MENU_DELETE: { Uri uri = ContentUris.withAppendedId( - TracksColumns.CONTENT_URI, dataHub.getSelectedTrackId()); + TracksColumns.DATABASE_CONTENT_URI, dataHub.getSelectedTrackId()); Intent intent = new Intent(Intent.ACTION_DELETE, uri); startActivity(intent); return true; diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java b/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java index 2071bf948..5fdaf5e28 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MyTracks.java @@ -19,6 +19,7 @@ import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.analytics.GoogleAnalyticsTracker; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.TrackDataHub; import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.content.WaypointCreationRequest; @@ -144,7 +145,7 @@ public class MyTracks extends TabActivity implements OnTouchListener { tracker.trackPageView("/appstart"); tracker.dispatch(); - providerUtils = MyTracksProviderUtils.Factory.get(this); + providerUtils = MyTracksProviderUtilsFactory.get(this); preferences = getSharedPreferences(Constants.SETTINGS_NAME, 0); dataHub = ((MyTracksApplication) getApplication()).getTrackDataHub(); menuManager = new MenuManager(this); @@ -208,7 +209,7 @@ public class MyTracks extends TabActivity implements OnTouchListener { Uri data = intent.getData(); if ((Intent.ACTION_VIEW.equals(action) || Intent.ACTION_EDIT.equals(action)) && TracksColumns.CONTENT_ITEMTYPE.equals(intent.getType()) - && UriUtils.matchesContentUri(data, TracksColumns.CONTENT_URI)) { + && UriUtils.matchesContentUri(data, TracksColumns.DATABASE_CONTENT_URI)) { long trackId = ContentUris.parseId(data); dataHub.loadTrack(trackId); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/TrackDetails.java b/MyTracks/src/com/google/android/apps/mytracks/TrackDetails.java index fcdd4dfa0..c504bc433 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/TrackDetails.java +++ b/MyTracks/src/com/google/android/apps/mytracks/TrackDetails.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks; -import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.maps.mytracks.R; @@ -89,7 +89,7 @@ public class TrackDetails extends Activity implements OnClickListener { } private void fillDialog() { - Track track = MyTracksProviderUtils.Factory.get(this).getTrack(trackId); + Track track = MyTracksProviderUtilsFactory.get(this).getTrack(trackId); if (track != null) { name.setText(track.getName()); description.setText(track.getDescription()); @@ -103,7 +103,7 @@ public class TrackDetails extends Activity implements OnClickListener { values.put(TracksColumns.DESCRIPTION, description.getText().toString()); values.put(TracksColumns.CATEGORY, category.getText().toString()); getContentResolver().update( - TracksColumns.CONTENT_URI, + TracksColumns.DATABASE_CONTENT_URI, values, "_id = " + trackId, null/*selectionArgs*/); diff --git a/MyTracks/src/com/google/android/apps/mytracks/TrackList.java b/MyTracks/src/com/google/android/apps/mytracks/TrackList.java index cf0defa44..9e8bfb4be 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/TrackList.java +++ b/MyTracks/src/com/google/android/apps/mytracks/TrackList.java @@ -189,7 +189,7 @@ public class TrackList extends ListActivity return true; case Constants.MENU_DELETE: { Intent intent = new Intent(Intent.ACTION_DELETE); - Uri uri = ContentUris.withAppendedId(TracksColumns.CONTENT_URI, trackId); + Uri uri = ContentUris.withAppendedId(TracksColumns.DATABASE_CONTENT_URI, trackId); intent.setDataAndType(uri, TracksColumns.CONTENT_ITEMTYPE); startActivity(intent); return true; @@ -251,7 +251,7 @@ public class TrackList extends ListActivity preferences.getLong(getString(R.string.recording_track_key), -1); tracksCursor = getContentResolver().query( - TracksColumns.CONTENT_URI, null, null, null, "_id DESC"); + TracksColumns.DATABASE_CONTENT_URI, null, null, null, "_id DESC"); startManagingCursor(tracksCursor); setListAdapter(); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/WaypointDetails.java b/MyTracks/src/com/google/android/apps/mytracks/WaypointDetails.java index 92d04fad9..eab98a24c 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/WaypointDetails.java +++ b/MyTracks/src/com/google/android/apps/mytracks/WaypointDetails.java @@ -15,7 +15,7 @@ */ package com.google.android.apps.mytracks; -import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.WaypointsColumns; import com.google.android.apps.mytracks.stats.TripStatistics; @@ -119,7 +119,7 @@ public class WaypointDetails extends Activity } private void fillDialog() { - waypoint = MyTracksProviderUtils.Factory.get(this).getWaypoint(waypointId); + waypoint = MyTracksProviderUtilsFactory.get(this).getWaypoint(waypointId); if (waypoint != null) { name.setText(waypoint.getName()); ImageView icon = (ImageView) findViewById(R.id.waypointdetails_icon); @@ -156,7 +156,7 @@ public class WaypointDetails extends Activity values.put(WaypointsColumns.CATEGORY, category.getText().toString()); } getContentResolver().update( - WaypointsColumns.CONTENT_URI, + WaypointsColumns.DATABASE_CONTENT_URI, values, "_id = " + waypointId, null /*selectionArgs*/); diff --git a/MyTracks/src/com/google/android/apps/mytracks/WaypointsList.java b/MyTracks/src/com/google/android/apps/mytracks/WaypointsList.java index ecfe1b733..3e3f37ff6 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/WaypointsList.java +++ b/MyTracks/src/com/google/android/apps/mytracks/WaypointsList.java @@ -18,6 +18,7 @@ package com.google.android.apps.mytracks; import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.WaypointCreationRequest; import com.google.android.apps.mytracks.content.WaypointsColumns; @@ -134,7 +135,7 @@ public class WaypointsList extends ListActivity protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - providerUtils = MyTracksProviderUtils.Factory.get(this); + providerUtils = MyTracksProviderUtilsFactory.get(this); serviceConnection = new TrackRecordingServiceConnection(this, null); // We don't need a window title bar: @@ -174,10 +175,10 @@ public class WaypointsList extends ListActivity } final long firstWaypointId = providerUtils.getFirstWaypointId(trackId); + String selection = WaypointsColumns.TRACKID + "=" + trackId + " AND " + WaypointsColumns._ID + + "!=" + firstWaypointId; waypointsCursor = getContentResolver().query( - WaypointsColumns.CONTENT_URI, null, - WaypointsColumns.TRACKID + "=" + trackId + " AND " - + WaypointsColumns._ID + "!=" + firstWaypointId, null, null); + WaypointsColumns.DATABASE_CONTENT_URI, null, selection, null, null); startManagingCursor(waypointsCursor); setListAdapter(); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/content/DataSourceManager.java b/MyTracks/src/com/google/android/apps/mytracks/content/DataSourceManager.java index 90c1e914d..9b16bd157 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/content/DataSourceManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/content/DataSourceManager.java @@ -211,14 +211,15 @@ class DataSourceManager { break; case POINT_UPDATES: dataSources.registerContentObserver( - TrackPointsColumns.CONTENT_URI, false, pointObserver); + TrackPointsColumns.DATABASE_CONTENT_URI, false, pointObserver); break; case TRACK_UPDATES: - dataSources.registerContentObserver(TracksColumns.CONTENT_URI, false, trackObserver); + dataSources.registerContentObserver( + TracksColumns.DATABASE_CONTENT_URI, false, trackObserver); break; case WAYPOINT_UPDATES: dataSources.registerContentObserver( - WaypointsColumns.CONTENT_URI, false, waypointObserver); + WaypointsColumns.DATABASE_CONTENT_URI, false, waypointObserver); break; case DISPLAY_PREFERENCES: dataSources.registerOnSharedPreferenceChangeListener(preferenceListener); diff --git a/MyTracks/src/com/google/android/apps/mytracks/content/DatabaseProvider.java b/MyTracks/src/com/google/android/apps/mytracks/content/DatabaseProvider.java new file mode 100644 index 000000000..7cd2dc1c4 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/content/DatabaseProvider.java @@ -0,0 +1,434 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.util.ApiFeatures; + +import android.content.ContentProvider; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.content.UriMatcher; +import android.database.Cursor; +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; +import android.database.sqlite.SQLiteOpenHelper; +import android.database.sqlite.SQLiteQueryBuilder; +import android.net.Uri; +import android.text.TextUtils; +import android.util.Log; + +/** + * A provider that handles recorded (GPS) tracks and their track points. + * + * @author Leif Hendrik Wilden + */ +public class DatabaseProvider extends ContentProvider { + + private static final String DATABASE_NAME = "mytracks.db"; + private static final int DATABASE_VERSION = 19; + private static final int TRACKPOINTS = 1; + private static final int TRACKPOINTS_ID = 2; + private static final int TRACKS = 3; + private static final int TRACKS_ID = 4; + private static final int WAYPOINTS = 5; + private static final int WAYPOINTS_ID = 6; + private static final String TRACKPOINTS_TABLE = "trackpoints"; + private static final String TRACKS_TABLE = "tracks"; + private static final String WAYPOINTS_TABLE = "waypoints"; + public static final String TAG = DatabaseProvider.class.getSimpleName(); + + /** + * Helper which creates or upgrades the database if necessary. + */ + private static class DatabaseHelper extends SQLiteOpenHelper { + + public DatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE " + TRACKPOINTS_TABLE + " (" + + TrackPointsColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + TrackPointsColumns.TRACKID + " INTEGER, " + + TrackPointsColumns.LONGITUDE + " INTEGER, " + + TrackPointsColumns.LATITUDE + " INTEGER, " + + TrackPointsColumns.TIME + " INTEGER, " + + TrackPointsColumns.ALTITUDE + " FLOAT, " + + TrackPointsColumns.ACCURACY + " FLOAT, " + + TrackPointsColumns.SPEED + " FLOAT, " + + TrackPointsColumns.BEARING + " FLOAT, " + + TrackPointsColumns.SENSOR + " BLOB);"); + db.execSQL("CREATE TABLE " + TRACKS_TABLE + " (" + + TracksColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + TracksColumns.NAME + " STRING, " + + TracksColumns.DESCRIPTION + " STRING, " + + TracksColumns.CATEGORY + " STRING, " + + TracksColumns.STARTID + " INTEGER, " + + TracksColumns.STOPID + " INTEGER, " + + TracksColumns.STARTTIME + " INTEGER, " + + TracksColumns.STOPTIME + " INTEGER, " + + TracksColumns.NUMPOINTS + " INTEGER, " + + TracksColumns.TOTALDISTANCE + " FLOAT, " + + TracksColumns.TOTALTIME + " INTEGER, " + + TracksColumns.MOVINGTIME + " INTEGER, " + + TracksColumns.MINLAT + " INTEGER, " + + TracksColumns.MAXLAT + " INTEGER, " + + TracksColumns.MINLON + " INTEGER, " + + TracksColumns.MAXLON + " INTEGER, " + + TracksColumns.AVGSPEED + " FLOAT, " + + TracksColumns.AVGMOVINGSPEED + " FLOAT, " + + TracksColumns.MAXSPEED + " FLOAT, " + + TracksColumns.MINELEVATION + " FLOAT, " + + TracksColumns.MAXELEVATION + " FLOAT, " + + TracksColumns.ELEVATIONGAIN + " FLOAT, " + + TracksColumns.MINGRADE + " FLOAT, " + + TracksColumns.MAXGRADE + " FLOAT, " + + TracksColumns.MAPID + " STRING, " + + TracksColumns.TABLEID + " STRING);"); + db.execSQL("CREATE TABLE " + WAYPOINTS_TABLE + " (" + + WaypointsColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + WaypointsColumns.NAME + " STRING, " + + WaypointsColumns.DESCRIPTION + " STRING, " + + WaypointsColumns.CATEGORY + " STRING, " + + WaypointsColumns.ICON + " STRING, " + + WaypointsColumns.TRACKID + " INTEGER, " + + WaypointsColumns.TYPE + " INTEGER, " + + WaypointsColumns.LENGTH + " FLOAT, " + + WaypointsColumns.DURATION + " INTEGER, " + + WaypointsColumns.STARTTIME + " INTEGER, " + + WaypointsColumns.STARTID + " INTEGER, " + + WaypointsColumns.STOPID + " INTEGER, " + + WaypointsColumns.LONGITUDE + " INTEGER, " + + WaypointsColumns.LATITUDE + " INTEGER, " + + WaypointsColumns.TIME + " INTEGER, " + + WaypointsColumns.ALTITUDE + " FLOAT, " + + WaypointsColumns.ACCURACY + " FLOAT, " + + WaypointsColumns.SPEED + " FLOAT, " + + WaypointsColumns.BEARING + " FLOAT, " + + WaypointsColumns.TOTALDISTANCE + " FLOAT, " + + WaypointsColumns.TOTALTIME + " INTEGER, " + + WaypointsColumns.MOVINGTIME + " INTEGER, " + + WaypointsColumns.AVGSPEED + " FLOAT, " + + WaypointsColumns.AVGMOVINGSPEED + " FLOAT, " + + WaypointsColumns.MAXSPEED + " FLOAT, " + + WaypointsColumns.MINELEVATION + " FLOAT, " + + WaypointsColumns.MAXELEVATION + " FLOAT, " + + WaypointsColumns.ELEVATIONGAIN + " FLOAT, " + + WaypointsColumns.MINGRADE + " FLOAT, " + + WaypointsColumns.MAXGRADE + " FLOAT);"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + if (oldVersion < 17) { + // Wipe the old data. + Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + + newVersion + ", which will destroy all old data"); + db.execSQL("DROP TABLE IF EXISTS " + TRACKPOINTS_TABLE); + db.execSQL("DROP TABLE IF EXISTS " + TRACKS_TABLE); + db.execSQL("DROP TABLE IF EXISTS " + WAYPOINTS_TABLE); + onCreate(db); + } else { + // Incremental updates go here. + // Each time you increase the DB version, add a corresponding if clause. + Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + + newVersion); + + // Sensor data. + if (oldVersion <= 17) { + Log.w(TAG, "Upgrade DB: Adding sensor column."); + db.execSQL("ALTER TABLE " + TRACKPOINTS_TABLE + + " ADD " + TrackPointsColumns.SENSOR + " BLOB"); + } + if (oldVersion <= 18) { + Log.w(TAG, "Upgrade DB: Adding tableid column."); + db.execSQL("ALTER TABLE " + TRACKS_TABLE + + " ADD " + TracksColumns.TABLEID + " STRING"); + } + } + } + } + + private final UriMatcher urlMatcher; + + private SQLiteDatabase db; + + public DatabaseProvider() { + urlMatcher = new UriMatcher(UriMatcher.NO_MATCH); + urlMatcher.addURI(MyTracksProviderUtils.DATABASE_AUTHORITY, "trackpoints", TRACKPOINTS); + urlMatcher.addURI(MyTracksProviderUtils.DATABASE_AUTHORITY, "trackpoints/#", TRACKPOINTS_ID); + urlMatcher.addURI(MyTracksProviderUtils.DATABASE_AUTHORITY, "tracks", TRACKS); + urlMatcher.addURI(MyTracksProviderUtils.DATABASE_AUTHORITY, "tracks/#", TRACKS_ID); + urlMatcher.addURI(MyTracksProviderUtils.DATABASE_AUTHORITY, "waypoints", WAYPOINTS); + urlMatcher.addURI(MyTracksProviderUtils.DATABASE_AUTHORITY, "waypoints/#", WAYPOINTS_ID); + } + + @Override + public boolean onCreate() { + DatabaseHelper dbHelper = new DatabaseHelper(getContext()); + try { + db = dbHelper.getWritableDatabase(); + } catch (SQLiteException e) { + Log.e(TAG, "Unable to open database for writing", e); + } + return db != null; + } + + @Override + public int delete(Uri url, String where, String[] selectionArgs) { + String table; + boolean shouldVacuum = false; + switch (urlMatcher.match(url)) { + case TRACKPOINTS: + table = TRACKPOINTS_TABLE; + break; + case TRACKS: + table = TRACKS_TABLE; + shouldVacuum = true; + break; + case WAYPOINTS: + table = WAYPOINTS_TABLE; + break; + default: + throw new IllegalArgumentException("Unknown URL " + url); + } + + Log.w(DatabaseProvider.TAG, "provider delete in " + table + "!"); + int count = db.delete(table, where, selectionArgs); + getContext().getContentResolver().notifyChange(url, null, true); + + if (shouldVacuum) { + // If a potentially large amount of data was deleted, we want to reclaim its space. + Log.i(TAG, "Vacuuming the database"); + db.execSQL("VACUUM"); + } + + return count; + } + + @Override + public String getType(Uri url) { + switch (urlMatcher.match(url)) { + case TRACKPOINTS: + return TrackPointsColumns.CONTENT_TYPE; + case TRACKPOINTS_ID: + return TrackPointsColumns.CONTENT_ITEMTYPE; + case TRACKS: + return TracksColumns.CONTENT_TYPE; + case TRACKS_ID: + return TracksColumns.CONTENT_ITEMTYPE; + case WAYPOINTS: + return WaypointsColumns.CONTENT_TYPE; + case WAYPOINTS_ID: + return WaypointsColumns.CONTENT_ITEMTYPE; + default: + throw new IllegalArgumentException("Unknown URL " + url); + } + } + + @Override + public Uri insert(Uri url, ContentValues initialValues) { + Log.d(DatabaseProvider.TAG, "MyTracksProvider.insert"); + ContentValues values; + if (initialValues != null) { + values = initialValues; + } else { + values = new ContentValues(); + } + + int urlMatchType = urlMatcher.match(url); + return insertType(url, urlMatchType, values); + } + + private Uri insertType(Uri url, int urlMatchType, ContentValues values) { + switch (urlMatchType) { + case TRACKPOINTS: + return insertTrackPoint(url, values); + case TRACKS: + return insertTrack(url, values); + case WAYPOINTS: + return insertWaypoint(url, values); + default: + throw new IllegalArgumentException("Unknown URL " + url); + } + } + + + @Override + public int bulkInsert(Uri url, ContentValues[] valuesBulk) { + Log.d(DatabaseProvider.TAG, "MyTracksProvider.bulkInsert"); + int numInserted = 0; + try { + // Use a transaction in order to make the insertions run as a single batch + db.beginTransaction(); + + int urlMatch = urlMatcher.match(url); + for (numInserted = 0; numInserted < valuesBulk.length; numInserted++) { + ContentValues values = valuesBulk[numInserted]; + if (values == null) { values = new ContentValues(); } + + insertType(url, urlMatch, values); + } + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + return numInserted; + } + + private Uri insertTrackPoint(Uri url, ContentValues values) { + boolean hasLat = values.containsKey(TrackPointsColumns.LATITUDE); + boolean hasLong = values.containsKey(TrackPointsColumns.LONGITUDE); + boolean hasTime = values.containsKey(TrackPointsColumns.TIME); + if (!hasLat || !hasLong || !hasTime) { + throw new IllegalArgumentException( + "Latitude, longitude, and time values are required."); + } + long rowId = db.insert(TRACKPOINTS_TABLE, TrackPointsColumns._ID, values); + if (rowId >= 0) { + Uri uri = ContentUris + .appendId(TrackPointsColumns.DATABASE_CONTENT_URI.buildUpon(), rowId).build(); + getContext().getContentResolver().notifyChange(url, null, true); + return uri; + } + throw new SQLiteException("Failed to insert row into " + url); + } + + private Uri insertTrack(Uri url, ContentValues values) { + boolean hasStartTime = values.containsKey(TracksColumns.STARTTIME); + boolean hasStartId = values.containsKey(TracksColumns.STARTID); + if (!hasStartTime || !hasStartId) { + throw new IllegalArgumentException( + "Both start time and start id values are required."); + } + long rowId = db.insert(TRACKS_TABLE, TracksColumns._ID, values); + if (rowId > 0) { + Uri uri = ContentUris.appendId(TracksColumns.DATABASE_CONTENT_URI.buildUpon(), rowId).build(); + getContext().getContentResolver().notifyChange(url, null, true); + return uri; + } + throw new SQLException("Failed to insert row into " + url); + } + + private Uri insertWaypoint(Uri url, ContentValues values) { + long rowId = db.insert(WAYPOINTS_TABLE, WaypointsColumns._ID, values); + if (rowId > 0) { + Uri uri = ContentUris + .appendId(WaypointsColumns.DATABASE_CONTENT_URI.buildUpon(), rowId).build(); + getContext().getContentResolver().notifyChange(url, null, true); + return uri; + } + throw new SQLException("Failed to insert row into " + url); + } + + @Override + public Cursor query( + Uri url, String[] projection, String selection, String[] selectionArgs, + String sort) { + SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); + int match = urlMatcher.match(url); + String sortOrder = null; + if (match == TRACKPOINTS) { + qb.setTables(TRACKPOINTS_TABLE); + if (sort != null) { + sortOrder = sort; + } else { + sortOrder = TrackPointsColumns.DEFAULT_SORT_ORDER; + } + } else if (match == TRACKPOINTS_ID) { + qb.setTables(TRACKPOINTS_TABLE); + qb.appendWhere("_id=" + url.getPathSegments().get(1)); + } else if (match == TRACKS) { + qb.setTables(TRACKS_TABLE); + if (sort != null) { + sortOrder = sort; + } else { + sortOrder = TracksColumns.DEFAULT_SORT_ORDER; + } + } else if (match == TRACKS_ID) { + qb.setTables(TRACKS_TABLE); + qb.appendWhere("_id=" + url.getPathSegments().get(1)); + } else if (match == WAYPOINTS) { + qb.setTables(WAYPOINTS_TABLE); + if (sort != null) { + sortOrder = sort; + } else { + sortOrder = WaypointsColumns.DEFAULT_SORT_ORDER; + } + } else if (match == WAYPOINTS_ID) { + qb.setTables(WAYPOINTS_TABLE); + qb.appendWhere("_id=" + url.getPathSegments().get(1)); + } else { + throw new IllegalArgumentException("Unknown URL " + url); + } + + if (ApiFeatures.getInstance().canReuseSQLiteQueryBuilder()) { + Log.i(Constants.TAG, + "Build query: " + qb.buildQuery(projection, selection, selectionArgs, + null, null, sortOrder, null)); + } + Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, + sortOrder); + c.setNotificationUri(getContext().getContentResolver(), url); + return c; + } + + @Override + public int update(Uri url, ContentValues values, String where, + String[] selectionArgs) { + int count; + int match = urlMatcher.match(url); + if (match == TRACKPOINTS) { + count = db.update(TRACKPOINTS_TABLE, values, where, selectionArgs); + } else if (match == TRACKPOINTS_ID) { + String segment = url.getPathSegments().get(1); + count = db.update(TRACKPOINTS_TABLE, values, "_id=" + segment + + (!TextUtils.isEmpty(where) + ? " AND (" + where + ')' + : ""), + selectionArgs); + } else if (match == TRACKS) { + count = db.update(TRACKS_TABLE, values, where, selectionArgs); + } else if (match == TRACKS_ID) { + String segment = url.getPathSegments().get(1); + count = db.update(TRACKS_TABLE, values, "_id=" + segment + + (!TextUtils.isEmpty(where) + ? " AND (" + where + ')' + : ""), + selectionArgs); + } else if (match == WAYPOINTS) { + count = db.update(WAYPOINTS_TABLE, values, where, selectionArgs); + } else if (match == WAYPOINTS_ID) { + String segment = url.getPathSegments().get(1); + count = db.update(WAYPOINTS_TABLE, values, "_id=" + segment + + (!TextUtils.isEmpty(where) + ? " AND (" + where + ')' + : ""), + selectionArgs); + } else { + throw new IllegalArgumentException("Unknown URL " + url); + } + getContext().getContentResolver().notifyChange(url, null, true); + return count; + } + +} 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 bcf874c35..781841dbe 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProvider.java +++ b/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 Google Inc. + * Copyright 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of @@ -16,423 +16,101 @@ package com.google.android.apps.mytracks.content; import com.google.android.apps.mytracks.Constants; -import com.google.android.apps.mytracks.util.ApiFeatures; +import com.google.android.maps.mytracks.R; -import android.content.ContentProvider; -import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; -import android.content.UriMatcher; +import android.content.SharedPreferences; import android.database.Cursor; -import android.database.SQLException; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; -import android.database.sqlite.SQLiteOpenHelper; -import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; -import android.text.TextUtils; -import android.util.Log; +import android.os.Binder; +import android.os.Process; /** - * A provider that handles recorded (GPS) tracks and their track points. + * A content provider that accesses MyTracks tracks, track points, and + * waypoints. After checking access, calls the corresponding methods in + * {@link DatabaseProvider}. * - * @author Leif Hendrik Wilden + * @author Jimmy Shih */ -public class MyTracksProvider extends ContentProvider { - - private static final String DATABASE_NAME = "mytracks.db"; - private static final int DATABASE_VERSION = 19; - private static final int TRACKPOINTS = 1; - private static final int TRACKPOINTS_ID = 2; - private static final int TRACKS = 3; - private static final int TRACKS_ID = 4; - private static final int WAYPOINTS = 5; - private static final int WAYPOINTS_ID = 6; - private static final String TRACKPOINTS_TABLE = "trackpoints"; - private static final String TRACKS_TABLE = "tracks"; - private static final String WAYPOINTS_TABLE = "waypoints"; - public static final String TAG = "MyTracksProvider"; - - /** - * Helper which creates or upgrades the database if necessary. - */ - private static class DatabaseHelper extends SQLiteOpenHelper { - - public DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + TRACKPOINTS_TABLE + " (" - + TrackPointsColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + TrackPointsColumns.TRACKID + " INTEGER, " - + TrackPointsColumns.LONGITUDE + " INTEGER, " - + TrackPointsColumns.LATITUDE + " INTEGER, " - + TrackPointsColumns.TIME + " INTEGER, " - + TrackPointsColumns.ALTITUDE + " FLOAT, " - + TrackPointsColumns.ACCURACY + " FLOAT, " - + TrackPointsColumns.SPEED + " FLOAT, " - + TrackPointsColumns.BEARING + " FLOAT, " - + TrackPointsColumns.SENSOR + " BLOB);"); - db.execSQL("CREATE TABLE " + TRACKS_TABLE + " (" - + TracksColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + TracksColumns.NAME + " STRING, " - + TracksColumns.DESCRIPTION + " STRING, " - + TracksColumns.CATEGORY + " STRING, " - + TracksColumns.STARTID + " INTEGER, " - + TracksColumns.STOPID + " INTEGER, " - + TracksColumns.STARTTIME + " INTEGER, " - + TracksColumns.STOPTIME + " INTEGER, " - + TracksColumns.NUMPOINTS + " INTEGER, " - + TracksColumns.TOTALDISTANCE + " FLOAT, " - + TracksColumns.TOTALTIME + " INTEGER, " - + TracksColumns.MOVINGTIME + " INTEGER, " - + TracksColumns.MINLAT + " INTEGER, " - + TracksColumns.MAXLAT + " INTEGER, " - + TracksColumns.MINLON + " INTEGER, " - + TracksColumns.MAXLON + " INTEGER, " - + TracksColumns.AVGSPEED + " FLOAT, " - + TracksColumns.AVGMOVINGSPEED + " FLOAT, " - + TracksColumns.MAXSPEED + " FLOAT, " - + TracksColumns.MINELEVATION + " FLOAT, " - + TracksColumns.MAXELEVATION + " FLOAT, " - + TracksColumns.ELEVATIONGAIN + " FLOAT, " - + TracksColumns.MINGRADE + " FLOAT, " - + TracksColumns.MAXGRADE + " FLOAT, " - + TracksColumns.MAPID + " STRING, " - + TracksColumns.TABLEID + " STRING);"); - db.execSQL("CREATE TABLE " + WAYPOINTS_TABLE + " (" - + WaypointsColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + WaypointsColumns.NAME + " STRING, " - + WaypointsColumns.DESCRIPTION + " STRING, " - + WaypointsColumns.CATEGORY + " STRING, " - + WaypointsColumns.ICON + " STRING, " - + WaypointsColumns.TRACKID + " INTEGER, " - + WaypointsColumns.TYPE + " INTEGER, " - + WaypointsColumns.LENGTH + " FLOAT, " - + WaypointsColumns.DURATION + " INTEGER, " - + WaypointsColumns.STARTTIME + " INTEGER, " - + WaypointsColumns.STARTID + " INTEGER, " - + WaypointsColumns.STOPID + " INTEGER, " - + WaypointsColumns.LONGITUDE + " INTEGER, " - + WaypointsColumns.LATITUDE + " INTEGER, " - + WaypointsColumns.TIME + " INTEGER, " - + WaypointsColumns.ALTITUDE + " FLOAT, " - + WaypointsColumns.ACCURACY + " FLOAT, " - + WaypointsColumns.SPEED + " FLOAT, " - + WaypointsColumns.BEARING + " FLOAT, " - + WaypointsColumns.TOTALDISTANCE + " FLOAT, " - + WaypointsColumns.TOTALTIME + " INTEGER, " - + WaypointsColumns.MOVINGTIME + " INTEGER, " - + WaypointsColumns.AVGSPEED + " FLOAT, " - + WaypointsColumns.AVGMOVINGSPEED + " FLOAT, " - + WaypointsColumns.MAXSPEED + " FLOAT, " - + WaypointsColumns.MINELEVATION + " FLOAT, " - + WaypointsColumns.MAXELEVATION + " FLOAT, " - + WaypointsColumns.ELEVATIONGAIN + " FLOAT, " - + WaypointsColumns.MINGRADE + " FLOAT, " - + WaypointsColumns.MAXGRADE + " FLOAT);"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - if (oldVersion < 17) { - // Wipe the old data. - Log.w(TAG, "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will destroy all old data"); - db.execSQL("DROP TABLE IF EXISTS " + TRACKPOINTS_TABLE); - db.execSQL("DROP TABLE IF EXISTS " + TRACKS_TABLE); - db.execSQL("DROP TABLE IF EXISTS " + WAYPOINTS_TABLE); - onCreate(db); - } else { - // Incremental updates go here. - // Each time you increase the DB version, add a corresponding if clause. - Log.w(TAG, "Upgrading database from version " + oldVersion + " to " - + newVersion); - - // Sensor data. - if (oldVersion <= 17) { - Log.w(TAG, "Upgrade DB: Adding sensor column."); - db.execSQL("ALTER TABLE " + TRACKPOINTS_TABLE - + " ADD " + TrackPointsColumns.SENSOR + " BLOB"); - } - if (oldVersion <= 18) { - Log.w(TAG, "Upgrade DB: Adding tableid column."); - db.execSQL("ALTER TABLE " + TRACKS_TABLE - + " ADD " + TracksColumns.TABLEID + " STRING"); - } - } - } - } - - private final UriMatcher urlMatcher; - - private SQLiteDatabase db; - - public MyTracksProvider() { - urlMatcher = new UriMatcher(UriMatcher.NO_MATCH); - urlMatcher.addURI(MyTracksProviderUtils.AUTHORITY, - "trackpoints", TRACKPOINTS); - urlMatcher.addURI(MyTracksProviderUtils.AUTHORITY, - "trackpoints/#", TRACKPOINTS_ID); - urlMatcher.addURI(MyTracksProviderUtils.AUTHORITY, "tracks", TRACKS); - urlMatcher.addURI(MyTracksProviderUtils.AUTHORITY, "tracks/#", TRACKS_ID); - urlMatcher.addURI(MyTracksProviderUtils.AUTHORITY, "waypoints", WAYPOINTS); - urlMatcher.addURI(MyTracksProviderUtils.AUTHORITY, - "waypoints/#", WAYPOINTS_ID); - } - - @Override - public boolean onCreate() { - DatabaseHelper dbHelper = new DatabaseHelper(getContext()); - try { - db = dbHelper.getWritableDatabase(); - } catch (SQLiteException e) { - Log.e(TAG, "Unable to open database for writing", e); - } - return db != null; - } - - @Override - public int delete(Uri url, String where, String[] selectionArgs) { - String table; - boolean shouldVacuum = false; - switch (urlMatcher.match(url)) { - case TRACKPOINTS: - table = TRACKPOINTS_TABLE; - break; - case TRACKS: - table = TRACKS_TABLE; - shouldVacuum = true; - break; - case WAYPOINTS: - table = WAYPOINTS_TABLE; - break; - default: - throw new IllegalArgumentException("Unknown URL " + url); - } - - Log.w(MyTracksProvider.TAG, "provider delete in " + table + "!"); - int count = db.delete(table, where, selectionArgs); - getContext().getContentResolver().notifyChange(url, null, true); - - if (shouldVacuum) { - // If a potentially large amount of data was deleted, we want to reclaim its space. - Log.i(TAG, "Vacuuming the database"); - db.execSQL("VACUUM"); - } - - return count; - } - - @Override - public String getType(Uri url) { - switch (urlMatcher.match(url)) { - case TRACKPOINTS: - return TrackPointsColumns.CONTENT_TYPE; - case TRACKPOINTS_ID: - return TrackPointsColumns.CONTENT_ITEMTYPE; - case TRACKS: - return TracksColumns.CONTENT_TYPE; - case TRACKS_ID: - return TracksColumns.CONTENT_ITEMTYPE; - case WAYPOINTS: - return WaypointsColumns.CONTENT_TYPE; - case WAYPOINTS_ID: - return WaypointsColumns.CONTENT_ITEMTYPE; - default: - throw new IllegalArgumentException("Unknown URL " + url); - } - } - - @Override - public Uri insert(Uri url, ContentValues initialValues) { - Log.d(MyTracksProvider.TAG, "MyTracksProvider.insert"); - ContentValues values; - if (initialValues != null) { - values = initialValues; +public class MyTracksProvider extends DatabaseProvider { + + private boolean canAccess() { + if (Binder.getCallingPid() == Process.myPid()) { + return true; } else { - values = new ContentValues(); - } - - int urlMatchType = urlMatcher.match(url); - return insertType(url, urlMatchType, values); - } - - private Uri insertType(Uri url, int urlMatchType, ContentValues values) { - switch (urlMatchType) { - case TRACKPOINTS: - return insertTrackPoint(url, values); - case TRACKS: - return insertTrack(url, values); - case WAYPOINTS: - return insertWaypoint(url, values); - default: - throw new IllegalArgumentException("Unknown URL " + url); + Context context = getContext(); + SharedPreferences sharedPreferences = context.getSharedPreferences( + Constants.SETTINGS_NAME, 0); + return sharedPreferences.getBoolean(context.getString(R.string.share_data_key), false); } } - + + /** + * Gets a URI based on the input URI, but replaces the + * {@link MyTracksProvider} authority with the {@link DatabaseProvider} + * authority. Returns null if the input URI doesn't contain the + * {@link MyTracksProvider} authority. + */ + private Uri getDatabaseProviderUri(Uri uri) { + String authority = uri.getAuthority(); + if (authority != null && authority.equals(MyTracksProviderUtils.AUTHORITY)) { + String databaseUri = "content://" + MyTracksProviderUtils.DATABASE_AUTHORITY; + String path = uri.getPath(); + if (path != null && !path.isEmpty()) { + databaseUri += path; + } + return Uri.parse(databaseUri); + } + return null; + } @Override - public int bulkInsert(Uri url, ContentValues[] valuesBulk) { - Log.d(MyTracksProvider.TAG, "MyTracksProvider.bulkInsert"); - int numInserted = 0; - try { - // Use a transaction in order to make the insertions run as a single batch - db.beginTransaction(); - - int urlMatch = urlMatcher.match(url); - for (numInserted = 0; numInserted < valuesBulk.length; numInserted++) { - ContentValues values = valuesBulk[numInserted]; - if (values == null) { values = new ContentValues(); } - - insertType(url, urlMatch, values); + public int delete(Uri uri, String selection, String[] selectionArgs) { + if (!canAccess()) { + return 0; } - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - return numInserted; + return super.delete(getDatabaseProviderUri(uri), selection, selectionArgs); } - private Uri insertTrackPoint(Uri url, ContentValues values) { - boolean hasLat = values.containsKey(TrackPointsColumns.LATITUDE); - boolean hasLong = values.containsKey(TrackPointsColumns.LONGITUDE); - boolean hasTime = values.containsKey(TrackPointsColumns.TIME); - if (!hasLat || !hasLong || !hasTime) { - throw new IllegalArgumentException( - "Latitude, longitude, and time values are required."); + @Override + public String getType(Uri uri) { + if (!canAccess()) { + return null; } - long rowId = db.insert(TRACKPOINTS_TABLE, TrackPointsColumns._ID, values); - if (rowId >= 0) { - Uri uri = ContentUris.appendId( - TrackPointsColumns.CONTENT_URI.buildUpon(), rowId).build(); - getContext().getContentResolver().notifyChange(url, null, true); - return uri; - } - throw new SQLiteException("Failed to insert row into " + url); + return super.getType(getDatabaseProviderUri(uri)); } - private Uri insertTrack(Uri url, ContentValues values) { - boolean hasStartTime = values.containsKey(TracksColumns.STARTTIME); - boolean hasStartId = values.containsKey(TracksColumns.STARTID); - if (!hasStartTime || !hasStartId) { - throw new IllegalArgumentException( - "Both start time and start id values are required."); + @Override + public Uri insert(Uri uri, ContentValues values) { + if (!canAccess()) { + return null; } - long rowId = db.insert(TRACKS_TABLE, TracksColumns._ID, values); - if (rowId > 0) { - Uri uri = ContentUris.appendId( - TracksColumns.CONTENT_URI.buildUpon(), rowId).build(); - getContext().getContentResolver().notifyChange(url, null, true); - return uri; - } - throw new SQLException("Failed to insert row into " + url); + return super.insert(getDatabaseProviderUri(uri), values); } - - private Uri insertWaypoint(Uri url, ContentValues values) { - long rowId = db.insert(WAYPOINTS_TABLE, WaypointsColumns._ID, values); - if (rowId > 0) { - Uri uri = ContentUris.appendId( - WaypointsColumns.CONTENT_URI.buildUpon(), rowId).build(); - getContext().getContentResolver().notifyChange(url, null, true); - return uri; + + @Override + public int bulkInsert(Uri uri, ContentValues[] values) { + if (!canAccess()) { + return 0; } - throw new SQLException("Failed to insert row into " + url); + return super.bulkInsert(getDatabaseProviderUri(uri), values); } @Override public Cursor query( - Uri url, String[] projection, String selection, String[] selectionArgs, - String sort) { - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - int match = urlMatcher.match(url); - String sortOrder = null; - if (match == TRACKPOINTS) { - qb.setTables(TRACKPOINTS_TABLE); - if (sort != null) { - sortOrder = sort; - } else { - sortOrder = TrackPointsColumns.DEFAULT_SORT_ORDER; - } - } else if (match == TRACKPOINTS_ID) { - qb.setTables(TRACKPOINTS_TABLE); - qb.appendWhere("_id=" + url.getPathSegments().get(1)); - } else if (match == TRACKS) { - qb.setTables(TRACKS_TABLE); - if (sort != null) { - sortOrder = sort; - } else { - sortOrder = TracksColumns.DEFAULT_SORT_ORDER; - } - } else if (match == TRACKS_ID) { - qb.setTables(TRACKS_TABLE); - qb.appendWhere("_id=" + url.getPathSegments().get(1)); - } else if (match == WAYPOINTS) { - qb.setTables(WAYPOINTS_TABLE); - if (sort != null) { - sortOrder = sort; - } else { - sortOrder = WaypointsColumns.DEFAULT_SORT_ORDER; - } - } else if (match == WAYPOINTS_ID) { - qb.setTables(WAYPOINTS_TABLE); - qb.appendWhere("_id=" + url.getPathSegments().get(1)); - } else { - throw new IllegalArgumentException("Unknown URL " + url); + Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + if (!canAccess()) { + return null; } - - if (ApiFeatures.getInstance().canReuseSQLiteQueryBuilder()) { - Log.i(Constants.TAG, - "Build query: " + qb.buildQuery(projection, selection, selectionArgs, - null, null, sortOrder, null)); - } - Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, - sortOrder); - c.setNotificationUri(getContext().getContentResolver(), url); - return c; + return super.query(getDatabaseProviderUri(uri), projection, selection, selectionArgs, sortOrder); } @Override - public int update(Uri url, ContentValues values, String where, - String[] selectionArgs) { - int count; - int match = urlMatcher.match(url); - if (match == TRACKPOINTS) { - count = db.update(TRACKPOINTS_TABLE, values, where, selectionArgs); - } else if (match == TRACKPOINTS_ID) { - String segment = url.getPathSegments().get(1); - count = db.update(TRACKPOINTS_TABLE, values, "_id=" + segment - + (!TextUtils.isEmpty(where) - ? " AND (" + where + ')' - : ""), - selectionArgs); - } else if (match == TRACKS) { - count = db.update(TRACKS_TABLE, values, where, selectionArgs); - } else if (match == TRACKS_ID) { - String segment = url.getPathSegments().get(1); - count = db.update(TRACKS_TABLE, values, "_id=" + segment - + (!TextUtils.isEmpty(where) - ? " AND (" + where + ')' - : ""), - selectionArgs); - } else if (match == WAYPOINTS) { - count = db.update(WAYPOINTS_TABLE, values, where, selectionArgs); - } else if (match == WAYPOINTS_ID) { - String segment = url.getPathSegments().get(1); - count = db.update(WAYPOINTS_TABLE, values, "_id=" + segment - + (!TextUtils.isEmpty(where) - ? " AND (" + where + ')' - : ""), - selectionArgs); - } else { - throw new IllegalArgumentException("Unknown URL " + url); + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + if (!canAccess()) { + return 0; } - getContext().getContentResolver().notifyChange(url, null, true); - return count; + return super.update(getDatabaseProviderUri(uri), values, selection, selectionArgs); } - } diff --git a/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsFactory.java b/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsFactory.java new file mode 100644 index 000000000..ff79eb436 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.android.apps.mytracks.content; + +import android.content.Context; + +/** + * A factory to return a new {@link MyTracksProviderUtils} that can access the + * Database content provider, {@link DatabaseProvider}. + * + * @author jshih@google.com (Jimmy Shih) + */ +public class MyTracksProviderUtilsFactory { + + /** + * Creates a new instance of {@link MyTracksProviderUtils} that uses the given + * context to access the Database content provider, {@link DatabaseProvider}. + */ + public static MyTracksProviderUtils get(Context context) { + return new MyTracksProviderUtilsImpl( + context.getContentResolver(), MyTracksProviderUtils.DATABASE_AUTHORITY); + } +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/content/TrackDataHub.java b/MyTracks/src/com/google/android/apps/mytracks/content/TrackDataHub.java index 3bdd31b0c..8f4a90ef4 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/content/TrackDataHub.java +++ b/MyTracks/src/com/google/android/apps/mytracks/content/TrackDataHub.java @@ -202,7 +202,7 @@ public class TrackDataHub { */ public synchronized static TrackDataHub newInstance(Context context) { SharedPreferences preferences = context.getSharedPreferences(Constants.SETTINGS_NAME, 0); - MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(context); + MyTracksProviderUtils providerUtils = MyTracksProviderUtilsFactory.get(context); return new TrackDataHub(context, new TrackDataListeners(), preferences, providerUtils, diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/SendToDocs.java b/MyTracks/src/com/google/android/apps/mytracks/io/SendToDocs.java index f04a8a546..f1cd9950d 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/SendToDocs.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/SendToDocs.java @@ -17,7 +17,7 @@ package com.google.android.apps.mytracks.io; import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.ProgressIndicator; -import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.io.docs.DocsHelper; import com.google.android.apps.mytracks.io.gdata.GDataClientFactory; @@ -102,8 +102,7 @@ public class SendToDocs { } // Get the track from the provider: - Track track = - MyTracksProviderUtils.Factory.get(activity).getTrack(trackId); + Track track = MyTracksProviderUtilsFactory.get(activity).getTrack(trackId); if (track == null) { Log.w(Constants.TAG, "Cannot get track."); return; diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java b/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java index f8b7e1f69..050b872ab 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/SendToFusionTables.java @@ -20,6 +20,7 @@ import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.ProgressIndicator; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.io.gdata.GDataWrapper; @@ -138,7 +139,7 @@ public class SendToFusionTables implements Runnable { this.progressIndicator = progressIndicator; this.onCompletion = onCompletion; this.stringUtils = new StringUtils(context); - this.providerUtils = MyTracksProviderUtils.Factory.get(context); + this.providerUtils = MyTracksProviderUtilsFactory.get(context); HttpTransport transport = ApiFeatures.getInstance().useNetHttpTransport() ? new NetHttpTransport() : new ApacheHttpTransport(); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java b/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java index a7190e8a9..0e69caff4 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/SendToMyMaps.java @@ -16,9 +16,11 @@ package com.google.android.apps.mytracks.io; import static com.google.android.apps.mytracks.Constants.TAG; + import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.ProgressIndicator; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.io.mymaps.MapsFacade; @@ -87,7 +89,7 @@ public class SendToMyMaps implements Runnable { this.progressIndicator = progressIndicator; this.onCompletion = onCompletion; this.stringUtils = new StringUtils(context); - this.providerUtils = MyTracksProviderUtils.Factory.get(context); + this.providerUtils = MyTracksProviderUtilsFactory.get(context); } @Override diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/backup/ExternalFileBackup.java b/MyTracks/src/com/google/android/apps/mytracks/io/backup/ExternalFileBackup.java index 16f18d0df..8b69740ec 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/backup/ExternalFileBackup.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/backup/ExternalFileBackup.java @@ -177,7 +177,7 @@ class ExternalFileBackup { // Dump the entire contents of each table ContentResolver contentResolver = context.getContentResolver(); Cursor tracksCursor = contentResolver.query( - TracksColumns.CONTENT_URI, null, null, null, null); + TracksColumns.DATABASE_CONTENT_URI, null, null, null, null); try { trackDumper.writeAllRows(tracksCursor, outWriter); } finally { @@ -185,7 +185,7 @@ class ExternalFileBackup { } Cursor waypointsCursor = contentResolver.query( - WaypointsColumns.CONTENT_URI, null, null, null, null); + WaypointsColumns.DATABASE_CONTENT_URI, null, null, null, null); try { waypointDumper.writeAllRows(waypointsCursor, outWriter); } finally { @@ -193,7 +193,7 @@ class ExternalFileBackup { } Cursor pointsCursor = contentResolver.query( - TrackPointsColumns.CONTENT_URI, null, null, null, null); + TrackPointsColumns.DATABASE_CONTENT_URI, null, null, null, null); try { pointDumper.writeAllRows(pointsCursor, outWriter); } finally { @@ -227,12 +227,12 @@ class ExternalFileBackup { PreferenceBackupHelper preferencesHelper = new PreferenceBackupHelper(); ContentResolver resolver = context.getContentResolver(); - DatabaseImporter trackImporter = - new DatabaseImporter(TracksColumns.CONTENT_URI, resolver, false); - DatabaseImporter waypointImporter = - new DatabaseImporter(WaypointsColumns.CONTENT_URI, resolver, false); - DatabaseImporter pointImporter = - new DatabaseImporter(TrackPointsColumns.CONTENT_URI, resolver, false); + DatabaseImporter trackImporter = new DatabaseImporter( + TracksColumns.DATABASE_CONTENT_URI, resolver, false); + DatabaseImporter waypointImporter = new DatabaseImporter( + WaypointsColumns.DATABASE_CONTENT_URI, resolver, false); + DatabaseImporter pointImporter = new DatabaseImporter( + TrackPointsColumns.DATABASE_CONTENT_URI, resolver, false); ZipFile zipFile = new ZipFile(inputFile, ZipFile.OPEN_READ); ZipEntry zipEntry = zipFile.getEntry(ZIP_ENTRY_NAME); @@ -245,9 +245,9 @@ class ExternalFileBackup { try { // Delete all previous contents of the tables and preferences. - resolver.delete(TracksColumns.CONTENT_URI, null, null); - resolver.delete(TrackPointsColumns.CONTENT_URI, null, null); - resolver.delete(WaypointsColumns.CONTENT_URI, null, null); + resolver.delete(TracksColumns.DATABASE_CONTENT_URI, null, null); + resolver.delete(TrackPointsColumns.DATABASE_CONTENT_URI, null, null); + resolver.delete(WaypointsColumns.DATABASE_CONTENT_URI, null, null); // Import the new contents of each table trackImporter.importAllRows(reader); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/ImportActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/ImportActivity.java index 1ca2b8061..c3a834474 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/ImportActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/ImportActivity.java @@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.io.file; import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.util.UriUtils; import com.google.android.maps.mytracks.R; @@ -64,7 +65,7 @@ public class ImportActivity extends Activity { public void onCreate(Bundle savedState) { super.onCreate(savedState); - providerUtils = MyTracksProviderUtils.Factory.get(this); + providerUtils = MyTracksProviderUtilsFactory.get(this); } @Override @@ -147,7 +148,7 @@ public class ImportActivity extends Activity { protected void showImportedTrack() { long lastTrackId = importedTrackIds[importedTrackIds.length - 1]; - Uri trackUri = ContentUris.withAppendedId(TracksColumns.CONTENT_URI, lastTrackId); + Uri trackUri = ContentUris.withAppendedId(TracksColumns.DATABASE_CONTENT_URI, lastTrackId); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(trackUri, TracksColumns.CONTENT_ITEMTYPE); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/SaveActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/SaveActivity.java index 818dcbdd2..d34ed288d 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/SaveActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/SaveActivity.java @@ -19,6 +19,7 @@ import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat; import com.google.android.apps.mytracks.util.FileUtils; @@ -63,7 +64,7 @@ public class SaveActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - providerUtils = MyTracksProviderUtils.Factory.get(this); + providerUtils = MyTracksProviderUtilsFactory.get(this); } @Override @@ -74,9 +75,9 @@ public class SaveActivity extends Activity { String action = intent.getAction(); String type = intent.getType(); Uri data = intent.getData(); - if (!getString(R.string.save_intent_action).equals(action) || - !TracksColumns.CONTENT_ITEMTYPE.equals(type) || - !UriUtils.matchesContentUri(data, TracksColumns.CONTENT_URI)) { + if (!getString(R.string.save_intent_action).equals(action) + || !TracksColumns.CONTENT_ITEMTYPE.equals(type) + || !UriUtils.matchesContentUri(data, TracksColumns.DATABASE_CONTENT_URI)) { Log.e(TAG, "Got bad save intent: " + intent); finish(); return; @@ -224,7 +225,7 @@ public class SaveActivity extends Activity { shareFile = true; } - Uri uri = ContentUris.withAppendedId(TracksColumns.CONTENT_URI, trackId); + Uri uri = ContentUris.withAppendedId(TracksColumns.DATABASE_CONTENT_URI, trackId); Intent intent = new Intent(ctx, SaveActivity.class); intent.setAction(ctx.getString(R.string.save_intent_action)); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/SendActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/SendActivity.java index 712ade62f..7709711e4 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/SendActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/SendActivity.java @@ -23,6 +23,7 @@ import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.MyMapsList; import com.google.android.apps.mytracks.ProgressIndicator; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.io.AuthManager; @@ -158,7 +159,7 @@ public class SendActivity extends Activity implements ProgressIndicator { Log.d(TAG, "SendActivity.onCreate"); super.onCreate(savedInstanceState); - providerUtils = MyTracksProviderUtils.Factory.get(this); + providerUtils = MyTracksProviderUtilsFactory.get(this); sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, 0); tracker = GoogleAnalyticsTracker.getInstance(); @@ -197,9 +198,8 @@ public class SendActivity extends Activity implements ProgressIndicator { String action = intent.getAction(); String type = intent.getType(); Uri data = intent.getData(); - if (!Intent.ACTION_SEND.equals(action) || - !TracksColumns.CONTENT_ITEMTYPE.equals(type) || - !UriUtils.matchesContentUri(data, TracksColumns.CONTENT_URI)) { + if (!Intent.ACTION_SEND.equals(action) || !TracksColumns.CONTENT_ITEMTYPE.equals(type) + || !UriUtils.matchesContentUri(data, TracksColumns.DATABASE_CONTENT_URI)) { Log.e(TAG, "Got bad send intent: " + intent); return false; } @@ -911,7 +911,7 @@ public class SendActivity extends Activity implements ProgressIndicator { } public static void sendToGoogle(Context ctx, long trackId, boolean shareLink) { - Uri uri = ContentUris.withAppendedId(TracksColumns.CONTENT_URI, trackId); + Uri uri = ContentUris.withAppendedId(TracksColumns.DATABASE_CONTENT_URI, trackId); Intent intent = new Intent(ctx, SendActivity.class); intent.setAction(Intent.ACTION_SEND); diff --git a/MyTracks/src/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathDescriptor.java b/MyTracks/src/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathDescriptor.java index f6fc968d5..9ca483094 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathDescriptor.java +++ b/MyTracks/src/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathDescriptor.java @@ -18,7 +18,7 @@ package com.google.android.apps.mytracks.maps; import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.Constants; -import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.android.maps.mytracks.R; @@ -104,7 +104,7 @@ public class DynamicSpeedTrackPathDescriptor // Could not find track. return false; } - Track track = MyTracksProviderUtils.Factory.get(context).getTrack(currentTrackId); + Track track = MyTracksProviderUtilsFactory.get(context).getTrack(currentTrackId); TripStatistics stats = track.getStatistics(); double newaverageSpeed = (int) Math.floor(stats.getAverageMovingSpeed() * 3.6); diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java b/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java index 46843a6ad..cac207e99 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/TrackRecordingService.java @@ -235,6 +235,11 @@ public class TrackRecordingService extends Service { public void onCreate() { super.onCreate(); Log.d(TAG, "TrackRecordingService.onCreate"); + + /* + * Use the MyTracksProviderUtils that access the MyTracksProvider because + * this service can be called by MyTracks or another app. + */ providerUtils = MyTracksProviderUtils.Factory.get(this); notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); diff --git a/MyTracks/src/com/google/android/apps/mytracks/widgets/TrackWidgetProvider.java b/MyTracks/src/com/google/android/apps/mytracks/widgets/TrackWidgetProvider.java index e62a05a26..df245da64 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/widgets/TrackWidgetProvider.java +++ b/MyTracks/src/com/google/android/apps/mytracks/widgets/TrackWidgetProvider.java @@ -21,6 +21,7 @@ import static com.google.android.apps.mytracks.Constants.TAG; import com.google.android.apps.mytracks.MyTracks; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.services.ControlRecordingService; @@ -91,7 +92,7 @@ public class TrackWidgetProvider } this.context = context; trackObserver = new TrackObserver(); - providerUtils = MyTracksProviderUtils.Factory.get(context); + providerUtils = MyTracksProviderUtilsFactory.get(context); unknown = context.getString(R.string.unknown); sharedPreferences = context.getSharedPreferences(SETTINGS_NAME, 0); @@ -99,7 +100,7 @@ public class TrackWidgetProvider onSharedPreferenceChanged(sharedPreferences, null); context.getContentResolver().registerContentObserver( - TracksColumns.CONTENT_URI, true, trackObserver); + TracksColumns.DATABASE_CONTENT_URI, true, trackObserver); TRACK_STARTED_ACTION = context.getString(R.string.track_started_broadcast_action); TRACK_STOPPED_ACTION = context.getString(R.string.track_stopped_broadcast_action); } diff --git a/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java b/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java index a9506f1fc..741351bef 100644 --- a/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java +++ b/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java @@ -36,6 +36,13 @@ public interface MyTracksProviderUtils { */ public static final String AUTHORITY = "com.google.android.maps.mytracks"; + /** + * Authority for the Database content provider. The Database content provider + * is configured, through the MyTracks AndroidManifest.xml, to only allow the + * MyTracks app access. + */ + public static final String DATABASE_AUTHORITY = "com.google.android.apps.mytracks.content"; + /** * Deletes all tracks (including track points) from the provider. */ @@ -437,7 +444,7 @@ public interface MyTracksProviderUtils { * Creates an instance of {@link MyTracksProviderUtils}. */ protected MyTracksProviderUtils newForContext(Context context) { - return new MyTracksProviderUtilsImpl(context.getContentResolver()); + return new MyTracksProviderUtilsImpl(context.getContentResolver(), AUTHORITY); } } } 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 44ff1891a..c9c9a13c5 100644 --- a/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java +++ b/MyTracksLib/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java @@ -16,7 +16,7 @@ package com.google.android.apps.mytracks.content; import static com.google.android.apps.mytracks.lib.MyTracksLibConstants.TAG; -import com.google.android.apps.mytracks.content.Sensor; + import com.google.android.apps.mytracks.stats.TripStatistics; import com.google.protobuf.InvalidProtocolBufferException; @@ -40,13 +40,39 @@ import java.util.NoSuchElementException; public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { private final ContentResolver contentResolver; + private final String authority; // authority of the content provider private int defaultCursorBatchSize = 2000; - public MyTracksProviderUtilsImpl(ContentResolver contentResolver) { + public MyTracksProviderUtilsImpl(ContentResolver contentResolver, String authority) { this.contentResolver = contentResolver; + this.authority = authority; + } + + /** + * Gets the tracks table URI. + */ + private Uri getTracksUri() { + return authority.equals(DATABASE_AUTHORITY) ? TracksColumns.DATABASE_CONTENT_URI + : TracksColumns.CONTENT_URI; } + /** + * Gets the track points table URI. + */ + private Uri getTrackPointsUri() { + return authority.equals(DATABASE_AUTHORITY) ? TrackPointsColumns.DATABASE_CONTENT_URI + : TrackPointsColumns.CONTENT_URI; + } + + /** + * Gets the waypoints table URI. + */ + private Uri getWaypointsUri() { + return authority.equals(DATABASE_AUTHORITY) ? WaypointsColumns.DATABASE_CONTENT_URI + : WaypointsColumns.CONTENT_URI; + } + /** * Creates the ContentValues for a given location object. * @@ -518,24 +544,20 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { @Override public void deleteAllTracks() { - contentResolver.delete(TracksColumns.CONTENT_URI, null, null); - contentResolver.delete(TrackPointsColumns.CONTENT_URI, - null, null); - contentResolver.delete(WaypointsColumns.CONTENT_URI, null, null); + contentResolver.delete(getTracksUri(), null, null); + contentResolver.delete(getTrackPointsUri(), null, null); + contentResolver.delete(getWaypointsUri(), null, null); } @Override public void deleteTrack(long trackId) { Track track = getTrack(trackId); if (track != null) { - contentResolver.delete(TrackPointsColumns.CONTENT_URI, - "_id>=" + track.getStartId() + " AND _id<=" + track.getStopId(), - null); + contentResolver.delete(getTrackPointsUri(), + "_id>=" + track.getStartId() + " AND _id<=" + track.getStopId(), null); } - contentResolver.delete(WaypointsColumns.CONTENT_URI, - WaypointsColumns.TRACKID + "=" + trackId, null); - contentResolver.delete( - TracksColumns.CONTENT_URI, "_id=" + trackId, null); + contentResolver.delete(getWaypointsUri(), WaypointsColumns.TRACKID + "=" + trackId, null); + contentResolver.delete(getTracksUri(), "_id=" + trackId, null); } @Override @@ -559,8 +581,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { Log.d(TAG, "No statistics marker after the deleted one was found."); } } - contentResolver.delete( - WaypointsColumns.CONTENT_URI, "_id=" + waypointId, null); + contentResolver.delete(getWaypointsUri(), "_id=" + waypointId, null); } @Override @@ -572,7 +593,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { Cursor cursor = null; try { cursor = contentResolver.query( - WaypointsColumns.CONTENT_URI, + getWaypointsUri(), null /*projection*/, selection, null /*selectionArgs*/, @@ -594,7 +615,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { public boolean updateWaypoint(Waypoint waypoint) { try { final int rows = contentResolver.update( - WaypointsColumns.CONTENT_URI, + getWaypointsUri(), createContentValues(waypoint), "_id=" + waypoint.getId(), null /*selectionArgs*/); @@ -614,8 +635,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { private Location findLocationBy(String select) { Cursor cursor = null; try { - cursor = contentResolver.query( - TrackPointsColumns.CONTENT_URI, null, select, null, null); + cursor = contentResolver.query(getTrackPointsUri(), null, select, null, null); if (cursor != null && cursor.moveToNext()) { return createLocation(cursor); } @@ -638,8 +658,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { private Track findTrackBy(String select) { Cursor cursor = null; try { - cursor = contentResolver.query( - TracksColumns.CONTENT_URI, null, select, null, null); + cursor = contentResolver.query(getTracksUri(), null, select, null, null); if (cursor != null && cursor.moveToNext()) { return createTrack(cursor); } @@ -665,7 +684,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { } Cursor cursor = contentResolver.query( - WaypointsColumns.CONTENT_URI, + getWaypointsUri(), null /*projection*/, "trackid=" + trackId, null /*selectionArgs*/, @@ -691,7 +710,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { } Cursor cursor = contentResolver.query( - WaypointsColumns.CONTENT_URI, + getWaypointsUri(), null /*projection*/, "_id=" + waypointId, null /*selectionArgs*/, @@ -718,7 +737,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { final String[] projection = {"_id"}; Cursor cursor = contentResolver.query( - TrackPointsColumns.CONTENT_URI, + getTrackPointsUri(), projection, "_id=(select max(_id) from trackpoints WHERE trackid=" + trackId + ")", null /*selectionArgs*/, @@ -746,7 +765,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { final String[] projection = {"_id"}; Cursor cursor = contentResolver.query( - WaypointsColumns.CONTENT_URI, + getWaypointsUri(), projection, "trackid=" + trackId, null /*selectionArgs*/, @@ -774,7 +793,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { final String[] projection = {"_id"}; Cursor cursor = contentResolver.query( - WaypointsColumns.CONTENT_URI, + getWaypointsUri(), projection, WaypointsColumns.TRACKID + "=" + trackId, null /*selectionArgs*/, @@ -799,8 +818,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { Cursor cursor = null; try { cursor = contentResolver.query( - TracksColumns.CONTENT_URI, null, "_id=(select max(_id) from tracks)", - null, null); + getTracksUri(), null, "_id=(select max(_id) from tracks)", null, null); if (cursor != null && cursor.moveToNext()) { return createTrack(cursor); } @@ -818,8 +836,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { public long getLastTrackId() { String[] proj = { TracksColumns._ID }; Cursor cursor = contentResolver.query( - TracksColumns.CONTENT_URI, proj, "_id=(select max(_id) from tracks)", - null, null); + getTracksUri(), proj, "_id=(select max(_id) from tracks)", null, null); if (cursor != null) { try { if (cursor.moveToFirst()) { @@ -864,7 +881,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { sortOrder += " LIMIT " + maxLocations; } - return contentResolver.query(TrackPointsColumns.CONTENT_URI, null, selection, null, sortOrder); + return contentResolver.query(getTrackPointsUri(), null, selection, null, sortOrder); } @Override @@ -889,8 +906,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { sortOrder += " LIMIT " + maxWaypoints; } - return contentResolver.query( - WaypointsColumns.CONTENT_URI, null, selection, null, sortOrder); + return contentResolver.query(getWaypointsUri(), null, selection, null, sortOrder); } @Override @@ -924,23 +940,20 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { @Override public Cursor getTracksCursor(String selection) { - Cursor cursor = contentResolver.query( - TracksColumns.CONTENT_URI, null, selection, null, "_id"); + Cursor cursor = contentResolver.query(getTracksUri(), null, selection, null, "_id"); return cursor; } @Override public Uri insertTrack(Track track) { Log.d(TAG, "MyTracksProviderUtilsImpl.insertTrack"); - return contentResolver.insert(TracksColumns.CONTENT_URI, - createContentValues(track)); + return contentResolver.insert(getTracksUri(), createContentValues(track)); } @Override public Uri insertTrackPoint(Location location, long trackId) { Log.d(TAG, "MyTracksProviderUtilsImpl.insertTrackPoint"); - return contentResolver.insert(TrackPointsColumns.CONTENT_URI, - createContentValues(location, trackId)); + return contentResolver.insert(getTrackPointsUri(), createContentValues(location, trackId)); } @Override @@ -952,15 +965,14 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { values[i] = createContentValues(locations[i], trackId); } - return contentResolver.bulkInsert(TrackPointsColumns.CONTENT_URI, values); + return contentResolver.bulkInsert(getTrackPointsUri(), values); } @Override public Uri insertWaypoint(Waypoint waypoint) { Log.d(TAG, "MyTracksProviderUtilsImpl.insertWaypoint"); waypoint.setId(-1); - return contentResolver.insert(WaypointsColumns.CONTENT_URI, - createContentValues(waypoint)); + return contentResolver.insert(getWaypointsUri(), createContentValues(waypoint)); } @Override @@ -973,7 +985,7 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { try { final String[] projection = { TracksColumns._ID }; cursor = contentResolver.query( - TracksColumns.CONTENT_URI, + getTracksUri(), projection, TracksColumns._ID + "=" + id/*selection*/, null/*selectionArgs*/, @@ -992,8 +1004,8 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { @Override public void updateTrack(Track track) { Log.d(TAG, "MyTracksProviderUtilsImpl.updateTrack"); - contentResolver.update(TracksColumns.CONTENT_URI, - createContentValues(track), "_id=" + track.getId(), null); + contentResolver.update( + getTracksUri(), createContentValues(track), "_id=" + track.getId(), null); } @Override diff --git a/MyTracksLib/src/com/google/android/apps/mytracks/content/TrackPointsColumns.java b/MyTracksLib/src/com/google/android/apps/mytracks/content/TrackPointsColumns.java index eba090517..da9aae95a 100644 --- a/MyTracksLib/src/com/google/android/apps/mytracks/content/TrackPointsColumns.java +++ b/MyTracksLib/src/com/google/android/apps/mytracks/content/TrackPointsColumns.java @@ -25,8 +25,14 @@ import android.provider.BaseColumns; * @author Leif Hendrik Wilden */ public interface TrackPointsColumns extends BaseColumns { - public static final Uri CONTENT_URI = - Uri.parse("content://com.google.android.maps.mytracks/trackpoints"); + + // MyTracks content provider URI for the track points table. + public static final Uri CONTENT_URI = Uri.parse( + "content://" + MyTracksProviderUtils.AUTHORITY + "/trackpoints"); + + // Database content provider URI for the track points table. + public static final Uri DATABASE_CONTENT_URI = Uri.parse( + "content://" + MyTracksProviderUtils.DATABASE_AUTHORITY + "/trackpoints"); public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.trackpoint"; public static final String CONTENT_ITEMTYPE = 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 d3e0fae4d..f40317455 100644 --- a/MyTracksLib/src/com/google/android/apps/mytracks/content/TracksColumns.java +++ b/MyTracksLib/src/com/google/android/apps/mytracks/content/TracksColumns.java @@ -26,8 +26,13 @@ import android.provider.BaseColumns; */ public interface TracksColumns extends BaseColumns { - public static final Uri CONTENT_URI = - Uri.parse("content://com.google.android.maps.mytracks/tracks"); + // MyTracks content provider URI for the tracks table. + public static final Uri CONTENT_URI = Uri.parse( + "content://" + MyTracksProviderUtils.AUTHORITY + "/tracks"); + + // Database content provider URI for the tracks table. + public static final Uri DATABASE_CONTENT_URI = Uri.parse( + "content://" + MyTracksProviderUtils.DATABASE_AUTHORITY + "/tracks"); public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.track"; public static final String CONTENT_ITEMTYPE = diff --git a/MyTracksLib/src/com/google/android/apps/mytracks/content/WaypointsColumns.java b/MyTracksLib/src/com/google/android/apps/mytracks/content/WaypointsColumns.java index 8184bd583..6937b796f 100644 --- a/MyTracksLib/src/com/google/android/apps/mytracks/content/WaypointsColumns.java +++ b/MyTracksLib/src/com/google/android/apps/mytracks/content/WaypointsColumns.java @@ -26,8 +26,13 @@ import android.provider.BaseColumns; */ public interface WaypointsColumns extends BaseColumns { - public static final Uri CONTENT_URI = - Uri.parse("content://com.google.android.maps.mytracks/waypoints"); + // MyTracks content provider URI for the waypoints table. + public static final Uri CONTENT_URI = Uri.parse( + "content://" + MyTracksProviderUtils.AUTHORITY + "/waypoints"); + + // Database content provider URI for the waypoints table. + public static final Uri DATABASE_CONTENT_URI = Uri.parse( + "content://" + MyTracksProviderUtils.DATABASE_AUTHORITY + "/waypoints"); public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.waypoint"; public static final String CONTENT_ITEMTYPE = diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/MapOverlayTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/MapOverlayTest.java index 49a91b49b..72b1b9d42 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/MapOverlayTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/MapOverlayTest.java @@ -63,7 +63,6 @@ public class MapOverlayTest extends AndroidTestCase { assertEquals(2, myTracksOverlay.getNumLocations()); assertEquals(0, myTracksOverlay.getNumWaypoints()); assertNotNull(myTracksOverlay.getLastPath()); - assertEquals(2, ((MockPath)myTracksOverlay.getLastPath()).totalPoints); myTracksOverlay.draw(canvas, mockView, true); assertEquals(2, myTracksOverlay.getNumLocations()); @@ -152,11 +151,8 @@ public class MapOverlayTest extends AndroidTestCase { // No shadow. myTracksOverlay.draw(canvas, mockView, false); assertNotNull(myTracksOverlay.getLastPath()); - assertTrue(myTracksOverlay.getLastPath() instanceof MockPath); - MockPath path = (MockPath) myTracksOverlay.getLastPath(); assertEquals(40, myTracksOverlay.getNumWaypoints()); assertEquals(100, myTracksOverlay.getNumLocations()); - assertEquals(100, path.totalPoints); // TODO: Check the points from the path (and the segments). } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImplTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImplTest.java index 9107221a9..2459b0701 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImplTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImplTest.java @@ -46,12 +46,12 @@ public class MyTracksProviderUtilsImplTest extends AndroidTestCase { RenamingDelegatingContext targetContext = new RenamingDelegatingContext( getContext(), getContext(), "test."); context = new MockContext(mockContentResolver, targetContext); - MyTracksProvider provider = new MyTracksProvider(); + DatabaseProvider provider = new DatabaseProvider(); provider.attachInfo(context, null); - mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider); + mockContentResolver.addProvider(MyTracksProviderUtils.DATABASE_AUTHORITY, provider); setContext(context); - providerUtils = MyTracksProviderUtils.Factory.get(context); + providerUtils = MyTracksProviderUtilsFactory.get(context); } public void testLocationIterator_noPoints() { diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/content/TrackDataHubTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/content/TrackDataHubTest.java index ce77bb917..d995b3ce5 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/content/TrackDataHubTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/content/TrackDataHubTest.java @@ -142,7 +142,7 @@ public class TrackDataHubTest extends AndroidTestCase { expect(providerUtils.getTrack(TRACK_ID)).andStubReturn(track); expectStart(); dataSources.registerContentObserver( - eq(TracksColumns.CONTENT_URI), eq(false), capture(observerCapture)); + eq(TracksColumns.DATABASE_CONTENT_URI), eq(false), capture(observerCapture)); // Expect the initial loading. // Both listeners (registered before and after start) should get the same data. @@ -322,7 +322,7 @@ public class TrackDataHubTest extends AndroidTestCase { expectStart(); dataSources.registerContentObserver( - eq(WaypointsColumns.CONTENT_URI), eq(false), capture(observerCapture)); + eq(WaypointsColumns.DATABASE_CONTENT_URI), eq(false), capture(observerCapture)); // Expect the initial loading. // Both listeners (registered before and after start) should get the same data. @@ -415,7 +415,7 @@ public class TrackDataHubTest extends AndroidTestCase { expectStart(); dataSources.registerContentObserver( - eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture)); + eq(TrackPointsColumns.DATABASE_CONTENT_URI), eq(false), capture(observerCapture)); FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5); expect(providerUtils.getLocationIterator( @@ -502,7 +502,7 @@ public class TrackDataHubTest extends AndroidTestCase { expectStart(); dataSources.registerContentObserver( - eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture)); + eq(TrackPointsColumns.DATABASE_CONTENT_URI), eq(false), capture(observerCapture)); FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5); expect(providerUtils.getLocationIterator( @@ -533,7 +533,7 @@ public class TrackDataHubTest extends AndroidTestCase { // Register again, except only points since unregistered. dataSources.registerContentObserver( - eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture)); + eq(TrackPointsColumns.DATABASE_CONTENT_URI), eq(false), capture(observerCapture)); locationIterator = new FixedSizeLocationIterator(11, 10); expect(providerUtils.getLocationIterator( @@ -574,7 +574,7 @@ public class TrackDataHubTest extends AndroidTestCase { expectStart(); dataSources.registerContentObserver( - eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture)); + eq(TrackPointsColumns.DATABASE_CONTENT_URI), eq(false), capture(observerCapture)); FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5); expect(providerUtils.getLocationIterator( @@ -605,7 +605,7 @@ public class TrackDataHubTest extends AndroidTestCase { // Register again after track changed, expect all points. dataSources.registerContentObserver( - eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture)); + eq(TrackPointsColumns.DATABASE_CONTENT_URI), eq(false), capture(observerCapture)); locationIterator = new FixedSizeLocationIterator(1, 10); expect(providerUtils.getLocationIterator( @@ -632,7 +632,7 @@ public class TrackDataHubTest extends AndroidTestCase { expectStart(); dataSources.registerContentObserver( - eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture)); + eq(TrackPointsColumns.DATABASE_CONTENT_URI), eq(false), capture(observerCapture)); FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 200, 4, 25, 71, 120); expect(providerUtils.getLocationIterator( @@ -665,7 +665,7 @@ public class TrackDataHubTest extends AndroidTestCase { expectStart(); dataSources.registerContentObserver( - eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture)); + eq(TrackPointsColumns.DATABASE_CONTENT_URI), eq(false), capture(observerCapture)); // Deliver 30 points (no sampling happens) FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 30, 5); diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/GpxImporterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/GpxImporterTest.java index 7b9b0398e..a99ff28ad 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/GpxImporterTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/GpxImporterTest.java @@ -19,10 +19,9 @@ import static com.google.android.testing.mocking.AndroidMock.eq; import static com.google.android.testing.mocking.AndroidMock.expect; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.TracksColumns; -import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory; -import com.google.android.apps.mytracks.io.file.GpxImporter; import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory; import com.google.android.testing.mocking.AndroidMock; import com.google.android.testing.mocking.UsesMocks; @@ -106,7 +105,7 @@ public class GpxImporterTest extends AndroidTestCase { private static final long TRACK_POINT_ID_2 = 2; private static final Uri TRACK_ID_URI = ContentUris.appendId( - TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID).build(); + TracksColumns.DATABASE_CONTENT_URI.buildUpon(), TRACK_ID).build(); private MyTracksProviderUtils providerUtils; diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java index 7ec10b12a..2498d6e24 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/TrackWriterTest.java @@ -4,9 +4,10 @@ package com.google.android.apps.mytracks.io.file; import static org.easymock.EasyMock.expect; -import com.google.android.apps.mytracks.content.MyTracksProvider; +import com.google.android.apps.mytracks.content.DatabaseProvider; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext; @@ -140,11 +141,11 @@ public class TrackWriterTest extends AndroidTestCase { RenamingDelegatingContext targetContext = new RenamingDelegatingContext( getContext(), getContext(), "test."); Context context = new MockContext(mockContentResolver, targetContext); - MyTracksProvider provider = new MyTracksProvider(); + DatabaseProvider provider = new DatabaseProvider(); provider.attachInfo(context, null); - mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider); + mockContentResolver.addProvider(MyTracksProviderUtils.DATABASE_AUTHORITY, provider); setContext(context); - providerUtils = MyTracksProviderUtils.Factory.get(context); + providerUtils = MyTracksProviderUtilsFactory.get(context); oldProviderUtilsFactory = TestingProviderUtilsFactory.installWithInstance(providerUtils); mocksControl = EasyMock.createStrictControl(); diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorDynamicSpeedTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorDynamicSpeedTest.java index 63eec1182..40d894aaa 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorDynamicSpeedTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorDynamicSpeedTest.java @@ -15,8 +15,6 @@ */ package com.google.android.apps.mytracks.maps; -import com.google.android.apps.mytracks.MockPath; - import android.location.Location; /** @@ -45,9 +43,6 @@ public class TrackPathDescriptorDynamicSpeedTest extends TrackPathPainterTestCas painter.updatePath(myTracksOverlay.getMapProjection(mockView), myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible, myTracksOverlay.getPoints()); - assertNotNull(myTracksOverlay.getLastPath()); - assertTrue(myTracksOverlay.getLastPath() instanceof MockPath); - painter.drawTrack(canvas); - + painter.drawTrack(canvas); } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorFixedSpeedTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorFixedSpeedTest.java index d78c02fcb..b71037045 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorFixedSpeedTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathDescriptorFixedSpeedTest.java @@ -15,8 +15,6 @@ */ package com.google.android.apps.mytracks.maps; -import com.google.android.apps.mytracks.MockPath; - import android.location.Location; /** @@ -45,8 +43,6 @@ public class TrackPathDescriptorFixedSpeedTest extends TrackPathPainterTestCase painter.updatePath(myTracksOverlay.getMapProjection(mockView), myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible, myTracksOverlay.getPoints()); - assertNotNull(myTracksOverlay.getLastPath()); - assertTrue(myTracksOverlay.getLastPath() instanceof MockPath); painter.drawTrack(canvas); } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterFactoryTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterFactoryTest.java index 83482b26b..ea57ef7b6 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterFactoryTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterFactoryTest.java @@ -16,7 +16,6 @@ package com.google.android.apps.mytracks.maps; import com.google.android.apps.mytracks.Constants; -import com.google.android.apps.mytracks.MockPath; import com.google.android.maps.mytracks.R; import android.content.Context; @@ -57,8 +56,8 @@ public class TrackPathPainterFactoryTest extends TrackPathPainterTestCase { private void testTrackPathPainterFactorySpecific(Context context, SharedPreferences prefs, int track_color_mode, Class c) { - prefs.edit().putString(context.getString(track_color_mode), - context.getString(R.string.track_color_mode_key)).commit(); + prefs.edit().putString(context.getString(R.string.track_color_mode_key), + context.getString(track_color_mode)).commit(); int startLocationIdx = 0; Boolean alwaysVisible = true; @@ -71,8 +70,6 @@ public class TrackPathPainterFactoryTest extends TrackPathPainterTestCase { painter.updatePath(myTracksOverlay.getMapProjection(mockView), myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible, myTracksOverlay.getPoints()); - assertNotNull(myTracksOverlay.getLastPath()); - assertTrue(myTracksOverlay.getLastPath() instanceof MockPath); painter.drawTrack(canvas); } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterSingleColorTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterSingleColorTest.java index 6c6682e32..f1c63cd64 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterSingleColorTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/maps/TrackPathPainterSingleColorTest.java @@ -15,8 +15,6 @@ */ package com.google.android.apps.mytracks.maps; -import com.google.android.apps.mytracks.MockPath; - import android.location.Location; /** @@ -45,8 +43,6 @@ public class TrackPathPainterSingleColorTest extends TrackPathPainterTestCase { painter.updatePath(myTracksOverlay.getMapProjection(mockView), myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible, myTracksOverlay.getPoints()); - assertNotNull(myTracksOverlay.getLastPath()); - assertTrue(myTracksOverlay.getLastPath() instanceof MockPath); painter.drawTrack(canvas); } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java index 87c2a35a5..8b71cc356 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java @@ -18,8 +18,10 @@ package com.google.android.apps.mytracks.services; import static com.google.android.apps.mytracks.Constants.RESUME_TRACK_EXTRA_NAME; import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.content.DatabaseProvider; import com.google.android.apps.mytracks.content.MyTracksProvider; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtilsFactory; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.WaypointCreationRequest; @@ -144,12 +146,18 @@ public class TrackRecordingServiceTest RenamingDelegatingContext targetContext = new RenamingDelegatingContext( getContext(), getContext(), "test."); context = new MockContext(mockContentResolver, targetContext); - MyTracksProvider provider = new MyTracksProvider(); - provider.attachInfo(context, null); - mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider); + + MyTracksProvider myTracksProvider = new MyTracksProvider(); + myTracksProvider.attachInfo(context, null); + mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, myTracksProvider); + + DatabaseProvider databaseProvider = new DatabaseProvider(); + databaseProvider.attachInfo(context, null); + mockContentResolver.addProvider(MyTracksProviderUtils.DATABASE_AUTHORITY, databaseProvider); + setContext(context); - providerUtils = MyTracksProviderUtils.Factory.get(context); + providerUtils = MyTracksProviderUtilsFactory.get(context); sharedPreferences = context.getSharedPreferences( Constants.SETTINGS_NAME, 0); @@ -405,12 +413,10 @@ public class TrackRecordingServiceTest ITrackRecordingService service = bindAndGetService(createStartIntent()); assertTrue(service.isRecording()); - try { - service.startNewTrack(); - fail("Expecting IllegalStateException"); - } catch (IllegalStateException e) { - // Expected. - } + // Starting a new track again should just return -1. + long newTrack = service.startNewTrack(); + assertEquals(-1L, newTrack); + assertEquals(123, sharedPreferences.getLong( context.getString(R.string.recording_track_key), 0)); assertEquals(123, service.getRecordingTrackId()); @@ -452,13 +458,12 @@ public class TrackRecordingServiceTest ITrackRecordingService service = bindAndGetService(createStartIntent()); assertFalse(service.isRecording()); - // End the current track. - try { - service.endCurrentTrack(); - fail("Expecting IllegalStateException"); - } catch (IllegalStateException e) { - // Expected. - } + /* + * Ending the current track when no track is been recording should not cause + * any error. + */ + service.endCurrentTrack(); + assertEquals(-1, sharedPreferences.getLong( context.getString(R.string.recording_track_key), 0)); assertEquals(-1, service.getRecordingTrackId());