1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.codelab.rssexample; 18 19 import android.content.ContentProvider; 20 import android.content.ContentProviderDatabaseHelper; 21 import android.content.UriMatcher; 22 import android.content.Context; 23 import android.database.Cursor; 24 import android.database.SQLException; 25 import android.database.sqlite.SQLiteDatabase; 26 import android.database.sqlite.SQLiteQueryBuilder; 27 import android.net.Uri; 28 import android.content.ContentValues; 29 import android.text.TextUtils; 30 31 import java.util.logging.Logger; 32 33 // Content Provider for RSS feed information. Each row describes a single 34 // RSS feed. See the public static constants at the end of this class 35 // to learn what each record contains. 36 public class RssContentProvider extends ContentProvider { 37 private Logger mLogger = Logger.getLogger("com.example.codelab.rssexample"); 38 private SQLiteDatabase mDb; 39 private DatabaseHelper mDbHelper = new DatabaseHelper(); 40 private static final String DATABASE_NAME = "rssitems.db"; 41 private static final String DATABASE_TABLE_NAME = "rssItems"; 42 private static final int DB_VERSION = 1; 43 private static final int ALL_MESSAGES = 1; 44 private static final int SPECIFIC_MESSAGE = 2; 45 46 // Set up our URL matchers to help us determine what an 47 // incoming URI parameter is. 48 private static final UriMatcher URI_MATCHER; 49 static{ 50 URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); 51 URI_MATCHER.addURI("my_rss_item", "rssitem", ALL_MESSAGES); 52 URI_MATCHER.addURI("my_rss_item", "rssitem/#", SPECIFIC_MESSAGE); 53 } 54 55 // Here's the public URI used to query for RSS items. 56 public static final Uri CONTENT_URI = Uri.parse( "content://my_rss_item/rssitem"); 57 58 // Here are our column name constants, used to query for field values. 59 public static final String ID = "_id"; 60 public static final String URL = "url"; 61 public static final String TITLE = "title"; 62 public static final String HAS_BEEN_READ = "hasbeenread"; 63 public static final String CONTENT = "rawcontent"; 64 public static final String LAST_UPDATED = "lastupdated"; 65 public static final String DEFAULT_SORT_ORDER = TITLE + " DESC"; 66 67 // Database creation/version management helper. 68 // Create it statically because we don't need to have customized instances. 69 private static class DatabaseHelper extends ContentProviderDatabaseHelper{ 70 71 @Override 72 public void onCreate(SQLiteDatabase db){ 73 try{ 74 String sql = "CREATE TABLE " + DATABASE_TABLE_NAME + "(" + 75 ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + 76 URL + " TEXT," + 77 TITLE + " TEXT," + 78 HAS_BEEN_READ + " BOOLEAN DEFAULT 0," + 79 CONTENT + " TEXT," + 80 LAST_UPDATED + " INTEGER DEFAULT 0);"; 81 Logger.getLogger("com.example.codelab.rssexample").info("DatabaseHelper.onCreate(): SQL statement: " + sql); 82 db.execSQL(sql); 83 Logger.getLogger("com.example.codelab.rssexample").info("DatabaseHelper.onCreate(): Created a database"); 84 } catch (SQLException e) { 85 Logger.getLogger("com.example.codelab.rssexample").warning("DatabaseHelper.onCreate(): Couldn't create a database!"); 86 } 87 } 88 89 @Override 90 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){ 91 // Don't have any upgrades yet, so if this gets called for some reason we'll 92 // just drop the existing table, and recreate the database with the 93 // standard method. 94 db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE_NAME + ";"); 95 96 } 97 } 98 99 @Override 100 public boolean onCreate() { 101 // First we need to open the database. If this is our first time, 102 // the attempt to retrieve a database will throw 103 // FileNotFoundException, and we will then create the database. 104 final Context con = getContext(); 105 try{ 106 mDb = mDbHelper.openDatabase(getContext(), DATABASE_NAME, null, DB_VERSION); 107 mLogger.info("RssContentProvider.onCreate(): Opened a database"); 108 } catch (Exception ex) { 109 return false; 110 } 111 if(mDb == null){ 112 return false; 113 } else { 114 return true; 115 } 116 } 117 118 // Convert the URI into a custom MIME type. 119 // Our UriMatcher will parse the URI to decide whether the 120 // URI is for a single item or a list. 121 @Override 122 public String getType(Uri uri) { 123 switch (URI_MATCHER.match(uri)){ 124 case ALL_MESSAGES: 125 return "vnd.android.cursor.dir/rssitem"; // List of items. 126 case SPECIFIC_MESSAGE: 127 return "vnd.android.cursor.item/rssitem"; // Specific item. 128 default: 129 return null; 130 } 131 } 132 133 @Override 134 public Cursor query(Uri uri, String[] projection, String selection, 135 String[] selectionArgs, String groupBy, String having, String sortOrder) { 136 // We won't bother checking the validity of params here, but you should! 137 138 // SQLiteQueryBuilder is the helper class that creates the 139 // proper SQL syntax for us. 140 SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder(); 141 142 // Set the table we're querying. 143 qBuilder.setTables(DATABASE_TABLE_NAME); 144 145 // If the query ends in a specific record number, we're 146 // being asked for a specific record, so set the 147 // WHERE clause in our query. 148 if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){ 149 qBuilder.appendWhere("_id=" + uri.getPathLeafId()); 150 } 151 152 // Set sort order. If none specified, use default. 153 if(TextUtils.isEmpty(sortOrder)){ 154 sortOrder = DEFAULT_SORT_ORDER; 155 } 156 157 // Make the query. 158 Cursor c = qBuilder.query(mDb, 159 projection, 160 selection, 161 selectionArgs, 162 groupBy, 163 having, 164 sortOrder); 165 c.setNotificationUri(getContext().getContentResolver(), uri); 166 return c; 167 } 168 169 @Override 170 public int update(Uri uri, ContentValues values, String whereClause) { 171 // NOTE Argument checking code omitted. Check your parameters! 172 int updateCount = mDb.update(DATABASE_TABLE_NAME, values, whereClause); 173 174 // Notify any listeners and return the updated row count. 175 getContext().getContentResolver().notifyUpdate(uri, null); 176 return updateCount; 177 } 178 179 @Override 180 public Uri insert(Uri requestUri, ContentValues initialValues) { 181 // NOTE Argument checking code omitted. Check your parameters! Check that 182 // your row addition request succeeded! 183 184 long rowId = -1; 185 rowId = mDb.insert(DATABASE_TABLE_NAME, "rawcontent", initialValues); 186 Uri newUri = CONTENT_URI.addId(rowId); 187 188 // Notify any listeners and return the URI of the new row. 189 getContext().getContentResolver().notifyInsert(CONTENT_URI, null); 190 return newUri; 191 } 192 193 @Override 194 public int delete(Uri uri, String where) { 195 // NOTE Argument checking code omitted. Check your parameters! 196 int rowCount = mDb.delete(DATABASE_TABLE_NAME, ID + " = " + uri.getPathLeafId()); 197 198 // Notify any listeners and return the deleted row count. 199 getContext().getContentResolver().notifyDelete(uri, null); 200 return rowCount; 201 } 202 } 203