summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGeorge Mount <mount@google.com>2013-02-20 17:01:54 -0800
committerGeorge Mount <mount@google.com>2013-02-26 12:49:13 -0800
commit178b04f4cea6dcbe0f84f0f189e9280d4c0d1442 (patch)
treedcf7aafa07634ee30491f50de3ce3d811723ec7e /src
parentaae069d8a006e4664414df56750b86844825b39c (diff)
downloadandroid_packages_apps_Snap-178b04f4cea6dcbe0f84f0f189e9280d4c0d1442.tar.gz
android_packages_apps_Snap-178b04f4cea6dcbe0f84f0f189e9280d4c0d1442.tar.bz2
android_packages_apps_Snap-178b04f4cea6dcbe0f84f0f189e9280d4c0d1442.zip
Add initial implementation of PhotosProvider.
Change-Id: I98694cf54bd0fb549703a7184e1816e9590a05ff
Diffstat (limited to 'src')
-rw-r--r--src/com/android/photos/data/PhotoDatabase.java111
-rw-r--r--src/com/android/photos/data/PhotoProvider.java514
2 files changed, 625 insertions, 0 deletions
diff --git a/src/com/android/photos/data/PhotoDatabase.java b/src/com/android/photos/data/PhotoDatabase.java
new file mode 100644
index 000000000..64a857fcc
--- /dev/null
+++ b/src/com/android/photos/data/PhotoDatabase.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.android.photos.data;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+import com.android.photos.data.PhotoProvider.Albums;
+import com.android.photos.data.PhotoProvider.Metadata;
+import com.android.photos.data.PhotoProvider.Photos;
+
+/**
+ * Used in PhotoProvider to create and access the database containing
+ * information about photo and video information stored on the server.
+ */
+public class PhotoDatabase extends SQLiteOpenHelper {
+ @SuppressWarnings("unused")
+ private static final String TAG = PhotoDatabase.class.getSimpleName();
+ static final String DB_NAME = "photo.db";
+ static final int DB_VERSION = 1;
+
+ private static final String SQL_CREATE_TABLE = "CREATE TABLE ";
+
+ private static final String[][] CREATE_PHOTO = {
+ { Photos._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
+ { Photos.SERVER_ID, "INTEGER UNIQUE" },
+ { Photos.WIDTH, "INTEGER NOT NULL" },
+ { Photos.HEIGHT, "INTEGER NOT NULL" },
+ { Photos.DATE_TAKEN, "INTEGER NOT NULL" },
+ // Photos.ALBUM_ID is a foreign key to Albums._ID
+ { Photos.ALBUM_ID, "INTEGER" },
+ { Photos.MIME_TYPE, "TEXT NOT NULL" },
+ };
+
+ private static final String[][] CREATE_ALBUM = {
+ { Albums._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
+ // Albums.PARENT_ID is a foriegn key to Albums._ID
+ { Albums.PARENT_ID, "INTEGER" },
+ { Albums.NAME, "Text NOT NULL" },
+ { Albums.VISIBILITY, "INTEGER NOT NULL" },
+ { Albums.SERVER_ID, "INTEGER UNIQUE" },
+ createUniqueConstraint(Albums.PARENT_ID, Albums.NAME),
+ };
+
+ private static final String[][] CREATE_METADATA = {
+ { Metadata._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
+ // Metadata.PHOTO_ID is a foreign key to Photos._ID
+ { Metadata.PHOTO_ID, "INTEGER NOT NULL" },
+ { Metadata.KEY, "TEXT NOT NULL" },
+ { Metadata.VALUE, "TEXT NOT NULL" },
+ createUniqueConstraint(Metadata.PHOTO_ID, Metadata.KEY),
+ };
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ createTable(db, Albums.TABLE, CREATE_ALBUM);
+ createTable(db, Photos.TABLE, CREATE_PHOTO);
+ createTable(db, Metadata.TABLE, CREATE_METADATA);
+ }
+
+ public PhotoDatabase(Context context) {
+ super(context, DB_NAME, null, DB_VERSION);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ }
+
+ protected static void createTable(SQLiteDatabase db, String table, String[][] columns) {
+ StringBuilder create = new StringBuilder(SQL_CREATE_TABLE);
+ create.append(table).append('(');
+ boolean first = true;
+ for (String[] column : columns) {
+ if (!first) {
+ create.append(',');
+ }
+ first = false;
+ for (String val: column) {
+ create.append(val).append(' ');
+ }
+ }
+ create.append(')');
+ db.beginTransaction();
+ try {
+ db.execSQL(create.toString());
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ protected static String[] createUniqueConstraint(String column1, String column2) {
+ return new String[] {
+ "UNIQUE(", column1, ",", column2, ")"
+ };
+ }
+}
diff --git a/src/com/android/photos/data/PhotoProvider.java b/src/com/android/photos/data/PhotoProvider.java
new file mode 100644
index 000000000..eefa37349
--- /dev/null
+++ b/src/com/android/photos/data/PhotoProvider.java
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.android.photos.data;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteStatement;
+import android.net.Uri;
+import android.os.CancellationSignal;
+import android.provider.BaseColumns;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A provider that gives access to photo and video information for media stored
+ * on the server. Only media that is or will be put on the server will be
+ * accessed by this provider. Use Photos.CONTENT_URI to query all photos and
+ * videos. Use Albums.CONTENT_URI to query all albums. Use Metadata.CONTENT_URI
+ * to query metadata about a photo or video, based on the ID of the media. Use
+ * ImageCache.THUMBNAIL_CONTENT_URI, ImageCache.PREVIEW_CONTENT_URI, or
+ * ImageCache.ORIGINAL_CONTENT_URI to query the path of the thumbnail, preview,
+ * or original-sized image respectfully. <br/>
+ * To add or update metadata, use the update function rather than insert. All
+ * values for the metadata must be in the ContentValues, even if they are also
+ * in the selection. The selection and selectionArgs are not used when updating
+ * metadata. If the metadata values are null, the row will be deleted.
+ */
+public class PhotoProvider extends ContentProvider {
+ @SuppressWarnings("unused")
+ private static final String TAG = PhotoProvider.class.getSimpleName();
+ static final String AUTHORITY = "com.android.gallery3d.photoprovider";
+ static final Uri BASE_CONTENT_URI = new Uri.Builder().scheme("content").authority(AUTHORITY)
+ .build();
+
+ /**
+ * Contains columns that can be accessed via PHOTOS_CONTENT_URI.
+ */
+ public static interface Photos extends BaseColumns {
+ /**
+ * Internal database table used for basic photo information.
+ */
+ public static final String TABLE = "photo";
+ /**
+ * Content URI for basic photo and video information.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
+ /**
+ * Identifier used on the server. Long value.
+ */
+ public static final String SERVER_ID = "server_id";
+ /**
+ * Column name for the width of the original image. Integer value.
+ */
+ public static final String WIDTH = "width";
+ /**
+ * Column name for the height of the original image. Integer value.
+ */
+ public static final String HEIGHT = "height";
+ /**
+ * Column name for the date that the original image was taken. Long
+ * value indicating the milliseconds since epoch in the GMT time zone.
+ */
+ public static final String DATE_TAKEN = "date_taken";
+ /**
+ * Column name indicating the long value of the album id that this image
+ * resides in. Will be NULL if it it has not been uploaded to the
+ * server.
+ */
+ public static final String ALBUM_ID = "album_id";
+ /**
+ * The column name for the mime-type String.
+ */
+ public static final String MIME_TYPE = "mime_type";
+ }
+
+ /**
+ * Contains columns and Uri for accessing album information.
+ */
+ public static interface Albums extends BaseColumns {
+ /**
+ * Internal database table used album information.
+ */
+ public static final String TABLE = "album";
+ /**
+ * Content URI for album information.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
+ /**
+ * Parent directory or null if this is in the root.
+ */
+ public static final String PARENT_ID = "parent";
+ /**
+ * Column name for the name of the album. String value.
+ */
+ public static final String NAME = "name";
+ /**
+ * Column name for the visibility level of the album. Can be any of the
+ * VISIBILITY_* values.
+ */
+ public static final String VISIBILITY = "visibility";
+ /**
+ * Column name for the server identifier for this album. NULL if the
+ * server doesn't have this album yet.
+ */
+ public static final String SERVER_ID = "server_id";
+
+ // Privacy values for Albums.VISIBILITY
+ public static final int VISIBILITY_PRIVATE = 1;
+ public static final int VISIBILITY_SHARED = 2;
+ public static final int VISIBILITY_PUBLIC = 3;
+ }
+
+ /**
+ * Contains columns and Uri for accessing photo and video metadata
+ */
+ public static interface Metadata extends BaseColumns {
+ /**
+ * Internal database table used metadata information.
+ */
+ public static final String TABLE = "metadata";
+ /**
+ * Content URI for photo and video metadata.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
+ /**
+ * Foreign key to photo_id. Long value.
+ */
+ public static final String PHOTO_ID = "photo_id";
+ /**
+ * Metadata key. String value
+ */
+ public static final String KEY = "key";
+ /**
+ * Metadata value. Type is based on key.
+ */
+ public static final String VALUE = "value";
+ }
+
+ /**
+ * Contains columns and Uri for maintaining the image cache.
+ */
+ public static interface ImageCache extends BaseColumns {
+ /**
+ * Internal database table used for the image cache
+ */
+ public static final String TABLE = "image_cache";
+
+ /**
+ * The image_type query parameter required for accessing a specific
+ * image
+ */
+ public static final String IMAGE_TYPE_QUERY_PARAMETER = "image_type";
+
+ // ImageCache.IMAGE_TYPE values
+ public static final int IMAGE_TYPE_THUMBNAIL = 1;
+ public static final int IMAGE_TYPE_PREVIEW = 2;
+ public static final int IMAGE_TYPE_ORIGINAL = 3;
+
+ /**
+ * Content URI for retrieving image paths. The
+ * IMAGE_TYPE_QUERY_PARAMETER must be used in queries.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
+
+ /**
+ * Foreign key to the photos._id. Long value.
+ */
+ public static final String PHOTO_ID = "photos_id";
+ /**
+ * One of IMAGE_TYPE_* values.
+ */
+ public static final String IMAGE_TYPE = "image_type";
+ /**
+ * The String path to the image.
+ */
+ public static final String PATH = "path";
+ };
+
+ // SQL used within this class.
+ protected static final String WHERE_ID = BaseColumns._ID + " = ?";
+ protected static final String WHERE_METADATA_ID = Metadata.PHOTO_ID + " = ? AND "
+ + Metadata.KEY + " = ?";
+
+ protected static final String SELECT_ALBUM_ID = "SELECT " + Albums._ID + " FROM "
+ + Albums.TABLE;
+ protected static final String SELECT_PHOTO_ID = "SELECT " + Photos._ID + " FROM "
+ + Photos.TABLE;
+ protected static final String SELECT_PHOTO_COUNT = "SELECT COUNT(*) FROM " + Photos.TABLE;
+ protected static final String DELETE_PHOTOS = "DELETE FROM " + Photos.TABLE;
+ protected static final String DELETE_METADATA = "DELETE FROM " + Metadata.TABLE;
+ protected static final String SELECT_METADATA_COUNT = "SELECT COUNT(*) FROM " + Metadata.TABLE;
+ protected static final String WHERE = " WHERE ";
+ protected static final String IN = " IN ";
+ protected static final String NESTED_SELECT_START = "(";
+ protected static final String NESTED_SELECT_END = ")";
+
+ /**
+ * For selecting the mime-type for an image.
+ */
+ private static final String[] PROJECTION_MIME_TYPE = {
+ Photos.MIME_TYPE,
+ };
+
+ private SQLiteOpenHelper mOpenHelper;
+ protected static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+ protected static final int MATCH_PHOTO = 1;
+ protected static final int MATCH_PHOTO_ID = 2;
+ protected static final int MATCH_ALBUM = 3;
+ protected static final int MATCH_ALBUM_ID = 4;
+ protected static final int MATCH_METADATA = 5;
+ protected static final int MATCH_METADATA_ID = 6;
+ protected static final int MATCH_IMAGE = 7;
+
+ static {
+ sUriMatcher.addURI(AUTHORITY, Photos.TABLE, MATCH_PHOTO);
+ // match against Photos._ID
+ sUriMatcher.addURI(AUTHORITY, Photos.TABLE + "/#", MATCH_PHOTO_ID);
+ sUriMatcher.addURI(AUTHORITY, Albums.TABLE, MATCH_ALBUM);
+ // match against Albums._ID
+ sUriMatcher.addURI(AUTHORITY, Albums.TABLE + "/#", MATCH_ALBUM_ID);
+ sUriMatcher.addURI(AUTHORITY, Metadata.TABLE, MATCH_METADATA);
+ // match against metadata/<Metadata._ID>
+ sUriMatcher.addURI(AUTHORITY, Metadata.TABLE + "/#", MATCH_METADATA_ID);
+ // match against image_cache/<ImageCache.PHOTO_ID>
+ sUriMatcher.addURI(AUTHORITY, ImageCache.TABLE + "/#", MATCH_IMAGE);
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ int match = matchUri(uri);
+ if (match == MATCH_IMAGE) {
+ throw new IllegalArgumentException("Cannot delete from image cache");
+ }
+ selection = addIdToSelection(match, selection);
+ selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
+ List<Uri> changeUris = new ArrayList<Uri>();
+ int deleted = 0;
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ deleted = deleteCascade(db, match, selection, selectionArgs, changeUris, uri);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ for (Uri changeUri : changeUris) {
+ notifyChanges(changeUri);
+ }
+ return deleted;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ Cursor cursor = query(uri, PROJECTION_MIME_TYPE, null, null, null);
+ String mimeType = null;
+ if (cursor.moveToNext()) {
+ mimeType = cursor.getString(0);
+ }
+ cursor.close();
+ return mimeType;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ // Cannot insert into this ContentProvider
+ return null;
+ }
+
+ @Override
+ public boolean onCreate() {
+ mOpenHelper = createDatabaseHelper();
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return query(uri, projection, selection, selectionArgs, sortOrder, null);
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder, CancellationSignal cancellationSignal) {
+ int match = matchUri(uri);
+ selection = addIdToSelection(match, selection);
+ selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
+ String table = getTableFromMatch(match, uri);
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ return db.query(false, table, projection, selection, selectionArgs, null, null, sortOrder,
+ null, cancellationSignal);
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ int match = matchUri(uri);
+ int rowsUpdated = 0;
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ if (match == MATCH_METADATA) {
+ rowsUpdated = modifyMetadata(db, values);
+ } else {
+ selection = addIdToSelection(match, selection);
+ selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
+ String table = getTableFromMatch(match, uri);
+ rowsUpdated = db.update(table, values, selection, selectionArgs);
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ notifyChanges(uri);
+ return rowsUpdated;
+ }
+
+ protected static String addIdToSelection(int match, String selection) {
+ String where;
+ switch (match) {
+ case MATCH_PHOTO_ID:
+ case MATCH_ALBUM_ID:
+ case MATCH_METADATA_ID:
+ where = WHERE_ID;
+ break;
+ default:
+ return selection;
+ }
+ return DatabaseUtils.concatenateWhere(selection, where);
+ }
+
+ protected static String[] addIdToSelectionArgs(int match, Uri uri, String[] selectionArgs) {
+ String[] whereArgs;
+ switch (match) {
+ case MATCH_PHOTO_ID:
+ case MATCH_ALBUM_ID:
+ case MATCH_METADATA_ID:
+ whereArgs = new String[] {
+ uri.getPathSegments().get(1),
+ };
+ break;
+ default:
+ return selectionArgs;
+ }
+ return DatabaseUtils.appendSelectionArgs(selectionArgs, whereArgs);
+ }
+
+ protected static String[] addMetadataKeysToSelectionArgs(String[] selectionArgs, Uri uri) {
+ List<String> segments = uri.getPathSegments();
+ String[] additionalArgs = {
+ segments.get(1),
+ segments.get(2),
+ };
+
+ return DatabaseUtils.appendSelectionArgs(selectionArgs, additionalArgs);
+ }
+
+ protected static String getTableFromMatch(int match, Uri uri) {
+ String table;
+ switch (match) {
+ case MATCH_PHOTO:
+ case MATCH_PHOTO_ID:
+ table = Photos.TABLE;
+ break;
+ case MATCH_ALBUM:
+ case MATCH_ALBUM_ID:
+ table = Albums.TABLE;
+ break;
+ case MATCH_METADATA:
+ case MATCH_METADATA_ID:
+ table = Metadata.TABLE;
+ break;
+ default:
+ throw unknownUri(uri);
+ }
+ return table;
+ }
+
+ protected final SQLiteOpenHelper getDatabaseHelper() {
+ return mOpenHelper;
+ }
+
+ protected SQLiteOpenHelper createDatabaseHelper() {
+ return new PhotoDatabase(getContext());
+ }
+
+ private int modifyMetadata(SQLiteDatabase db, ContentValues values) {
+ String[] selectionArgs = {
+ values.getAsString(Metadata.PHOTO_ID),
+ values.getAsString(Metadata.KEY),
+ };
+ int rowCount;
+ if (values.get(Metadata.VALUE) == null) {
+ rowCount = db.delete(Metadata.TABLE, WHERE_METADATA_ID, selectionArgs);
+ } else {
+ rowCount = (int) DatabaseUtils.queryNumEntries(db, Metadata.TABLE, WHERE_METADATA_ID,
+ selectionArgs);
+ if (rowCount > 0) {
+ db.update(Metadata.TABLE, values, WHERE_METADATA_ID, selectionArgs);
+ } else {
+ db.insert(Metadata.TABLE, null, values);
+ rowCount = 1;
+ }
+ }
+ return rowCount;
+ }
+
+ private int matchUri(Uri uri) {
+ int match = sUriMatcher.match(uri);
+ if (match == UriMatcher.NO_MATCH) {
+ throw unknownUri(uri);
+ }
+ return match;
+ }
+
+ protected void notifyChanges(Uri uri) {
+ ContentResolver resolver = getContext().getContentResolver();
+ resolver.notifyChange(uri, null, false);
+ }
+
+ protected static IllegalArgumentException unknownUri(Uri uri) {
+ return new IllegalArgumentException("Unknown Uri format: " + uri);
+ }
+
+ protected static String nestSql(String base, String columnMatch, String nested) {
+ StringBuilder sql = new StringBuilder(base);
+ sql.append(WHERE);
+ sql.append(columnMatch);
+ sql.append(IN);
+ sql.append(NESTED_SELECT_START);
+ sql.append(nested);
+ sql.append(NESTED_SELECT_END);
+ return sql.toString();
+ }
+
+ protected static String addWhere(String base, String where) {
+ if (where == null || where.isEmpty()) {
+ return base;
+ }
+ return base + WHERE + where;
+ }
+
+ protected static int deleteCascade(SQLiteDatabase db, int match, String selection,
+ String[] selectionArgs, List<Uri> changeUris, Uri uri) {
+ switch (match) {
+ case MATCH_PHOTO:
+ case MATCH_PHOTO_ID: {
+ String selectPhotoIdsSql = addWhere(SELECT_PHOTO_ID, selection);
+ deleteCascadeMetadata(db, selectPhotoIdsSql, selectionArgs, changeUris);
+ break;
+ }
+ case MATCH_ALBUM:
+ case MATCH_ALBUM_ID: {
+ String selectAlbumIdSql = addWhere(SELECT_ALBUM_ID, selection);
+ deleteCascadePhotos(db, selectAlbumIdSql, selectionArgs, changeUris);
+ break;
+ }
+ }
+ String table = getTableFromMatch(match, uri);
+ changeUris.add(uri);
+ return db.delete(table, selection, selectionArgs);
+ }
+
+ protected static void execSql(SQLiteDatabase db, String sql, String[] args) {
+ if (args == null) {
+ db.execSQL(sql);
+ } else {
+ db.execSQL(sql, args);
+ }
+ }
+
+ private static void deleteCascadePhotos(SQLiteDatabase db, String albumSelect,
+ String[] selectArgs, List<Uri> changeUris) {
+ String selectPhotoIdSql = nestSql(SELECT_PHOTO_ID, Photos.ALBUM_ID, albumSelect);
+ deleteCascadeMetadata(db, selectPhotoIdSql, selectArgs, changeUris);
+ String deletePhotoSql = nestSql(DELETE_PHOTOS, Photos.ALBUM_ID, albumSelect);
+ SQLiteStatement statement = db.compileStatement(deletePhotoSql);
+ statement.bindAllArgsAsStrings(selectArgs);
+ int deleted = statement.executeUpdateDelete();
+ if (deleted > 0) {
+ changeUris.add(Photos.CONTENT_URI);
+ }
+ }
+
+ private static void deleteCascadeMetadata(SQLiteDatabase db, String photosSelect,
+ String[] selectArgs, List<Uri> changeUris) {
+ String deleteMetadataSql = nestSql(DELETE_METADATA, Metadata.PHOTO_ID, photosSelect);
+ SQLiteStatement statement = db.compileStatement(deleteMetadataSql);
+ statement.bindAllArgsAsStrings(selectArgs);
+ int deleted = statement.executeUpdateDelete();
+ if (deleted > 0) {
+ changeUris.add(Metadata.CONTENT_URI);
+ }
+ }
+}