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