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