FeedProvider.java (10069B)
1 package de.nordgedanken.rpicms.basicsyncadapter.provider; 2 3 /** 4 * Created by frank on 13.10.14. 5 */ 6 import android.content.ContentProvider; 7 import android.content.ContentValues; 8 import android.content.Context; 9 import android.content.UriMatcher; 10 import android.database.Cursor; 11 import android.database.sqlite.SQLiteDatabase; 12 import android.database.sqlite.SQLiteOpenHelper; 13 import android.net.Uri; 14 15 import de.nordgedanken.rpicms.common.db.SelectionBuilder; 16 17 public class FeedProvider extends ContentProvider { 18 19 20 FeedDatabase mDatabaseHelper; 21 22 /** 23 * Content authority for this provider. 24 */ 25 private static final String AUTHORITY = FeedContract.CONTENT_AUTHORITY; 26 27 // The constants below represent individual URI routes, as IDs. Every URI pattern recognized by 28 // this ContentProvider is defined using sUriMatcher.addURI(), and associated with one of these 29 // IDs. 30 // 31 // When a incoming URI is run through sUriMatcher, it will be tested against the defined 32 // URI patterns, and the corresponding route ID will be returned. 33 /** 34 * URI ID for route: /entries 35 */ 36 public static final int ROUTE_ENTRIES = 1; 37 38 /** 39 * URI ID for route: /entries/{ID} 40 */ 41 public static final int ROUTE_ENTRIES_ID = 2; 42 43 /** 44 * UriMatcher, used to decode incoming URIs. 45 */ 46 private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 47 static { 48 sUriMatcher.addURI(AUTHORITY, "entries", ROUTE_ENTRIES); 49 sUriMatcher.addURI(AUTHORITY, "entries/*", ROUTE_ENTRIES_ID); 50 } 51 52 @Override 53 public boolean onCreate() { 54 mDatabaseHelper = new FeedDatabase(getContext()); 55 return true; 56 } 57 58 /** 59 * Determine the mime type for entries returned by a given URI. 60 */ 61 @Override 62 public String getType(Uri uri) { 63 final int match = sUriMatcher.match(uri); 64 switch (match) { 65 case ROUTE_ENTRIES: 66 return FeedContract.Entry.CONTENT_TYPE; 67 case ROUTE_ENTRIES_ID: 68 return FeedContract.Entry.CONTENT_ITEM_TYPE; 69 default: 70 throw new UnsupportedOperationException("Unknown uri: " + uri); 71 } 72 } 73 74 /** 75 * Perform a database query by URI. 76 * 77 * <p>Currently supports returning all entries (/entries) and individual entries by ID 78 * (/entries/{ID}). 79 */ 80 @Override 81 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 82 String sortOrder) { 83 SQLiteDatabase db = mDatabaseHelper.getReadableDatabase(); 84 SelectionBuilder builder = new SelectionBuilder(); 85 int uriMatch = sUriMatcher.match(uri); 86 switch (uriMatch) { 87 case ROUTE_ENTRIES_ID: 88 // Return a single entry, by ID. 89 String id = uri.getLastPathSegment(); 90 builder.where(FeedContract.Entry._ID + "=?", id); 91 case ROUTE_ENTRIES: 92 // Return all known entries. 93 builder.table(FeedContract.Entry.TABLE_NAME) 94 .where(selection, selectionArgs); 95 Cursor c = builder.query(db, projection, sortOrder); 96 // Note: Notification URI must be manually set here for loaders to correctly 97 // register ContentObservers. 98 Context ctx = getContext(); 99 assert ctx != null; 100 c.setNotificationUri(ctx.getContentResolver(), uri); 101 return c; 102 default: 103 throw new UnsupportedOperationException("Unknown uri: " + uri); 104 } 105 } 106 107 /** 108 * Insert a new entry into the database. 109 */ 110 @Override 111 public Uri insert(Uri uri, ContentValues values) { 112 final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase(); 113 assert db != null; 114 final int match = sUriMatcher.match(uri); 115 Uri result; 116 switch (match) { 117 case ROUTE_ENTRIES: 118 long id = db.insertOrThrow(FeedContract.Entry.TABLE_NAME, null, values); 119 result = Uri.parse(FeedContract.Entry.CONTENT_URI + "/" + id); 120 break; 121 case ROUTE_ENTRIES_ID: 122 throw new UnsupportedOperationException("Insert not supported on URI: " + uri); 123 default: 124 throw new UnsupportedOperationException("Unknown uri: " + uri); 125 } 126 // Send broadcast to registered ContentObservers, to refresh UI. 127 Context ctx = getContext(); 128 assert ctx != null; 129 ctx.getContentResolver().notifyChange(uri, null, false); 130 return result; 131 } 132 133 /** 134 * Delete an entry by database by URI. 135 */ 136 @Override 137 public int delete(Uri uri, String selection, String[] selectionArgs) { 138 SelectionBuilder builder = new SelectionBuilder(); 139 final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase(); 140 final int match = sUriMatcher.match(uri); 141 int count; 142 switch (match) { 143 case ROUTE_ENTRIES: 144 count = builder.table(FeedContract.Entry.TABLE_NAME) 145 .where(selection, selectionArgs) 146 .delete(db); 147 break; 148 case ROUTE_ENTRIES_ID: 149 String id = uri.getLastPathSegment(); 150 count = builder.table(FeedContract.Entry.TABLE_NAME) 151 .where(FeedContract.Entry._ID + "=?", id) 152 .where(selection, selectionArgs) 153 .delete(db); 154 break; 155 default: 156 throw new UnsupportedOperationException("Unknown uri: " + uri); 157 } 158 // Send broadcast to registered ContentObservers, to refresh UI. 159 Context ctx = getContext(); 160 assert ctx != null; 161 ctx.getContentResolver().notifyChange(uri, null, false); 162 return count; 163 } 164 165 /** 166 * Update an etry in the database by URI. 167 */ 168 @Override 169 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 170 SelectionBuilder builder = new SelectionBuilder(); 171 final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase(); 172 final int match = sUriMatcher.match(uri); 173 int count; 174 switch (match) { 175 case ROUTE_ENTRIES: 176 count = builder.table(FeedContract.Entry.TABLE_NAME) 177 .where(selection, selectionArgs) 178 .update(db, values); 179 break; 180 case ROUTE_ENTRIES_ID: 181 String id = uri.getLastPathSegment(); 182 count = builder.table(FeedContract.Entry.TABLE_NAME) 183 .where(FeedContract.Entry._ID + "=?", id) 184 .where(selection, selectionArgs) 185 .update(db, values); 186 break; 187 default: 188 throw new UnsupportedOperationException("Unknown uri: " + uri); 189 } 190 Context ctx = getContext(); 191 assert ctx != null; 192 ctx.getContentResolver().notifyChange(uri, null, false); 193 return count; 194 } 195 196 /** 197 * SQLite backend for @{link FeedProvider}. 198 * 199 * Provides access to an disk-backed, SQLite datastore which is utilized by FeedProvider. This 200 * database should never be accessed by other parts of the application directly. 201 */ 202 static class FeedDatabase extends SQLiteOpenHelper { 203 /** Schema version. */ 204 public static final int DATABASE_VERSION = 1; 205 /** Filename for SQLite file. */ 206 public static final String DATABASE_NAME = "feed.db"; 207 208 private static final String TYPE_TEXT = " TEXT"; 209 private static final String TYPE_INTEGER = " INTEGER"; 210 private static final String COMMA_SEP = ","; 211 /** SQL statement to create "entry" table. */ 212 private static final String SQL_CREATE_ENTRIES = 213 "CREATE TABLE " + FeedContract.Entry.TABLE_NAME + " (" + 214 FeedContract.Entry._ID + " INTEGER PRIMARY KEY," + 215 FeedContract.Entry.COLUMN_NAME_ENTRY_ID + TYPE_TEXT + COMMA_SEP + 216 FeedContract.Entry.COLUMN_NAME_TITLE + TYPE_TEXT + COMMA_SEP + 217 FeedContract.Entry.COLUMN_NAME_LINK + TYPE_TEXT + COMMA_SEP + 218 FeedContract.Entry.COLUMN_NAME_PUBLISHED + TYPE_INTEGER + ")"; 219 220 /** SQL statement to drop "entry" table. */ 221 private static final String SQL_DELETE_ENTRIES = 222 "DROP TABLE IF EXISTS " + FeedContract.Entry.TABLE_NAME; 223 224 public FeedDatabase(Context context) { 225 super(context, DATABASE_NAME, null, DATABASE_VERSION); 226 } 227 228 @Override 229 public void onCreate(SQLiteDatabase db) { 230 db.execSQL(SQL_CREATE_ENTRIES); 231 } 232 233 @Override 234 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 235 // This database is only a cache for online data, so its upgrade policy is 236 // to simply to discard the data and start over 237 db.execSQL(SQL_DELETE_ENTRIES); 238 onCreate(db); 239 } 240 } 241 242 }