PhotoAppWidgetProvider.java revision 666ea1b28a76aeba74744148b15099254d918671
1666ea1b28a76aeba74744148b15099254d918671Owen Lin/*
2666ea1b28a76aeba74744148b15099254d918671Owen Lin * Copyright (C) 2009 The Android Open Source Project
3666ea1b28a76aeba74744148b15099254d918671Owen Lin *
4666ea1b28a76aeba74744148b15099254d918671Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5666ea1b28a76aeba74744148b15099254d918671Owen Lin * you may not use this file except in compliance with the License.
6666ea1b28a76aeba74744148b15099254d918671Owen Lin * You may obtain a copy of the License at
7666ea1b28a76aeba74744148b15099254d918671Owen Lin *
8666ea1b28a76aeba74744148b15099254d918671Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9666ea1b28a76aeba74744148b15099254d918671Owen Lin *
10666ea1b28a76aeba74744148b15099254d918671Owen Lin * Unless required by applicable law or agreed to in writing, software
11666ea1b28a76aeba74744148b15099254d918671Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12666ea1b28a76aeba74744148b15099254d918671Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13666ea1b28a76aeba74744148b15099254d918671Owen Lin * See the License for the specific language governing permissions and
14666ea1b28a76aeba74744148b15099254d918671Owen Lin * limitations under the License.
15666ea1b28a76aeba74744148b15099254d918671Owen Lin */
16666ea1b28a76aeba74744148b15099254d918671Owen Lin
17666ea1b28a76aeba74744148b15099254d918671Owen Linpackage com.android.camera;
18666ea1b28a76aeba74744148b15099254d918671Owen Lin
19666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.appwidget.AppWidgetManager;
20666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.appwidget.AppWidgetProvider;
21666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.ContentValues;
22666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.Context;
23666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.database.Cursor;
24666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.database.sqlite.SQLiteDatabase;
25666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.database.sqlite.SQLiteException;
26666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.database.sqlite.SQLiteOpenHelper;
27666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.graphics.Bitmap;
28666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.graphics.BitmapFactory;
29666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.util.Log;
30666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.widget.RemoteViews;
31666ea1b28a76aeba74744148b15099254d918671Owen Lin
32666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.ByteArrayOutputStream;
33666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.io.IOException;
34666ea1b28a76aeba74744148b15099254d918671Owen Lin
35666ea1b28a76aeba74744148b15099254d918671Owen Lin/**
36666ea1b28a76aeba74744148b15099254d918671Owen Lin * Simple widget to show a user-selected picture.
37666ea1b28a76aeba74744148b15099254d918671Owen Lin */
38666ea1b28a76aeba74744148b15099254d918671Owen Linpublic class PhotoAppWidgetProvider extends AppWidgetProvider {
39666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final String TAG = "PhotoAppWidgetProvider";
40666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final boolean LOGD = true;
41666ea1b28a76aeba74744148b15099254d918671Owen Lin
42666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
43666ea1b28a76aeba74744148b15099254d918671Owen Lin    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
44666ea1b28a76aeba74744148b15099254d918671Owen Lin                         int[] appWidgetIds) {
45666ea1b28a76aeba74744148b15099254d918671Owen Lin        // Update each requested appWidgetId with its unique photo
46666ea1b28a76aeba74744148b15099254d918671Owen Lin        PhotoDatabaseHelper helper = new PhotoDatabaseHelper(context);
47666ea1b28a76aeba74744148b15099254d918671Owen Lin        for (int appWidgetId : appWidgetIds) {
48666ea1b28a76aeba74744148b15099254d918671Owen Lin            int[] specificAppWidget = new int[] { appWidgetId };
49666ea1b28a76aeba74744148b15099254d918671Owen Lin            RemoteViews views = buildUpdate(context, appWidgetId, helper);
50666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (LOGD) {
51666ea1b28a76aeba74744148b15099254d918671Owen Lin                Log.d(TAG, "sending out views=" + views
52666ea1b28a76aeba74744148b15099254d918671Owen Lin                        + " for id=" + appWidgetId);
53666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
54666ea1b28a76aeba74744148b15099254d918671Owen Lin            appWidgetManager.updateAppWidget(specificAppWidget, views);
55666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
56666ea1b28a76aeba74744148b15099254d918671Owen Lin        helper.close();
57666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
58666ea1b28a76aeba74744148b15099254d918671Owen Lin
59666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
60666ea1b28a76aeba74744148b15099254d918671Owen Lin    public void onDeleted(Context context, int[] appWidgetIds) {
61666ea1b28a76aeba74744148b15099254d918671Owen Lin        // Clean deleted photos out of our database
62666ea1b28a76aeba74744148b15099254d918671Owen Lin        PhotoDatabaseHelper helper = new PhotoDatabaseHelper(context);
63666ea1b28a76aeba74744148b15099254d918671Owen Lin        for (int appWidgetId : appWidgetIds) {
64666ea1b28a76aeba74744148b15099254d918671Owen Lin            helper.deletePhoto(appWidgetId);
65666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
66666ea1b28a76aeba74744148b15099254d918671Owen Lin        helper.close();
67666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
68666ea1b28a76aeba74744148b15099254d918671Owen Lin
69666ea1b28a76aeba74744148b15099254d918671Owen Lin    /**
70666ea1b28a76aeba74744148b15099254d918671Owen Lin     * Load photo for given widget and build {@link RemoteViews} for it.
71666ea1b28a76aeba74744148b15099254d918671Owen Lin     */
72666ea1b28a76aeba74744148b15099254d918671Owen Lin    static RemoteViews buildUpdate(Context context, int appWidgetId,
73666ea1b28a76aeba74744148b15099254d918671Owen Lin                                   PhotoDatabaseHelper helper) {
74666ea1b28a76aeba74744148b15099254d918671Owen Lin        RemoteViews views = null;
75666ea1b28a76aeba74744148b15099254d918671Owen Lin        Bitmap bitmap = helper.getPhoto(appWidgetId);
76666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (bitmap != null) {
77666ea1b28a76aeba74744148b15099254d918671Owen Lin            views = new RemoteViews(context.getPackageName(),
78666ea1b28a76aeba74744148b15099254d918671Owen Lin                                    R.layout.photo_frame);
79666ea1b28a76aeba74744148b15099254d918671Owen Lin            views.setImageViewBitmap(R.id.photo, bitmap);
80666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
81666ea1b28a76aeba74744148b15099254d918671Owen Lin        return views;
82666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
83666ea1b28a76aeba74744148b15099254d918671Owen Lin
84666ea1b28a76aeba74744148b15099254d918671Owen Lin    static class PhotoDatabaseHelper extends SQLiteOpenHelper {
85666ea1b28a76aeba74744148b15099254d918671Owen Lin        private static final String DATABASE_NAME = "launcher.db";
86666ea1b28a76aeba74744148b15099254d918671Owen Lin
87666ea1b28a76aeba74744148b15099254d918671Owen Lin        private static final int DATABASE_VERSION = 2;
88666ea1b28a76aeba74744148b15099254d918671Owen Lin
89666ea1b28a76aeba74744148b15099254d918671Owen Lin        static final String TABLE_PHOTOS = "photos";
90666ea1b28a76aeba74744148b15099254d918671Owen Lin        static final String FIELD_APPWIDGET_ID = "appWidgetId";
91666ea1b28a76aeba74744148b15099254d918671Owen Lin        static final String FIELD_PHOTO_BLOB = "photoBlob";
92666ea1b28a76aeba74744148b15099254d918671Owen Lin
93666ea1b28a76aeba74744148b15099254d918671Owen Lin        PhotoDatabaseHelper(Context context) {
94666ea1b28a76aeba74744148b15099254d918671Owen Lin            super(context, DATABASE_NAME, null, DATABASE_VERSION);
95666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
96666ea1b28a76aeba74744148b15099254d918671Owen Lin
97666ea1b28a76aeba74744148b15099254d918671Owen Lin        @Override
98666ea1b28a76aeba74744148b15099254d918671Owen Lin        public void onCreate(SQLiteDatabase db) {
99666ea1b28a76aeba74744148b15099254d918671Owen Lin            db.execSQL("CREATE TABLE " + TABLE_PHOTOS + " (" +
100666ea1b28a76aeba74744148b15099254d918671Owen Lin                    FIELD_APPWIDGET_ID + " INTEGER PRIMARY KEY," +
101666ea1b28a76aeba74744148b15099254d918671Owen Lin                    FIELD_PHOTO_BLOB + " BLOB" +
102666ea1b28a76aeba74744148b15099254d918671Owen Lin                    ");");
103666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
104666ea1b28a76aeba74744148b15099254d918671Owen Lin
105666ea1b28a76aeba74744148b15099254d918671Owen Lin        @Override
106666ea1b28a76aeba74744148b15099254d918671Owen Lin        public void onUpgrade(SQLiteDatabase db, int oldVersion,
107666ea1b28a76aeba74744148b15099254d918671Owen Lin                              int newVersion) {
108666ea1b28a76aeba74744148b15099254d918671Owen Lin            int version = oldVersion;
109666ea1b28a76aeba74744148b15099254d918671Owen Lin
110666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (version != DATABASE_VERSION) {
111666ea1b28a76aeba74744148b15099254d918671Owen Lin                Log.w(TAG, "Destroying all old data.");
112666ea1b28a76aeba74744148b15099254d918671Owen Lin                db.execSQL("DROP TABLE IF EXISTS " + TABLE_PHOTOS);
113666ea1b28a76aeba74744148b15099254d918671Owen Lin                onCreate(db);
114666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
115666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
116666ea1b28a76aeba74744148b15099254d918671Owen Lin
117666ea1b28a76aeba74744148b15099254d918671Owen Lin        /**
118666ea1b28a76aeba74744148b15099254d918671Owen Lin         * Store the given bitmap in this database for the given appWidgetId.
119666ea1b28a76aeba74744148b15099254d918671Owen Lin         */
120666ea1b28a76aeba74744148b15099254d918671Owen Lin        public boolean setPhoto(int appWidgetId, Bitmap bitmap) {
121666ea1b28a76aeba74744148b15099254d918671Owen Lin            boolean success = false;
122666ea1b28a76aeba74744148b15099254d918671Owen Lin            try {
123666ea1b28a76aeba74744148b15099254d918671Owen Lin                // Try go guesstimate how much space the icon will take when
124666ea1b28a76aeba74744148b15099254d918671Owen Lin                // serialized to avoid unnecessary allocations/copies during
125666ea1b28a76aeba74744148b15099254d918671Owen Lin                // the write.
126666ea1b28a76aeba74744148b15099254d918671Owen Lin                int size = bitmap.getWidth() * bitmap.getHeight() * 4;
127666ea1b28a76aeba74744148b15099254d918671Owen Lin                ByteArrayOutputStream out = new ByteArrayOutputStream(size);
128666ea1b28a76aeba74744148b15099254d918671Owen Lin                bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
129666ea1b28a76aeba74744148b15099254d918671Owen Lin                out.flush();
130666ea1b28a76aeba74744148b15099254d918671Owen Lin                out.close();
131666ea1b28a76aeba74744148b15099254d918671Owen Lin
132666ea1b28a76aeba74744148b15099254d918671Owen Lin                ContentValues values = new ContentValues();
133666ea1b28a76aeba74744148b15099254d918671Owen Lin                values.put(PhotoDatabaseHelper.FIELD_APPWIDGET_ID, appWidgetId);
134666ea1b28a76aeba74744148b15099254d918671Owen Lin                values.put(PhotoDatabaseHelper.FIELD_PHOTO_BLOB,
135666ea1b28a76aeba74744148b15099254d918671Owen Lin                           out.toByteArray());
136666ea1b28a76aeba74744148b15099254d918671Owen Lin
137666ea1b28a76aeba74744148b15099254d918671Owen Lin                SQLiteDatabase db = getWritableDatabase();
138666ea1b28a76aeba74744148b15099254d918671Owen Lin                db.insertOrThrow(PhotoDatabaseHelper.TABLE_PHOTOS, null,
139666ea1b28a76aeba74744148b15099254d918671Owen Lin                                 values);
140666ea1b28a76aeba74744148b15099254d918671Owen Lin
141666ea1b28a76aeba74744148b15099254d918671Owen Lin                success = true;
142666ea1b28a76aeba74744148b15099254d918671Owen Lin            } catch (SQLiteException e) {
143666ea1b28a76aeba74744148b15099254d918671Owen Lin                Log.e(TAG, "Could not open database", e);
144666ea1b28a76aeba74744148b15099254d918671Owen Lin            } catch (IOException e) {
145666ea1b28a76aeba74744148b15099254d918671Owen Lin                Log.e(TAG, "Could not serialize photo", e);
146666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
147666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (LOGD) {
148666ea1b28a76aeba74744148b15099254d918671Owen Lin                Log.d(TAG, "setPhoto success=" + success);
149666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
150666ea1b28a76aeba74744148b15099254d918671Owen Lin            return success;
151666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
152666ea1b28a76aeba74744148b15099254d918671Owen Lin
153666ea1b28a76aeba74744148b15099254d918671Owen Lin        static final String[] PHOTOS_PROJECTION = {
154666ea1b28a76aeba74744148b15099254d918671Owen Lin            FIELD_PHOTO_BLOB,
155666ea1b28a76aeba74744148b15099254d918671Owen Lin        };
156666ea1b28a76aeba74744148b15099254d918671Owen Lin
157666ea1b28a76aeba74744148b15099254d918671Owen Lin        static final int INDEX_PHOTO_BLOB = 0;
158666ea1b28a76aeba74744148b15099254d918671Owen Lin
159666ea1b28a76aeba74744148b15099254d918671Owen Lin        /**
160666ea1b28a76aeba74744148b15099254d918671Owen Lin         * Inflate and return a bitmap for the given appWidgetId.
161666ea1b28a76aeba74744148b15099254d918671Owen Lin         */
162666ea1b28a76aeba74744148b15099254d918671Owen Lin        public Bitmap getPhoto(int appWidgetId) {
163666ea1b28a76aeba74744148b15099254d918671Owen Lin            Cursor c = null;
164666ea1b28a76aeba74744148b15099254d918671Owen Lin            Bitmap bitmap = null;
165666ea1b28a76aeba74744148b15099254d918671Owen Lin            try {
166666ea1b28a76aeba74744148b15099254d918671Owen Lin                SQLiteDatabase db = getReadableDatabase();
167666ea1b28a76aeba74744148b15099254d918671Owen Lin                String selection = String.format("%s=%d", FIELD_APPWIDGET_ID,
168666ea1b28a76aeba74744148b15099254d918671Owen Lin                                                 appWidgetId);
169666ea1b28a76aeba74744148b15099254d918671Owen Lin                c = db.query(TABLE_PHOTOS, PHOTOS_PROJECTION, selection, null,
170666ea1b28a76aeba74744148b15099254d918671Owen Lin                        null, null, null, null);
171666ea1b28a76aeba74744148b15099254d918671Owen Lin
172666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (c != null && LOGD) {
173666ea1b28a76aeba74744148b15099254d918671Owen Lin                    Log.d(TAG, "getPhoto query count=" + c.getCount());
174666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
175666ea1b28a76aeba74744148b15099254d918671Owen Lin
176666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (c != null && c.moveToFirst()) {
177666ea1b28a76aeba74744148b15099254d918671Owen Lin                    byte[] data = c.getBlob(INDEX_PHOTO_BLOB);
178666ea1b28a76aeba74744148b15099254d918671Owen Lin                    if (data != null) {
179666ea1b28a76aeba74744148b15099254d918671Owen Lin                        bitmap = BitmapFactory.decodeByteArray(data, 0,
180666ea1b28a76aeba74744148b15099254d918671Owen Lin                                data.length);
181666ea1b28a76aeba74744148b15099254d918671Owen Lin                    }
182666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
183666ea1b28a76aeba74744148b15099254d918671Owen Lin            } catch (SQLiteException e) {
184666ea1b28a76aeba74744148b15099254d918671Owen Lin                Log.e(TAG, "Could not load photo from database", e);
185666ea1b28a76aeba74744148b15099254d918671Owen Lin            } finally {
186666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (c != null) {
187666ea1b28a76aeba74744148b15099254d918671Owen Lin                    c.close();
188666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
189666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
190666ea1b28a76aeba74744148b15099254d918671Owen Lin            return bitmap;
191666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
192666ea1b28a76aeba74744148b15099254d918671Owen Lin
193666ea1b28a76aeba74744148b15099254d918671Owen Lin        /**
194666ea1b28a76aeba74744148b15099254d918671Owen Lin         * Remove any bitmap associated with the given appWidgetId.
195666ea1b28a76aeba74744148b15099254d918671Owen Lin         */
196666ea1b28a76aeba74744148b15099254d918671Owen Lin        public void deletePhoto(int appWidgetId) {
197666ea1b28a76aeba74744148b15099254d918671Owen Lin            try {
198666ea1b28a76aeba74744148b15099254d918671Owen Lin                SQLiteDatabase db = getWritableDatabase();
199666ea1b28a76aeba74744148b15099254d918671Owen Lin                String whereClause = String.format("%s=%d", FIELD_APPWIDGET_ID,
200666ea1b28a76aeba74744148b15099254d918671Owen Lin                                                   appWidgetId);
201666ea1b28a76aeba74744148b15099254d918671Owen Lin                db.delete(TABLE_PHOTOS, whereClause, null);
202666ea1b28a76aeba74744148b15099254d918671Owen Lin            } catch (SQLiteException e) {
203666ea1b28a76aeba74744148b15099254d918671Owen Lin                Log.e(TAG, "Could not delete photo from database", e);
204666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
205666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
206666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
207666ea1b28a76aeba74744148b15099254d918671Owen Lin
208666ea1b28a76aeba74744148b15099254d918671Owen Lin}
209666ea1b28a76aeba74744148b15099254d918671Owen Lin
210