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.android.notepad; 18 19 import com.example.android.notepad.NotePad.NoteColumns; 20 21 import android.content.ContentProvider; 22 import android.content.ContentUris; 23 import android.content.ContentValues; 24 import android.content.Context; 25 import android.content.UriMatcher; 26 import android.content.res.Resources; 27 import android.database.Cursor; 28 import android.database.SQLException; 29 import android.database.sqlite.SQLiteDatabase; 30 import android.database.sqlite.SQLiteOpenHelper; 31 import android.database.sqlite.SQLiteQueryBuilder; 32 import android.net.Uri; 33 import android.provider.LiveFolders; 34 import android.text.TextUtils; 35 import android.util.Log; 36 37 import java.util.HashMap; 38 39 /** 40 * Provides access to a database of notes. Each note has a title, the note 41 * itself, a creation date and a modified data. 42 */ 43 public class NotePadProvider extends ContentProvider { 44 45 private static final String TAG = "NotePadProvider"; 46 47 private static final String DATABASE_NAME = "notepad.db"; 48 private static final int DATABASE_VERSION = 2; 49 private static final String NOTES_TABLE_NAME = "notes"; 50 51 private static HashMap<String, String> sNotesProjectionMap; 52 private static HashMap<String, String> sLiveFolderProjectionMap; 53 54 private static final int NOTES = 1; 55 private static final int NOTE_ID = 2; 56 private static final int LIVE_FOLDER_NOTES = 3; 57 58 private static final UriMatcher sUriMatcher; 59 60 /** 61 * This class helps open, create, and upgrade the database file. 62 */ 63 private static class DatabaseHelper extends SQLiteOpenHelper { 64 DatabaseHelper(Context context)65 DatabaseHelper(Context context) { 66 super(context, DATABASE_NAME, null, DATABASE_VERSION); 67 } 68 69 @Override onCreate(SQLiteDatabase db)70 public void onCreate(SQLiteDatabase db) { 71 db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME + " (" 72 + NoteColumns._ID + " INTEGER PRIMARY KEY," 73 + NoteColumns.TITLE + " TEXT," 74 + NoteColumns.NOTE + " TEXT," 75 + NoteColumns.CREATED_DATE + " INTEGER," 76 + NoteColumns.MODIFIED_DATE + " INTEGER" 77 + ");"); 78 } 79 80 @Override onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)81 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 82 Log.w(TAG, "Upgrading database from version " + oldVersion + " to " 83 + newVersion + ", which will destroy all old data"); 84 db.execSQL("DROP TABLE IF EXISTS notes"); 85 onCreate(db); 86 } 87 } 88 89 private DatabaseHelper mOpenHelper; 90 91 @Override onCreate()92 public boolean onCreate() { 93 mOpenHelper = new DatabaseHelper(getContext()); 94 return true; 95 } 96 97 @Override query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)98 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 99 String sortOrder) { 100 SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 101 qb.setTables(NOTES_TABLE_NAME); 102 103 switch (sUriMatcher.match(uri)) { 104 case NOTES: 105 qb.setProjectionMap(sNotesProjectionMap); 106 break; 107 108 case NOTE_ID: 109 qb.setProjectionMap(sNotesProjectionMap); 110 qb.appendWhere(NoteColumns._ID + "=" + uri.getPathSegments().get(1)); 111 break; 112 113 case LIVE_FOLDER_NOTES: 114 qb.setProjectionMap(sLiveFolderProjectionMap); 115 break; 116 117 default: 118 throw new IllegalArgumentException("Unknown URI " + uri); 119 } 120 121 // If no sort order is specified use the default 122 String orderBy; 123 if (TextUtils.isEmpty(sortOrder)) { 124 orderBy = NoteColumns.DEFAULT_SORT_ORDER; 125 } else { 126 orderBy = sortOrder; 127 } 128 129 // Get the database and run the query 130 SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 131 Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy); 132 133 // Tell the cursor what uri to watch, so it knows when its source data changes 134 c.setNotificationUri(getContext().getContentResolver(), uri); 135 return c; 136 } 137 138 @Override getType(Uri uri)139 public String getType(Uri uri) { 140 switch (sUriMatcher.match(uri)) { 141 case NOTES: 142 case LIVE_FOLDER_NOTES: 143 return NoteColumns.CONTENT_TYPE; 144 145 case NOTE_ID: 146 return NoteColumns.CONTENT_ITEM_TYPE; 147 148 default: 149 throw new IllegalArgumentException("Unknown URI " + uri); 150 } 151 } 152 153 @Override insert(Uri uri, ContentValues initialValues)154 public Uri insert(Uri uri, ContentValues initialValues) { 155 // Validate the requested uri 156 if (sUriMatcher.match(uri) != NOTES) { 157 throw new IllegalArgumentException("Unknown URI " + uri); 158 } 159 160 ContentValues values; 161 if (initialValues != null) { 162 values = new ContentValues(initialValues); 163 } else { 164 values = new ContentValues(); 165 } 166 167 Long now = Long.valueOf(System.currentTimeMillis()); 168 169 // Make sure that the fields are all set 170 if (values.containsKey(NoteColumns.CREATED_DATE) == false) { 171 values.put(NoteColumns.CREATED_DATE, now); 172 } 173 174 if (values.containsKey(NoteColumns.MODIFIED_DATE) == false) { 175 values.put(NoteColumns.MODIFIED_DATE, now); 176 } 177 178 if (values.containsKey(NoteColumns.TITLE) == false) { 179 Resources r = Resources.getSystem(); 180 values.put(NoteColumns.TITLE, r.getString(android.R.string.untitled)); 181 } 182 183 if (values.containsKey(NoteColumns.NOTE) == false) { 184 values.put(NoteColumns.NOTE, ""); 185 } 186 187 SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 188 long rowId = db.insert(NOTES_TABLE_NAME, NoteColumns.NOTE, values); 189 if (rowId > 0) { 190 Uri noteUri = ContentUris.withAppendedId(NoteColumns.CONTENT_URI, rowId); 191 getContext().getContentResolver().notifyChange(noteUri, null); 192 return noteUri; 193 } 194 195 throw new SQLException("Failed to insert row into " + uri); 196 } 197 198 @Override delete(Uri uri, String where, String[] whereArgs)199 public int delete(Uri uri, String where, String[] whereArgs) { 200 SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 201 int count; 202 switch (sUriMatcher.match(uri)) { 203 case NOTES: 204 count = db.delete(NOTES_TABLE_NAME, where, whereArgs); 205 break; 206 207 case NOTE_ID: 208 String noteId = uri.getPathSegments().get(1); 209 count = db.delete(NOTES_TABLE_NAME, NoteColumns._ID + "=" + noteId 210 + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs); 211 break; 212 213 default: 214 throw new IllegalArgumentException("Unknown URI " + uri); 215 } 216 217 getContext().getContentResolver().notifyChange(uri, null); 218 return count; 219 } 220 221 @Override update(Uri uri, ContentValues values, String where, String[] whereArgs)222 public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { 223 SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 224 int count; 225 switch (sUriMatcher.match(uri)) { 226 case NOTES: 227 count = db.update(NOTES_TABLE_NAME, values, where, whereArgs); 228 break; 229 230 case NOTE_ID: 231 String noteId = uri.getPathSegments().get(1); 232 count = db.update(NOTES_TABLE_NAME, values, NoteColumns._ID + "=" + noteId 233 + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs); 234 break; 235 236 default: 237 throw new IllegalArgumentException("Unknown URI " + uri); 238 } 239 240 getContext().getContentResolver().notifyChange(uri, null); 241 return count; 242 } 243 244 static { 245 sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES)246 sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES); sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID)247 sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID); sUriMatcher.addURI(NotePad.AUTHORITY, "live_folders/notes", LIVE_FOLDER_NOTES)248 sUriMatcher.addURI(NotePad.AUTHORITY, "live_folders/notes", LIVE_FOLDER_NOTES); 249 250 sNotesProjectionMap = new HashMap<String, String>(); sNotesProjectionMap.put(NoteColumns._ID, NoteColumns._ID)251 sNotesProjectionMap.put(NoteColumns._ID, NoteColumns._ID); sNotesProjectionMap.put(NoteColumns.TITLE, NoteColumns.TITLE)252 sNotesProjectionMap.put(NoteColumns.TITLE, NoteColumns.TITLE); sNotesProjectionMap.put(NoteColumns.NOTE, NoteColumns.NOTE)253 sNotesProjectionMap.put(NoteColumns.NOTE, NoteColumns.NOTE); sNotesProjectionMap.put(NoteColumns.CREATED_DATE, NoteColumns.CREATED_DATE)254 sNotesProjectionMap.put(NoteColumns.CREATED_DATE, NoteColumns.CREATED_DATE); sNotesProjectionMap.put(NoteColumns.MODIFIED_DATE, NoteColumns.MODIFIED_DATE)255 sNotesProjectionMap.put(NoteColumns.MODIFIED_DATE, NoteColumns.MODIFIED_DATE); 256 257 // Support for Live Folders. 258 sLiveFolderProjectionMap = new HashMap<String, String>(); sLiveFolderProjectionMap.put(LiveFolders._ID, NoteColumns._ID + " AS " + LiveFolders._ID)259 sLiveFolderProjectionMap.put(LiveFolders._ID, NoteColumns._ID + " AS " + 260 LiveFolders._ID); sLiveFolderProjectionMap.put(LiveFolders.NAME, NoteColumns.TITLE + " AS " + LiveFolders.NAME)261 sLiveFolderProjectionMap.put(LiveFolders.NAME, NoteColumns.TITLE + " AS " + 262 LiveFolders.NAME); 263 // Add more columns here for more robust Live Folders. 264 } 265 } 266