PhotoProvider.java revision 135c2e576f3dfea954ba628942c55adcb35a7cf6
1c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount/* 2c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Copyright (C) 2013 The Android Open Source Project 3c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * 4c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Licensed under the Apache License, Version 2.0 (the "License"); 5c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * you may not use this file except in compliance with the License. 6c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * You may obtain a copy of the License at 7c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * 8c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * http://www.apache.org/licenses/LICENSE-2.0 9c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * 10c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Unless required by applicable law or agreed to in writing, software 11c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * distributed under the License is distributed on an "AS IS" BASIS, 12c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * See the License for the specific language governing permissions and 14c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * limitations under the License. 15c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 16c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountpackage com.android.photos.data; 17c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 18c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.content.ContentProvider; 19c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.content.ContentValues; 20c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.content.UriMatcher; 21c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.Cursor; 22c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.DatabaseUtils; 23c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.sqlite.SQLiteDatabase; 24c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.database.sqlite.SQLiteOpenHelper; 25135c2e576f3dfea954ba628942c55adcb35a7cf6George Mountimport android.database.sqlite.SQLiteQueryBuilder; 26c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.net.Uri; 27c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.os.CancellationSignal; 28c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport android.provider.BaseColumns; 29c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 30135c2e576f3dfea954ba628942c55adcb35a7cf6George Mountimport com.google.android.gms.common.util.VisibleForTesting; 31135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount 32c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport java.util.ArrayList; 33c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountimport java.util.List; 34c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 35c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount/** 36c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * A provider that gives access to photo and video information for media stored 37c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * on the server. Only media that is or will be put on the server will be 38c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * accessed by this provider. Use Photos.CONTENT_URI to query all photos and 39c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * videos. Use Albums.CONTENT_URI to query all albums. Use Metadata.CONTENT_URI 40c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * to query metadata about a photo or video, based on the ID of the media. Use 41c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * ImageCache.THUMBNAIL_CONTENT_URI, ImageCache.PREVIEW_CONTENT_URI, or 42c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * ImageCache.ORIGINAL_CONTENT_URI to query the path of the thumbnail, preview, 43c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * or original-sized image respectfully. <br/> 44c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * To add or update metadata, use the update function rather than insert. All 45c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * values for the metadata must be in the ContentValues, even if they are also 46c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * in the selection. The selection and selectionArgs are not used when updating 47c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * metadata. If the metadata values are null, the row will be deleted. 48c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 49c8419b4e5e3302f2efc7ea629891041a14219aa7George Mountpublic class PhotoProvider extends ContentProvider { 50c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount @SuppressWarnings("unused") 51c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount private static final String TAG = PhotoProvider.class.getSimpleName(); 52135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount 53135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount protected static final String DB_NAME = "photo.db"; 54135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount public static final String AUTHORITY = PhotoProviderAuthority.AUTHORITY; 55c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount static final Uri BASE_CONTENT_URI = new Uri.Builder().scheme("content").authority(AUTHORITY) 56c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount .build(); 57c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 58135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount // Used to allow mocking out the change notification because 59135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount // MockContextResolver disallows system-wide notification. 60135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount public static interface ChangeNotification { 61135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount void notifyChange(Uri uri); 62135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount } 63135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount 64c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 65c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Contains columns that can be accessed via PHOTOS_CONTENT_URI. 66c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 67c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static interface Photos extends BaseColumns { 68c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 69c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Internal database table used for basic photo information. 70c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 71c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String TABLE = "photo"; 72c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 73c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Content URI for basic photo and video information. 74c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 75c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE); 76c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 77c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Identifier used on the server. Long value. 78c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 79c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String SERVER_ID = "server_id"; 80c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 81c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Column name for the width of the original image. Integer value. 82c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 83c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String WIDTH = "width"; 84c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 85c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Column name for the height of the original image. Integer value. 86c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 87c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String HEIGHT = "height"; 88c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 89c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Column name for the date that the original image was taken. Long 90c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * value indicating the milliseconds since epoch in the GMT time zone. 91c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 92c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String DATE_TAKEN = "date_taken"; 93c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 94c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Column name indicating the long value of the album id that this image 95c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * resides in. Will be NULL if it it has not been uploaded to the 96c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * server. 97c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 98c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String ALBUM_ID = "album_id"; 99c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 100c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * The column name for the mime-type String. 101c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 102c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String MIME_TYPE = "mime_type"; 103c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 104c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 105c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 106c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Contains columns and Uri for accessing album information. 107c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 108c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static interface Albums extends BaseColumns { 109c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 110c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Internal database table used album information. 111c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 112c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String TABLE = "album"; 113c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 114c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Content URI for album information. 115c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 116c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE); 117c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 118c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Parent directory or null if this is in the root. 119c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 120c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String PARENT_ID = "parent"; 121c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 122c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Column name for the name of the album. String value. 123c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 124c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String NAME = "name"; 125c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 126c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Column name for the visibility level of the album. Can be any of the 127c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * VISIBILITY_* values. 128c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 129c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String VISIBILITY = "visibility"; 130c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 131c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Column name for the server identifier for this album. NULL if the 132c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * server doesn't have this album yet. 133c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 134c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String SERVER_ID = "server_id"; 135c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 136c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount // Privacy values for Albums.VISIBILITY 137c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final int VISIBILITY_PRIVATE = 1; 138c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final int VISIBILITY_SHARED = 2; 139c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final int VISIBILITY_PUBLIC = 3; 140c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 141c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 142c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 143c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Contains columns and Uri for accessing photo and video metadata 144c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 145c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static interface Metadata extends BaseColumns { 146c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 147c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Internal database table used metadata information. 148c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 149c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String TABLE = "metadata"; 150c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 151c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Content URI for photo and video metadata. 152c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 153c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE); 154c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 155c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Foreign key to photo_id. Long value. 156c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 157c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String PHOTO_ID = "photo_id"; 158c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 159c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Metadata key. String value 160c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 161c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String KEY = "key"; 162c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 163c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Metadata value. Type is based on key. 164c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 165c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String VALUE = "value"; 166c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 167c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 168c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 169c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Contains columns and Uri for maintaining the image cache. 170c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 171c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static interface ImageCache extends BaseColumns { 172c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 173c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Internal database table used for the image cache 174c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 175c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String TABLE = "image_cache"; 176c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 177c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 178c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * The image_type query parameter required for accessing a specific 179c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * image 180c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 181c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String IMAGE_TYPE_QUERY_PARAMETER = "image_type"; 182c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 183c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount // ImageCache.IMAGE_TYPE values 184c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final int IMAGE_TYPE_THUMBNAIL = 1; 185c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final int IMAGE_TYPE_PREVIEW = 2; 186c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final int IMAGE_TYPE_ORIGINAL = 3; 187c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 188c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 189c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Content URI for retrieving image paths. The 190c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * IMAGE_TYPE_QUERY_PARAMETER must be used in queries. 191c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 192c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE); 193c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 194c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 195c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * Foreign key to the photos._id. Long value. 196c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 197135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount public static final String PHOTO_ID = "photo_id"; 198c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 199c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * One of IMAGE_TYPE_* values. 200c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 201c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String IMAGE_TYPE = "image_type"; 202c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 203c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * The String path to the image. 204c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 205c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public static final String PATH = "path"; 206c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount }; 207c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 208c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount // SQL used within this class. 209c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String WHERE_ID = BaseColumns._ID + " = ?"; 210c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String WHERE_METADATA_ID = Metadata.PHOTO_ID + " = ? AND " 211c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount + Metadata.KEY + " = ?"; 212c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 213c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String SELECT_ALBUM_ID = "SELECT " + Albums._ID + " FROM " 214c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount + Albums.TABLE; 215c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String SELECT_PHOTO_ID = "SELECT " + Photos._ID + " FROM " 216c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount + Photos.TABLE; 217c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String SELECT_PHOTO_COUNT = "SELECT COUNT(*) FROM " + Photos.TABLE; 218c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String DELETE_PHOTOS = "DELETE FROM " + Photos.TABLE; 219c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String DELETE_METADATA = "DELETE FROM " + Metadata.TABLE; 220c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String SELECT_METADATA_COUNT = "SELECT COUNT(*) FROM " + Metadata.TABLE; 221c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String WHERE = " WHERE "; 222c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String IN = " IN "; 223c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String NESTED_SELECT_START = "("; 224c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final String NESTED_SELECT_END = ")"; 225c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 226c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount /** 227c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount * For selecting the mime-type for an image. 228c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount */ 229c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount private static final String[] PROJECTION_MIME_TYPE = { 230c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount Photos.MIME_TYPE, 231c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount }; 232c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 233135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount private static final String[] BASE_COLUMNS_ID = { 234135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount BaseColumns._ID, 235135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount }; 236135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount 237135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount protected ChangeNotification mNotifier = null; 238c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount private SQLiteOpenHelper mOpenHelper; 239c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 240c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 241c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final int MATCH_PHOTO = 1; 242c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final int MATCH_PHOTO_ID = 2; 243c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final int MATCH_ALBUM = 3; 244c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final int MATCH_ALBUM_ID = 4; 245c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final int MATCH_METADATA = 5; 246c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final int MATCH_METADATA_ID = 6; 247c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static final int MATCH_IMAGE = 7; 248c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 249c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount static { 250c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount sUriMatcher.addURI(AUTHORITY, Photos.TABLE, MATCH_PHOTO); 251c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount // match against Photos._ID 252c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount sUriMatcher.addURI(AUTHORITY, Photos.TABLE + "/#", MATCH_PHOTO_ID); 253c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount sUriMatcher.addURI(AUTHORITY, Albums.TABLE, MATCH_ALBUM); 254c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount // match against Albums._ID 255c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount sUriMatcher.addURI(AUTHORITY, Albums.TABLE + "/#", MATCH_ALBUM_ID); 256c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount sUriMatcher.addURI(AUTHORITY, Metadata.TABLE, MATCH_METADATA); 257c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount // match against metadata/<Metadata._ID> 258c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount sUriMatcher.addURI(AUTHORITY, Metadata.TABLE + "/#", MATCH_METADATA_ID); 259c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount // match against image_cache/<ImageCache.PHOTO_ID> 260c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount sUriMatcher.addURI(AUTHORITY, ImageCache.TABLE + "/#", MATCH_IMAGE); 261c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 262c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 263c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount @Override 264c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public int delete(Uri uri, String selection, String[] selectionArgs) { 265c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount int match = matchUri(uri); 266c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount if (match == MATCH_IMAGE) { 267c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount throw new IllegalArgumentException("Cannot delete from image cache"); 268c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 269c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount selection = addIdToSelection(match, selection); 270c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs); 271c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount List<Uri> changeUris = new ArrayList<Uri>(); 272c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount int deleted = 0; 273c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 274c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount db.beginTransaction(); 275c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount try { 276c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount deleted = deleteCascade(db, match, selection, selectionArgs, changeUris, uri); 277c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount db.setTransactionSuccessful(); 278c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } finally { 279c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount db.endTransaction(); 280c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 281c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount for (Uri changeUri : changeUris) { 282c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount notifyChanges(changeUri); 283c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 284c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return deleted; 285c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 286c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 287c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount @Override 288c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public String getType(Uri uri) { 289c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount Cursor cursor = query(uri, PROJECTION_MIME_TYPE, null, null, null); 290c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String mimeType = null; 291c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount if (cursor.moveToNext()) { 292c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount mimeType = cursor.getString(0); 293c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 294c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount cursor.close(); 295c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return mimeType; 296c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 297c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 298c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount @Override 299c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public Uri insert(Uri uri, ContentValues values) { 300c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount // Cannot insert into this ContentProvider 301c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return null; 302c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 303c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 304c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount @Override 305c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public boolean onCreate() { 306c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount mOpenHelper = createDatabaseHelper(); 307c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return true; 308c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 309c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 310c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount @Override 311135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount public void shutdown() { 312135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount getDatabaseHelper().close(); 313135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount } 314135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount 315135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount @Override 316c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 317c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String sortOrder) { 318c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return query(uri, projection, selection, selectionArgs, sortOrder, null); 319c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 320c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 321c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount @Override 322c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 323c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String sortOrder, CancellationSignal cancellationSignal) { 324c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount int match = matchUri(uri); 325c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount selection = addIdToSelection(match, selection); 326c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs); 327c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String table = getTableFromMatch(match, uri); 328c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 329c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return db.query(false, table, projection, selection, selectionArgs, null, null, sortOrder, 330c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount null, cancellationSignal); 331c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 332c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 333c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount @Override 334c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 335c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount int match = matchUri(uri); 336c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount int rowsUpdated = 0; 337c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 338c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount db.beginTransaction(); 339c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount try { 340c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount if (match == MATCH_METADATA) { 341c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount rowsUpdated = modifyMetadata(db, values); 342c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } else { 343c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount selection = addIdToSelection(match, selection); 344c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs); 345c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String table = getTableFromMatch(match, uri); 346c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount rowsUpdated = db.update(table, values, selection, selectionArgs); 347c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 348c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount db.setTransactionSuccessful(); 349c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } finally { 350c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount db.endTransaction(); 351c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 352c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount notifyChanges(uri); 353c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return rowsUpdated; 354c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 355c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 356135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount @VisibleForTesting 357135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount public void setMockNotification(ChangeNotification notification) { 358135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount mNotifier = notification; 359135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount } 360135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount 361c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static String addIdToSelection(int match, String selection) { 362c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String where; 363c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount switch (match) { 364c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_PHOTO_ID: 365c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_ALBUM_ID: 366c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_METADATA_ID: 367c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount where = WHERE_ID; 368c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount break; 369c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount default: 370c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return selection; 371c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 372c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return DatabaseUtils.concatenateWhere(selection, where); 373c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 374c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 375c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static String[] addIdToSelectionArgs(int match, Uri uri, String[] selectionArgs) { 376c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String[] whereArgs; 377c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount switch (match) { 378c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_PHOTO_ID: 379c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_ALBUM_ID: 380c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_METADATA_ID: 381c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount whereArgs = new String[] { 382c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount uri.getPathSegments().get(1), 383c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount }; 384c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount break; 385c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount default: 386c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return selectionArgs; 387c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 388c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return DatabaseUtils.appendSelectionArgs(selectionArgs, whereArgs); 389c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 390c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 391c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static String[] addMetadataKeysToSelectionArgs(String[] selectionArgs, Uri uri) { 392c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount List<String> segments = uri.getPathSegments(); 393c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String[] additionalArgs = { 394c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount segments.get(1), 395c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount segments.get(2), 396c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount }; 397c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 398c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return DatabaseUtils.appendSelectionArgs(selectionArgs, additionalArgs); 399c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 400c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 401c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static String getTableFromMatch(int match, Uri uri) { 402c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String table; 403c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount switch (match) { 404c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_PHOTO: 405c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_PHOTO_ID: 406c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount table = Photos.TABLE; 407c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount break; 408c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_ALBUM: 409c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_ALBUM_ID: 410c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount table = Albums.TABLE; 411c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount break; 412c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_METADATA: 413c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_METADATA_ID: 414c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount table = Metadata.TABLE; 415c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount break; 416c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount default: 417c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount throw unknownUri(uri); 418c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 419c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return table; 420c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 421c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 422c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected final SQLiteOpenHelper getDatabaseHelper() { 423c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return mOpenHelper; 424c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 425c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 426c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected SQLiteOpenHelper createDatabaseHelper() { 427135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount return new PhotoDatabase(getContext(), DB_NAME); 428c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 429c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 430c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount private int modifyMetadata(SQLiteDatabase db, ContentValues values) { 431c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String[] selectionArgs = { 432c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount values.getAsString(Metadata.PHOTO_ID), 433c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount values.getAsString(Metadata.KEY), 434c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount }; 435c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount int rowCount; 436c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount if (values.get(Metadata.VALUE) == null) { 437c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount rowCount = db.delete(Metadata.TABLE, WHERE_METADATA_ID, selectionArgs); 438c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } else { 439c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount rowCount = (int) DatabaseUtils.queryNumEntries(db, Metadata.TABLE, WHERE_METADATA_ID, 440c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount selectionArgs); 441c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount if (rowCount > 0) { 442c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount db.update(Metadata.TABLE, values, WHERE_METADATA_ID, selectionArgs); 443c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } else { 444c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount db.insert(Metadata.TABLE, null, values); 445c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount rowCount = 1; 446c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 447c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 448c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return rowCount; 449c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 450c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 451c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount private int matchUri(Uri uri) { 452c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount int match = sUriMatcher.match(uri); 453c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount if (match == UriMatcher.NO_MATCH) { 454c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount throw unknownUri(uri); 455c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 456c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return match; 457c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 458c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 459c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected void notifyChanges(Uri uri) { 460135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount if (mNotifier != null) { 461135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount mNotifier.notifyChange(uri); 462135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount } else { 463135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount getContext().getContentResolver().notifyChange(uri, null, false); 464135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount } 465c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 466c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 467c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static IllegalArgumentException unknownUri(Uri uri) { 468c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount return new IllegalArgumentException("Unknown Uri format: " + uri); 469c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 470c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 471135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount protected static String nestWhere(String matchColumn, String table, String nestedWhere) { 472135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount String query = SQLiteQueryBuilder.buildQueryString(false, table, BASE_COLUMNS_ID, 473135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount nestedWhere, null, null, null, null); 474135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount return matchColumn + IN + NESTED_SELECT_START + query + NESTED_SELECT_END; 475c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 476c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 477c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount protected static int deleteCascade(SQLiteDatabase db, int match, String selection, 478c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String[] selectionArgs, List<Uri> changeUris, Uri uri) { 479c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount switch (match) { 480c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_PHOTO: 481c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_PHOTO_ID: { 482135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount deleteCascadeMetadata(db, selection, selectionArgs, changeUris); 483c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount break; 484c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 485c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_ALBUM: 486c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount case MATCH_ALBUM_ID: { 487135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount deleteCascadePhotos(db, selection, selectionArgs, changeUris); 488c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount break; 489c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 490c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 491c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String table = getTableFromMatch(match, uri); 492135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount int deleted = db.delete(table, selection, selectionArgs); 493135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount if (deleted > 0) { 494135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount changeUris.add(uri); 495c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 496135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount return deleted; 497c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 498c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 499c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount private static void deleteCascadePhotos(SQLiteDatabase db, String albumSelect, 500c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String[] selectArgs, List<Uri> changeUris) { 501135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount String photoWhere = nestWhere(Photos.ALBUM_ID, Albums.TABLE, albumSelect); 502135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount deleteCascadeMetadata(db, photoWhere, selectArgs, changeUris); 503135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount int deleted = db.delete(Photos.TABLE, photoWhere, selectArgs); 504c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount if (deleted > 0) { 505c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount changeUris.add(Photos.CONTENT_URI); 506c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 507c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 508c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount 509c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount private static void deleteCascadeMetadata(SQLiteDatabase db, String photosSelect, 510c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount String[] selectArgs, List<Uri> changeUris) { 511135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount String metadataWhere = nestWhere(Metadata.PHOTO_ID, Photos.TABLE, photosSelect); 512135c2e576f3dfea954ba628942c55adcb35a7cf6George Mount int deleted = db.delete(Metadata.TABLE, metadataWhere, selectArgs); 513c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount if (deleted > 0) { 514c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount changeUris.add(Metadata.CONTENT_URI); 515c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 516c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount } 517c8419b4e5e3302f2efc7ea629891041a14219aa7George Mount} 518