1 /* 2 * Copyright (C) 2009 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.cooliris.media; 18 19 import android.appwidget.AppWidgetManager; 20 import android.appwidget.AppWidgetProvider; 21 import android.content.ContentValues; 22 import android.content.Context; 23 import android.database.Cursor; 24 import android.database.sqlite.SQLiteDatabase; 25 import android.database.sqlite.SQLiteException; 26 import android.database.sqlite.SQLiteOpenHelper; 27 import android.graphics.Bitmap; 28 import android.graphics.BitmapFactory; 29 import android.util.Log; 30 import android.widget.RemoteViews; 31 32 import java.io.ByteArrayOutputStream; 33 import java.io.IOException; 34 35 import com.cooliris.app.Res; 36 37 /** 38 * Simple widget to show a user-selected picture. 39 */ 40 public class PhotoAppWidgetProvider extends AppWidgetProvider { 41 private static final String TAG = "PhotoAppWidgetProvider"; 42 private static final boolean LOGD = true; 43 44 @Override onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)45 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 46 // Update each requested appWidgetId with its unique photo 47 PhotoDatabaseHelper helper = new PhotoDatabaseHelper(context); 48 for (int appWidgetId : appWidgetIds) { 49 int[] specificAppWidget = new int[] { appWidgetId }; 50 RemoteViews views = buildUpdate(context, appWidgetId, helper); 51 if (LOGD) { 52 Log.d(TAG, "sending out views=" + views + " for id=" + appWidgetId); 53 } 54 appWidgetManager.updateAppWidget(specificAppWidget, views); 55 } 56 helper.close(); 57 } 58 59 @Override onDeleted(Context context, int[] appWidgetIds)60 public void onDeleted(Context context, int[] appWidgetIds) { 61 // Clean deleted photos out of our database 62 PhotoDatabaseHelper helper = new PhotoDatabaseHelper(context); 63 for (int appWidgetId : appWidgetIds) { 64 helper.deletePhoto(appWidgetId); 65 } 66 helper.close(); 67 } 68 69 /** 70 * Load photo for given widget and build {@link RemoteViews} for it. 71 */ buildUpdate(Context context, int appWidgetId, PhotoDatabaseHelper helper)72 static RemoteViews buildUpdate(Context context, int appWidgetId, PhotoDatabaseHelper helper) { 73 RemoteViews views = null; 74 Bitmap bitmap = helper.getPhoto(appWidgetId); 75 if (bitmap != null) { 76 views = new RemoteViews(context.getPackageName(), Res.layout.photo_frame); 77 views.setImageViewBitmap(Res.id.photo, bitmap); 78 } 79 return views; 80 } 81 82 static class PhotoDatabaseHelper extends SQLiteOpenHelper { 83 private static final String DATABASE_NAME = "launcher.db"; 84 85 private static final int DATABASE_VERSION = 2; 86 87 static final String TABLE_PHOTOS = "photos"; 88 static final String FIELD_APPWIDGET_ID = "appWidgetId"; 89 static final String FIELD_PHOTO_BLOB = "photoBlob"; 90 PhotoDatabaseHelper(Context context)91 PhotoDatabaseHelper(Context context) { 92 super(context, DATABASE_NAME, null, DATABASE_VERSION); 93 } 94 95 @Override onCreate(SQLiteDatabase db)96 public void onCreate(SQLiteDatabase db) { 97 db.execSQL("CREATE TABLE " + TABLE_PHOTOS + " (" + FIELD_APPWIDGET_ID + " INTEGER PRIMARY KEY," + FIELD_PHOTO_BLOB 98 + " BLOB" + ");"); 99 } 100 101 @Override onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)102 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 103 int version = oldVersion; 104 105 if (version != DATABASE_VERSION) { 106 Log.w(TAG, "Destroying all old data."); 107 db.execSQL("DROP TABLE IF EXISTS " + TABLE_PHOTOS); 108 onCreate(db); 109 } 110 } 111 112 /** 113 * Store the given bitmap in this database for the given appWidgetId. 114 */ setPhoto(int appWidgetId, Bitmap bitmap)115 public boolean setPhoto(int appWidgetId, Bitmap bitmap) { 116 boolean success = false; 117 try { 118 // Try go guesstimate how much space the icon will take when 119 // serialized to avoid unnecessary allocations/copies during 120 // the write. 121 int size = bitmap.getWidth() * bitmap.getHeight() * 4; 122 ByteArrayOutputStream out = new ByteArrayOutputStream(size); 123 bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); 124 out.flush(); 125 out.close(); 126 127 ContentValues values = new ContentValues(); 128 values.put(PhotoDatabaseHelper.FIELD_APPWIDGET_ID, appWidgetId); 129 values.put(PhotoDatabaseHelper.FIELD_PHOTO_BLOB, out.toByteArray()); 130 131 SQLiteDatabase db = getWritableDatabase(); 132 db.insertOrThrow(PhotoDatabaseHelper.TABLE_PHOTOS, null, values); 133 134 success = true; 135 } catch (SQLiteException e) { 136 Log.e(TAG, "Could not open database", e); 137 } catch (IOException e) { 138 Log.e(TAG, "Could not serialize photo", e); 139 } 140 if (LOGD) { 141 Log.d(TAG, "setPhoto success=" + success); 142 } 143 return success; 144 } 145 146 static final String[] PHOTOS_PROJECTION = { FIELD_PHOTO_BLOB, }; 147 148 static final int INDEX_PHOTO_BLOB = 0; 149 150 /** 151 * Inflate and return a bitmap for the given appWidgetId. 152 */ getPhoto(int appWidgetId)153 public Bitmap getPhoto(int appWidgetId) { 154 Cursor c = null; 155 Bitmap bitmap = null; 156 try { 157 SQLiteDatabase db = getReadableDatabase(); 158 String selection = String.format("%s=%d", FIELD_APPWIDGET_ID, appWidgetId); 159 c = db.query(TABLE_PHOTOS, PHOTOS_PROJECTION, selection, null, null, null, null, null); 160 161 if (c != null && LOGD) { 162 Log.d(TAG, "getPhoto query count=" + c.getCount()); 163 } 164 165 if (c != null && c.moveToFirst()) { 166 byte[] data = c.getBlob(INDEX_PHOTO_BLOB); 167 if (data != null) { 168 bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); 169 } 170 } 171 } catch (SQLiteException e) { 172 Log.e(TAG, "Could not load photo from database", e); 173 } finally { 174 if (c != null) { 175 c.close(); 176 } 177 } 178 return bitmap; 179 } 180 181 /** 182 * Remove any bitmap associated with the given appWidgetId. 183 */ deletePhoto(int appWidgetId)184 public void deletePhoto(int appWidgetId) { 185 try { 186 SQLiteDatabase db = getWritableDatabase(); 187 String whereClause = String.format("%s=%d", FIELD_APPWIDGET_ID, appWidgetId); 188 db.delete(TABLE_PHOTOS, whereClause, null); 189 } catch (SQLiteException e) { 190 Log.e(TAG, "Could not delete photo from database", e); 191 } 192 } 193 } 194 195 } 196