Home | History | Annotate | Download | only in launcher3
      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.content.ContentValues;
     20 import android.content.Context;
     21 import android.database.Cursor;
     22 import android.database.sqlite.SQLiteDatabase;
     23 import android.database.sqlite.SQLiteOpenHelper;
     24 import android.graphics.Bitmap;
     25 import android.graphics.BitmapFactory;
     26 import android.graphics.drawable.BitmapDrawable;
     27 import android.graphics.drawable.Drawable;
     28 import android.net.Uri;
     29 import android.text.TextUtils;
     30 import android.util.Log;
     31 import android.util.Pair;
     32 import android.view.LayoutInflater;
     33 import android.view.View;
     34 import android.view.ViewGroup;
     35 import android.widget.BaseAdapter;
     36 import android.widget.ListAdapter;
     37 
     38 import com.android.launcher3.WallpaperCropActivity.CropViewScaleAndOffsetProvider;
     39 import com.android.photos.views.TiledImageRenderer.TileSource;
     40 
     41 import java.io.ByteArrayInputStream;
     42 import java.io.File;
     43 import java.io.FileOutputStream;
     44 import java.io.IOException;
     45 import java.io.InputStream;
     46 import java.util.ArrayList;
     47 
     48 
     49 public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
     50     private static String TAG = "Launcher3.SavedWallpaperImages";
     51     private ImageDb mDb;
     52     ArrayList<SavedWallpaperTile> mImages;
     53     Context mContext;
     54     LayoutInflater mLayoutInflater;
     55 
     56     public static class SavedWallpaperTile extends WallpaperPickerActivity.FileWallpaperInfo {
     57         private int mDbId;
     58 
     59         // three floats representing scale, centerX and centerY of the crop view in order.
     60         private Float[] mExtras;
     61         public SavedWallpaperTile(int dbId, File target, Drawable thumb, Float[] extras) {
     62             super(target, thumb);
     63             mDbId = dbId;
     64             mExtras = extras != null && extras.length == 3 ? extras : null;
     65         }
     66 
     67         @Override
     68         public void onDelete(WallpaperPickerActivity a) {
     69             a.getSavedImages().deleteImage(mDbId);
     70         }
     71 
     72         @Override
     73         protected CropViewScaleAndOffsetProvider getCropViewScaleAndOffsetProvider() {
     74             if (mExtras != null) {
     75                 return new CropViewScaleAndOffsetProvider() {
     76                     @Override
     77                     public void updateCropView(WallpaperCropActivity a, TileSource src) {
     78                         a.mCropView.setScaleAndCenter(mExtras[0], mExtras[1], mExtras[2]);
     79                     }
     80                 };
     81             }
     82             return null;
     83         }
     84 
     85         @Override
     86         public void onSave(final WallpaperPickerActivity a) {
     87             if (mExtras == null) {
     88                 super.onSave(a);
     89             } else {
     90                 boolean shouldFadeOutOnFinish = a.getWallpaperParallaxOffset() == 0f;
     91                 a.cropImageAndSetWallpaper(Uri.fromFile(mFile), null, true, shouldFadeOutOnFinish);
     92             }
     93         }
     94     }
     95 
     96     public SavedWallpaperImages(Context context) {
     97         // We used to store the saved images in the cache directory, but that meant they'd get
     98         // deleted sometimes-- move them to the data directory
     99         ImageDb.moveFromCacheDirectoryIfNecessary(context);
    100         mDb = new ImageDb(context);
    101         mContext = context;
    102         mLayoutInflater = LayoutInflater.from(context);
    103     }
    104 
    105     public void loadThumbnailsAndImageIdList() {
    106         mImages = new ArrayList<SavedWallpaperTile>();
    107         SQLiteDatabase db = mDb.getReadableDatabase();
    108         Cursor result = db.query(ImageDb.TABLE_NAME,
    109                 new String[] { ImageDb.COLUMN_ID,
    110                     ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME,
    111                     ImageDb.COLUMN_IMAGE_FILENAME,
    112                     ImageDb.COLUMN_EXTRAS}, // cols to return
    113                 null, // select query
    114                 null, // args to select query
    115                 null,
    116                 null,
    117                 ImageDb.COLUMN_ID + " DESC",
    118                 null);
    119 
    120         while (result.moveToNext()) {
    121             String filename = result.getString(1);
    122             File file = new File(mContext.getFilesDir(), filename);
    123 
    124             Bitmap thumb = BitmapFactory.decodeFile(file.getAbsolutePath());
    125             if (thumb != null) {
    126 
    127                 Float[] extras = null;
    128                 String extraStr = result.getString(3);
    129                 if (extraStr != null) {
    130                     String[] parts = extraStr.split(",");
    131                     extras = new Float[parts.length];
    132                     for (int i = 0; i < parts.length; i++) {
    133                         try {
    134                             extras[i] = Float.parseFloat(parts[i]);
    135                         } catch (Exception e) {
    136                             extras = null;
    137                             break;
    138                         }
    139                     }
    140                 }
    141 
    142                 mImages.add(new SavedWallpaperTile(result.getInt(0),
    143                         new File(mContext.getFilesDir(), result.getString(2)),
    144                         new BitmapDrawable(thumb), extras));
    145             }
    146         }
    147         result.close();
    148     }
    149 
    150     public int getCount() {
    151         return mImages.size();
    152     }
    153 
    154     public SavedWallpaperTile getItem(int position) {
    155         return mImages.get(position);
    156     }
    157 
    158     public long getItemId(int position) {
    159         return position;
    160     }
    161 
    162     public View getView(int position, View convertView, ViewGroup parent) {
    163         Drawable thumbDrawable = mImages.get(position).mThumb;
    164         if (thumbDrawable == null) {
    165             Log.e(TAG, "Error decoding thumbnail for wallpaper #" + position);
    166         }
    167         return WallpaperPickerActivity.createImageTileView(
    168                 mLayoutInflater, convertView, parent, thumbDrawable);
    169     }
    170 
    171     private Pair<String, String> getImageFilenames(int id) {
    172         SQLiteDatabase db = mDb.getReadableDatabase();
    173         Cursor result = db.query(ImageDb.TABLE_NAME,
    174                 new String[] { ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME,
    175                     ImageDb.COLUMN_IMAGE_FILENAME }, // cols to return
    176                 ImageDb.COLUMN_ID + " = ?", // select query
    177                 new String[] { Integer.toString(id) }, // args to select query
    178                 null,
    179                 null,
    180                 null,
    181                 null);
    182         if (result.getCount() > 0) {
    183             result.moveToFirst();
    184             String thumbFilename = result.getString(0);
    185             String imageFilename = result.getString(1);
    186             result.close();
    187             return new Pair<String, String>(thumbFilename, imageFilename);
    188         } else {
    189             return null;
    190         }
    191     }
    192 
    193     public void deleteImage(int id) {
    194         Pair<String, String> filenames = getImageFilenames(id);
    195         File imageFile = new File(mContext.getFilesDir(), filenames.first);
    196         imageFile.delete();
    197         File thumbFile = new File(mContext.getFilesDir(), filenames.second);
    198         thumbFile.delete();
    199         SQLiteDatabase db = mDb.getWritableDatabase();
    200         db.delete(ImageDb.TABLE_NAME,
    201                 ImageDb.COLUMN_ID + " = ?", // SELECT query
    202                 new String[] {
    203                     Integer.toString(id) // args to SELECT query
    204                 });
    205     }
    206 
    207     public void writeImage(Bitmap thumbnail, byte[] imageBytes) {
    208         try {
    209             writeImage(thumbnail, new ByteArrayInputStream(imageBytes), null);
    210         } catch (IOException e) {
    211             Log.e(TAG, "Failed writing images to storage " + e);
    212         }
    213     }
    214 
    215     public void writeImage(Bitmap thumbnail, Uri uri, Float[] extras) {
    216         try {
    217             writeImage(thumbnail, mContext.getContentResolver().openInputStream(uri), extras);
    218         } catch (IOException e) {
    219             Log.e(TAG, "Failed writing images to storage " + e);
    220         }
    221     }
    222 
    223     private void writeImage(Bitmap thumbnail, InputStream in, Float[] extras) throws IOException {
    224         File imageFile = File.createTempFile("wallpaper", "", mContext.getFilesDir());
    225         FileOutputStream imageFileStream =
    226                 mContext.openFileOutput(imageFile.getName(), Context.MODE_PRIVATE);
    227         byte[] buf = new byte[4096];    // 4k
    228         int len;
    229         while ((len = in.read(buf)) > 0) {
    230             imageFileStream.write(buf, 0, len);
    231         }
    232         imageFileStream.close();
    233         in.close();
    234 
    235         File thumbFile = File.createTempFile("wallpaperthumb", "", mContext.getFilesDir());
    236         FileOutputStream thumbFileStream =
    237                 mContext.openFileOutput(thumbFile.getName(), Context.MODE_PRIVATE);
    238         thumbnail.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
    239         thumbFileStream.close();
    240 
    241         SQLiteDatabase db = mDb.getWritableDatabase();
    242         ContentValues values = new ContentValues();
    243         values.put(ImageDb.COLUMN_IMAGE_THUMBNAIL_FILENAME, thumbFile.getName());
    244         values.put(ImageDb.COLUMN_IMAGE_FILENAME, imageFile.getName());
    245         if (extras != null) {
    246             values.put(ImageDb.COLUMN_EXTRAS, TextUtils.join(",", extras));
    247         }
    248         db.insert(ImageDb.TABLE_NAME, null, values);
    249     }
    250 
    251     static class ImageDb extends SQLiteOpenHelper {
    252         final static int DB_VERSION = 2;
    253         final static String TABLE_NAME = "saved_wallpaper_images";
    254         final static String COLUMN_ID = "id";
    255         final static String COLUMN_IMAGE_THUMBNAIL_FILENAME = "image_thumbnail";
    256         final static String COLUMN_IMAGE_FILENAME = "image";
    257         final static String COLUMN_EXTRAS = "extras";
    258 
    259         Context mContext;
    260 
    261         public ImageDb(Context context) {
    262             super(context, context.getDatabasePath(LauncherFiles.WALLPAPER_IMAGES_DB).getPath(),
    263                     null, DB_VERSION);
    264             // Store the context for later use
    265             mContext = context;
    266         }
    267 
    268         public static void moveFromCacheDirectoryIfNecessary(Context context) {
    269             // We used to store the saved images in the cache directory, but that meant they'd get
    270             // deleted sometimes-- move them to the data directory
    271             File oldSavedImagesFile = new File(context.getCacheDir(),
    272                     LauncherFiles.WALLPAPER_IMAGES_DB);
    273             File savedImagesFile = context.getDatabasePath(LauncherFiles.WALLPAPER_IMAGES_DB);
    274             if (oldSavedImagesFile.exists()) {
    275                 oldSavedImagesFile.renameTo(savedImagesFile);
    276             }
    277         }
    278         @Override
    279         public void onCreate(SQLiteDatabase database) {
    280             database.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
    281                     COLUMN_ID + " INTEGER NOT NULL, " +
    282                     COLUMN_IMAGE_THUMBNAIL_FILENAME + " TEXT NOT NULL, " +
    283                     COLUMN_IMAGE_FILENAME + " TEXT NOT NULL, " +
    284                     COLUMN_EXTRAS + " TEXT, " +
    285                     "PRIMARY KEY (" + COLUMN_ID + " ASC) " +
    286                     ");");
    287         }
    288 
    289         @Override
    290         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    291             if (oldVersion == 1) {
    292                 // Add extras column
    293                 db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + COLUMN_EXTRAS + " TEXT;");
    294             } else if (oldVersion != newVersion) {
    295                 // Delete all the records; they'll be repopulated as this is a cache
    296                 db.execSQL("DELETE FROM " + TABLE_NAME);
    297                 onCreate(db);
    298             }
    299         }
    300     }
    301 }
    302