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 com.android.photos.BitmapRegionTileSource; 38 39 import java.io.File; 40 import java.io.FileOutputStream; 41 import java.io.IOException; 42 import java.util.ArrayList; 43 44 45 public class SavedWallpaperImages extends BaseAdapter implements ListAdapter { 46 private static String TAG = "Launcher3.SavedWallpaperImages"; 47 private ImageDb mDb; 48 ArrayList<SavedWallpaperTile> mImages; 49 Context mContext; 50 LayoutInflater mLayoutInflater; 51 52 public static class SavedWallpaperTile extends WallpaperPickerActivity.WallpaperTileInfo { 53 private int mDbId; 54 private Drawable mThumb; 55 public SavedWallpaperTile(int dbId, Drawable thumb) { 56 mDbId = dbId; 57 mThumb = thumb; 58 } 59 @Override 60 public void onClick(WallpaperPickerActivity a) { 61 String imageFilename = a.getSavedImages().getImageFilename(mDbId); 62 File file = new File(a.getFilesDir(), imageFilename); 63 CropView v = a.getCropView(); 64 int rotation = WallpaperCropActivity.getRotationFromExif(file.getAbsolutePath()); 65 v.setTileSource( 66 new BitmapRegionTileSource(a, file.getAbsolutePath(), 1024, rotation), null); 67 v.moveToLeft(); 68 v.setTouchEnabled(false); 69 } 70 @Override 71 public void onSave(WallpaperPickerActivity a) { 72 boolean finishActivityWhenDone = true; 73 String imageFilename = a.getSavedImages().getImageFilename(mDbId); 74 a.setWallpaper(imageFilename, finishActivityWhenDone); 75 } 76 @Override 77 public void onDelete(WallpaperPickerActivity a) { 78 a.getSavedImages().deleteImage(mDbId); 79 } 80 @Override 81 public boolean isSelectable() { 82 return true; 83 } 84 @Override 85 public boolean isNamelessWallpaper() { 86 return true; 87 } 88 } 89 90 public SavedWallpaperImages(Activity context) { 91 mDb = new ImageDb(context); 92 mContext = context; 93 mLayoutInflater = context.getLayoutInflater(); 94 } 95 96 public void loadThumbnailsAndImageIdList() { 97 mImages = new ArrayList<SavedWallpaperTile>(); 98 SQLiteDatabase db = mDb.getReadableDatabase(); 99 Cursor result = db.query(ImageDb.TABLE_NAME, 100 new String[] { ImageDb.COLUMN_ID, 101 ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME }, // cols to return 102 null, // select query 103 null, // args to select query 104 null, 105 null, 106 ImageDb.COLUMN_ID + " DESC", 107 null); 108 109 while (result.moveToNext()) { 110 String filename = result.getString(1); 111 File file = new File(mContext.getFilesDir(), filename); 112 113 Bitmap thumb = BitmapFactory.decodeFile(file.getAbsolutePath()); 114 if (thumb != null) { 115 mImages.add(new SavedWallpaperTile(result.getInt(0), new BitmapDrawable(thumb))); 116 } 117 } 118 result.close(); 119 } 120 121 public int getCount() { 122 return mImages.size(); 123 } 124 125 public SavedWallpaperTile getItem(int position) { 126 return mImages.get(position); 127 } 128 129 public long getItemId(int position) { 130 return position; 131 } 132 133 public View getView(int position, View convertView, ViewGroup parent) { 134 Drawable thumbDrawable = mImages.get(position).mThumb; 135 if (thumbDrawable == null) { 136 Log.e(TAG, "Error decoding thumbnail for wallpaper #" + position); 137 } 138 return WallpaperPickerActivity.createImageTileView( 139 mLayoutInflater, position, convertView, parent, thumbDrawable); 140 } 141 142 public String getImageFilename(int id) { 143 Pair<String, String> filenames = getImageFilenames(id); 144 if (filenames != null) { 145 return filenames.second; 146 } 147 return null; 148 } 149 150 private Pair<String, String> getImageFilenames(int id) { 151 SQLiteDatabase db = mDb.getReadableDatabase(); 152 Cursor result = db.query(ImageDb.TABLE_NAME, 153 new String[] { ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME, 154 ImageDb.COLUMN_IMAGE_FILENAME }, // cols to return 155 ImageDb.COLUMN_ID + " = ?", // select query 156 new String[] { Integer.toString(id) }, // args to select query 157 null, 158 null, 159 null, 160 null); 161 if (result.getCount() > 0) { 162 result.moveToFirst(); 163 String thumbFilename = result.getString(0); 164 String imageFilename = result.getString(1); 165 result.close(); 166 return new Pair<String, String>(thumbFilename, imageFilename); 167 } else { 168 return null; 169 } 170 } 171 172 public void deleteImage(int id) { 173 Pair<String, String> filenames = getImageFilenames(id); 174 File imageFile = new File(mContext.getFilesDir(), filenames.first); 175 imageFile.delete(); 176 File thumbFile = new File(mContext.getFilesDir(), filenames.second); 177 thumbFile.delete(); 178 SQLiteDatabase db = mDb.getWritableDatabase(); 179 db.delete(ImageDb.TABLE_NAME, 180 ImageDb.COLUMN_ID + " = ?", // SELECT query 181 new String[] { 182 Integer.toString(id) // args to SELECT query 183 }); 184 } 185 186 public void writeImage(Bitmap thumbnail, byte[] imageBytes) { 187 try { 188 File imageFile = File.createTempFile("wallpaper", "", mContext.getFilesDir()); 189 FileOutputStream imageFileStream = 190 mContext.openFileOutput(imageFile.getName(), Context.MODE_PRIVATE); 191 imageFileStream.write(imageBytes); 192 imageFileStream.close(); 193 194 File thumbFile = File.createTempFile("wallpaperthumb", "", mContext.getFilesDir()); 195 FileOutputStream thumbFileStream = 196 mContext.openFileOutput(thumbFile.getName(), Context.MODE_PRIVATE); 197 thumbnail.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream); 198 thumbFileStream.close(); 199 200 SQLiteDatabase db = mDb.getWritableDatabase(); 201 ContentValues values = new ContentValues(); 202 values.put(ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME, thumbFile.getName()); 203 values.put(ImageDb.COLUMN_IMAGE_FILENAME, imageFile.getName()); 204 db.insert(ImageDb.TABLE_NAME, null, values); 205 } catch (IOException e) { 206 Log.e(TAG, "Failed writing images to storage " + e); 207 } 208 } 209 210 static class ImageDb extends SQLiteOpenHelper { 211 final static int DB_VERSION = 1; 212 final static String DB_NAME = "saved_wallpaper_images.db"; 213 final static String TABLE_NAME = "saved_wallpaper_images"; 214 final static String COLUMN_ID = "id"; 215 final static String COLUMN_IMAGE_THUMBNAIL_FILENAME = "image_thumbnail"; 216 final static String COLUMN_IMAGE_FILENAME = "image"; 217 218 Context mContext; 219 220 public ImageDb(Context context) { 221 super(context, new File(context.getCacheDir(), DB_NAME).getPath(), null, DB_VERSION); 222 // Store the context for later use 223 mContext = context; 224 } 225 226 @Override 227 public void onCreate(SQLiteDatabase database) { 228 database.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + 229 COLUMN_ID + " INTEGER NOT NULL, " + 230 COLUMN_IMAGE_THUMBNAIL_FILENAME + " TEXT NOT NULL, " + 231 COLUMN_IMAGE_FILENAME + " TEXT NOT NULL, " + 232 "PRIMARY KEY (" + COLUMN_ID + " ASC) " + 233 ");"); 234 } 235 236 @Override 237 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 238 if (oldVersion != newVersion) { 239 // Delete all the records; they'll be repopulated as this is a cache 240 db.execSQL("DELETE FROM " + TABLE_NAME); 241 } 242 } 243 } 244 } 245