1 /*
2  * Copyright (C) 2013 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.launcher3;
18 
19 import android.app.Activity;
20 import android.content.ContentValues;
21 import android.content.Context;
22 import android.database.Cursor;
23 import android.database.sqlite.SQLiteDatabase;
24 import android.database.sqlite.SQLiteOpenHelper;
25 import android.graphics.Bitmap;
26 import android.graphics.BitmapFactory;
27 import android.graphics.drawable.BitmapDrawable;
28 import android.graphics.drawable.Drawable;
29 import android.util.Log;
30 import android.util.Pair;
31 import android.view.LayoutInflater;
32 import android.view.View;
33 import android.view.ViewGroup;
34 import android.widget.BaseAdapter;
35 import android.widget.ListAdapter;
36 
37 import java.io.File;
38 import java.io.FileOutputStream;
39 import java.io.IOException;
40 import java.util.ArrayList;
41 
42 
43 public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
44     private static String TAG = "Launcher3.SavedWallpaperImages";
45     private ImageDb mDb;
46     ArrayList<SavedWallpaperTile> mImages;
47     Context mContext;
48     LayoutInflater mLayoutInflater;
49 
50     public static class SavedWallpaperTile extends WallpaperPickerActivity.FileWallpaperInfo {
51         private int mDbId;
SavedWallpaperTile(int dbId, File target, Drawable thumb)52         public SavedWallpaperTile(int dbId, File target, Drawable thumb) {
53             super(target, thumb);
54             mDbId = dbId;
55         }
56 
57         @Override
onDelete(WallpaperPickerActivity a)58         public void onDelete(WallpaperPickerActivity a) {
59             a.getSavedImages().deleteImage(mDbId);
60         }
61     }
62 
SavedWallpaperImages(Activity context)63     public SavedWallpaperImages(Activity context) {
64         // We used to store the saved images in the cache directory, but that meant they'd get
65         // deleted sometimes-- move them to the data directory
66         ImageDb.moveFromCacheDirectoryIfNecessary(context);
67         mDb = new ImageDb(context);
68         mContext = context;
69         mLayoutInflater = context.getLayoutInflater();
70     }
71 
loadThumbnailsAndImageIdList()72     public void loadThumbnailsAndImageIdList() {
73         mImages = new ArrayList<SavedWallpaperTile>();
74         SQLiteDatabase db = mDb.getReadableDatabase();
75         Cursor result = db.query(ImageDb.TABLE_NAME,
76                 new String[] { ImageDb.COLUMN_ID,
77                     ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME,
78                     ImageDb.COLUMN_IMAGE_FILENAME}, // cols to return
79                 null, // select query
80                 null, // args to select query
81                 null,
82                 null,
83                 ImageDb.COLUMN_ID + " DESC",
84                 null);
85 
86         while (result.moveToNext()) {
87             String filename = result.getString(1);
88             File file = new File(mContext.getFilesDir(), filename);
89 
90             Bitmap thumb = BitmapFactory.decodeFile(file.getAbsolutePath());
91             if (thumb != null) {
92                 mImages.add(new SavedWallpaperTile(result.getInt(0),
93                         new File(mContext.getFilesDir(), result.getString(2)),
94                         new BitmapDrawable(thumb)));
95             }
96         }
97         result.close();
98     }
99 
getCount()100     public int getCount() {
101         return mImages.size();
102     }
103 
getItem(int position)104     public SavedWallpaperTile getItem(int position) {
105         return mImages.get(position);
106     }
107 
getItemId(int position)108     public long getItemId(int position) {
109         return position;
110     }
111 
getView(int position, View convertView, ViewGroup parent)112     public View getView(int position, View convertView, ViewGroup parent) {
113         Drawable thumbDrawable = mImages.get(position).mThumb;
114         if (thumbDrawable == null) {
115             Log.e(TAG, "Error decoding thumbnail for wallpaper #" + position);
116         }
117         return WallpaperPickerActivity.createImageTileView(
118                 mLayoutInflater, convertView, parent, thumbDrawable);
119     }
120 
getImageFilenames(int id)121     private Pair<String, String> getImageFilenames(int id) {
122         SQLiteDatabase db = mDb.getReadableDatabase();
123         Cursor result = db.query(ImageDb.TABLE_NAME,
124                 new String[] { ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME,
125                     ImageDb.COLUMN_IMAGE_FILENAME }, // cols to return
126                 ImageDb.COLUMN_ID + " = ?", // select query
127                 new String[] { Integer.toString(id) }, // args to select query
128                 null,
129                 null,
130                 null,
131                 null);
132         if (result.getCount() > 0) {
133             result.moveToFirst();
134             String thumbFilename = result.getString(0);
135             String imageFilename = result.getString(1);
136             result.close();
137             return new Pair<String, String>(thumbFilename, imageFilename);
138         } else {
139             return null;
140         }
141     }
142 
deleteImage(int id)143     public void deleteImage(int id) {
144         Pair<String, String> filenames = getImageFilenames(id);
145         File imageFile = new File(mContext.getFilesDir(), filenames.first);
146         imageFile.delete();
147         File thumbFile = new File(mContext.getFilesDir(), filenames.second);
148         thumbFile.delete();
149         SQLiteDatabase db = mDb.getWritableDatabase();
150         db.delete(ImageDb.TABLE_NAME,
151                 ImageDb.COLUMN_ID + " = ?", // SELECT query
152                 new String[] {
153                     Integer.toString(id) // args to SELECT query
154                 });
155     }
156 
writeImage(Bitmap thumbnail, byte[] imageBytes)157     public void writeImage(Bitmap thumbnail, byte[] imageBytes) {
158         try {
159             File imageFile = File.createTempFile("wallpaper", "", mContext.getFilesDir());
160             FileOutputStream imageFileStream =
161                     mContext.openFileOutput(imageFile.getName(), Context.MODE_PRIVATE);
162             imageFileStream.write(imageBytes);
163             imageFileStream.close();
164 
165             File thumbFile = File.createTempFile("wallpaperthumb", "", mContext.getFilesDir());
166             FileOutputStream thumbFileStream =
167                     mContext.openFileOutput(thumbFile.getName(), Context.MODE_PRIVATE);
168             thumbnail.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
169             thumbFileStream.close();
170 
171             SQLiteDatabase db = mDb.getWritableDatabase();
172             ContentValues values = new ContentValues();
173             values.put(ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME, thumbFile.getName());
174             values.put(ImageDb.COLUMN_IMAGE_FILENAME, imageFile.getName());
175             db.insert(ImageDb.TABLE_NAME, null, values);
176         } catch (IOException e) {
177             Log.e(TAG, "Failed writing images to storage " + e);
178         }
179     }
180 
181     static class ImageDb extends SQLiteOpenHelper {
182         final static int DB_VERSION = 1;
183         final static String TABLE_NAME = "saved_wallpaper_images";
184         final static String COLUMN_ID = "id";
185         final static String COLUMN_IMAGE_THUMBNAIL_FILENAME = "image_thumbnail";
186         final static String COLUMN_IMAGE_FILENAME = "image";
187 
188         Context mContext;
189 
ImageDb(Context context)190         public ImageDb(Context context) {
191             super(context, context.getDatabasePath(LauncherFiles.WALLPAPER_IMAGES_DB).getPath(),
192                     null, DB_VERSION);
193             // Store the context for later use
194             mContext = context;
195         }
196 
moveFromCacheDirectoryIfNecessary(Context context)197         public static void moveFromCacheDirectoryIfNecessary(Context context) {
198             // We used to store the saved images in the cache directory, but that meant they'd get
199             // deleted sometimes-- move them to the data directory
200             File oldSavedImagesFile = new File(context.getCacheDir(),
201                     LauncherFiles.WALLPAPER_IMAGES_DB);
202             File savedImagesFile = context.getDatabasePath(LauncherFiles.WALLPAPER_IMAGES_DB);
203             if (oldSavedImagesFile.exists()) {
204                 oldSavedImagesFile.renameTo(savedImagesFile);
205             }
206         }
207         @Override
onCreate(SQLiteDatabase database)208         public void onCreate(SQLiteDatabase database) {
209             database.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
210                     COLUMN_ID + " INTEGER NOT NULL, " +
211                     COLUMN_IMAGE_THUMBNAIL_FILENAME + " TEXT NOT NULL, " +
212                     COLUMN_IMAGE_FILENAME + " TEXT NOT NULL, " +
213                     "PRIMARY KEY (" + COLUMN_ID + " ASC) " +
214                     ");");
215         }
216 
217         @Override
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)218         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
219             if (oldVersion != newVersion) {
220                 // Delete all the records; they'll be repopulated as this is a cache
221                 db.execSQL("DELETE FROM " + TABLE_NAME);
222             }
223         }
224     }
225 }
226