1 /* 2 * Copyright (C) 2010 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.android.gallery3d.gadget; 18 19 import android.content.ContentValues; 20 import android.content.Context; 21 import android.database.Cursor; 22 import android.database.sqlite.SQLiteDatabase; 23 import android.database.sqlite.SQLiteException; 24 import android.database.sqlite.SQLiteOpenHelper; 25 import android.graphics.Bitmap; 26 import android.net.Uri; 27 import android.util.Log; 28 29 import com.android.gallery3d.common.Utils; 30 31 import java.io.ByteArrayOutputStream; 32 import java.util.ArrayList; 33 import java.util.List; 34 35 public class WidgetDatabaseHelper extends SQLiteOpenHelper { 36 private static final String TAG = "PhotoDatabaseHelper"; 37 private static final String DATABASE_NAME = "launcher.db"; 38 39 private static final int DATABASE_VERSION = 4; 40 41 private static final String TABLE_WIDGETS = "widgets"; 42 43 private static final String FIELD_APPWIDGET_ID = "appWidgetId"; 44 private static final String FIELD_IMAGE_URI = "imageUri"; 45 private static final String FIELD_PHOTO_BLOB = "photoBlob"; 46 private static final String FIELD_WIDGET_TYPE = "widgetType"; 47 private static final String FIELD_ALBUM_PATH = "albumPath"; 48 49 public static final int TYPE_SINGLE_PHOTO = 0; 50 public static final int TYPE_SHUFFLE = 1; 51 public static final int TYPE_ALBUM = 2; 52 53 private static final String[] PROJECTION = { 54 FIELD_WIDGET_TYPE, FIELD_IMAGE_URI, FIELD_PHOTO_BLOB, FIELD_ALBUM_PATH, 55 FIELD_APPWIDGET_ID}; 56 private static final int INDEX_WIDGET_TYPE = 0; 57 private static final int INDEX_IMAGE_URI = 1; 58 private static final int INDEX_PHOTO_BLOB = 2; 59 private static final int INDEX_ALBUM_PATH = 3; 60 private static final int INDEX_APPWIDGET_ID = 4; 61 private static final String WHERE_APPWIDGET_ID = FIELD_APPWIDGET_ID + " = ?"; 62 private static final String WHERE_WIDGET_TYPE = FIELD_WIDGET_TYPE + " = ?"; 63 64 public static class Entry { 65 public int widgetId; 66 public int type; 67 public String imageUri; 68 public byte imageData[]; 69 public String albumPath; 70 Entry()71 private Entry() {} 72 Entry(int id, Cursor cursor)73 private Entry(int id, Cursor cursor) { 74 widgetId = id; 75 type = cursor.getInt(INDEX_WIDGET_TYPE); 76 if (type == TYPE_SINGLE_PHOTO) { 77 imageUri = cursor.getString(INDEX_IMAGE_URI); 78 imageData = cursor.getBlob(INDEX_PHOTO_BLOB); 79 } else if (type == TYPE_ALBUM) { 80 albumPath = cursor.getString(INDEX_ALBUM_PATH); 81 } 82 } 83 Entry(Cursor cursor)84 private Entry(Cursor cursor) { 85 this(cursor.getInt(INDEX_APPWIDGET_ID), cursor); 86 } 87 } 88 WidgetDatabaseHelper(Context context)89 public WidgetDatabaseHelper(Context context) { 90 super(context, DATABASE_NAME, null, DATABASE_VERSION); 91 } 92 93 @Override onCreate(SQLiteDatabase db)94 public void onCreate(SQLiteDatabase db) { 95 db.execSQL("CREATE TABLE " + TABLE_WIDGETS + " (" 96 + FIELD_APPWIDGET_ID + " INTEGER PRIMARY KEY, " 97 + FIELD_WIDGET_TYPE + " INTEGER DEFAULT 0, " 98 + FIELD_IMAGE_URI + " TEXT, " 99 + FIELD_ALBUM_PATH + " TEXT, " 100 + FIELD_PHOTO_BLOB + " BLOB)"); 101 } 102 saveData(SQLiteDatabase db, int oldVersion, ArrayList<Entry> data)103 private void saveData(SQLiteDatabase db, int oldVersion, ArrayList<Entry> data) { 104 if (oldVersion <= 2) { 105 Cursor cursor = db.query("photos", 106 new String[] {FIELD_APPWIDGET_ID, FIELD_PHOTO_BLOB}, 107 null, null, null, null, null); 108 if (cursor == null) return; 109 try { 110 while (cursor.moveToNext()) { 111 Entry entry = new Entry(); 112 entry.type = TYPE_SINGLE_PHOTO; 113 entry.widgetId = cursor.getInt(0); 114 entry.imageData = cursor.getBlob(1); 115 data.add(entry); 116 } 117 } finally { 118 cursor.close(); 119 } 120 } else if (oldVersion == 3) { 121 Cursor cursor = db.query("photos", 122 new String[] {FIELD_APPWIDGET_ID, FIELD_PHOTO_BLOB, FIELD_IMAGE_URI}, 123 null, null, null, null, null); 124 if (cursor == null) return; 125 try { 126 while (cursor.moveToNext()) { 127 Entry entry = new Entry(); 128 entry.type = TYPE_SINGLE_PHOTO; 129 entry.widgetId = cursor.getInt(0); 130 entry.imageData = cursor.getBlob(1); 131 entry.imageUri = cursor.getString(2); 132 data.add(entry); 133 } 134 } finally { 135 cursor.close(); 136 } 137 } 138 } 139 restoreData(SQLiteDatabase db, ArrayList<Entry> data)140 private void restoreData(SQLiteDatabase db, ArrayList<Entry> data) { 141 db.beginTransaction(); 142 try { 143 for (Entry entry : data) { 144 ContentValues values = new ContentValues(); 145 values.put(FIELD_APPWIDGET_ID, entry.widgetId); 146 values.put(FIELD_WIDGET_TYPE, entry.type); 147 values.put(FIELD_IMAGE_URI, entry.imageUri); 148 values.put(FIELD_PHOTO_BLOB, entry.imageData); 149 values.put(FIELD_ALBUM_PATH, entry.albumPath); 150 db.insert(TABLE_WIDGETS, null, values); 151 } 152 db.setTransactionSuccessful(); 153 } finally { 154 db.endTransaction(); 155 } 156 } 157 158 @Override onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)159 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 160 int version = oldVersion; 161 162 if (version != DATABASE_VERSION) { 163 ArrayList<Entry> data = new ArrayList<Entry>(); 164 saveData(db, oldVersion, data); 165 166 Log.w(TAG, "destroying all old data."); 167 // Table "photos" is renamed to "widget" in version 4 168 db.execSQL("DROP TABLE IF EXISTS photos"); 169 db.execSQL("DROP TABLE IF EXISTS " + TABLE_WIDGETS); 170 onCreate(db); 171 172 restoreData(db, data); 173 } 174 } 175 176 /** 177 * Store the given bitmap in this database for the given appWidgetId. 178 */ setPhoto(int appWidgetId, Uri imageUri, Bitmap bitmap)179 public boolean setPhoto(int appWidgetId, Uri imageUri, Bitmap bitmap) { 180 try { 181 // Try go guesstimate how much space the icon will take when 182 // serialized to avoid unnecessary allocations/copies during 183 // the write. 184 int size = bitmap.getWidth() * bitmap.getHeight() * 4; 185 ByteArrayOutputStream out = new ByteArrayOutputStream(size); 186 bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); 187 out.close(); 188 189 ContentValues values = new ContentValues(); 190 values.put(FIELD_APPWIDGET_ID, appWidgetId); 191 values.put(FIELD_WIDGET_TYPE, TYPE_SINGLE_PHOTO); 192 values.put(FIELD_IMAGE_URI, imageUri.toString()); 193 values.put(FIELD_PHOTO_BLOB, out.toByteArray()); 194 195 SQLiteDatabase db = getWritableDatabase(); 196 db.replaceOrThrow(TABLE_WIDGETS, null, values); 197 return true; 198 } catch (Throwable e) { 199 Log.e(TAG, "set widget photo fail", e); 200 return false; 201 } 202 } 203 setWidget(int id, int type, String albumPath)204 public boolean setWidget(int id, int type, String albumPath) { 205 try { 206 ContentValues values = new ContentValues(); 207 values.put(FIELD_APPWIDGET_ID, id); 208 values.put(FIELD_WIDGET_TYPE, type); 209 values.put(FIELD_ALBUM_PATH, Utils.ensureNotNull(albumPath)); 210 getWritableDatabase().replaceOrThrow(TABLE_WIDGETS, null, values); 211 return true; 212 } catch (Throwable e) { 213 Log.e(TAG, "set widget fail", e); 214 return false; 215 } 216 } 217 getEntry(int appWidgetId)218 public Entry getEntry(int appWidgetId) { 219 Cursor cursor = null; 220 try { 221 SQLiteDatabase db = getReadableDatabase(); 222 cursor = db.query(TABLE_WIDGETS, PROJECTION, 223 WHERE_APPWIDGET_ID, new String[] {String.valueOf(appWidgetId)}, 224 null, null, null); 225 if (cursor == null || !cursor.moveToNext()) { 226 Log.e(TAG, "query fail: empty cursor: " + cursor); 227 return null; 228 } 229 return new Entry(appWidgetId, cursor); 230 } catch (Throwable e) { 231 Log.e(TAG, "Could not load photo from database", e); 232 return null; 233 } finally { 234 Utils.closeSilently(cursor); 235 } 236 } 237 getEntries(int type)238 public List<Entry> getEntries(int type) { 239 Cursor cursor = null; 240 try { 241 SQLiteDatabase db = getReadableDatabase(); 242 cursor = db.query(TABLE_WIDGETS, PROJECTION, 243 WHERE_WIDGET_TYPE, new String[] {String.valueOf(type)}, 244 null, null, null); 245 if (cursor == null) { 246 Log.e(TAG, "query fail: null cursor: " + cursor); 247 return null; 248 } 249 ArrayList<Entry> result = new ArrayList<Entry>(cursor.getCount()); 250 while (cursor.moveToNext()) { 251 result.add(new Entry(cursor)); 252 } 253 return result; 254 } catch (Throwable e) { 255 Log.e(TAG, "Could not load widget from database", e); 256 return null; 257 } finally { 258 Utils.closeSilently(cursor); 259 } 260 } 261 262 /** 263 * Updates the entry in the widget database. 264 */ updateEntry(Entry entry)265 public void updateEntry(Entry entry) { 266 deleteEntry(entry.widgetId); 267 try { 268 ContentValues values = new ContentValues(); 269 values.put(FIELD_APPWIDGET_ID, entry.widgetId); 270 values.put(FIELD_WIDGET_TYPE, entry.type); 271 values.put(FIELD_ALBUM_PATH, entry.albumPath); 272 values.put(FIELD_IMAGE_URI, entry.imageUri); 273 values.put(FIELD_PHOTO_BLOB, entry.imageData); 274 getWritableDatabase().insert(TABLE_WIDGETS, null, values); 275 } catch (Throwable e) { 276 Log.e(TAG, "set widget fail", e); 277 } 278 } 279 280 /** 281 * Remove any bitmap associated with the given appWidgetId. 282 */ deleteEntry(int appWidgetId)283 public void deleteEntry(int appWidgetId) { 284 try { 285 SQLiteDatabase db = getWritableDatabase(); 286 db.delete(TABLE_WIDGETS, WHERE_APPWIDGET_ID, 287 new String[] {String.valueOf(appWidgetId)}); 288 } catch (SQLiteException e) { 289 Log.e(TAG, "Could not delete photo from database", e); 290 } 291 } 292 } 293