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