1 /* 2 * Copyright (C) 2008 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.launcher2; 18 19 import android.app.Activity; 20 import android.app.WallpaperManager; 21 import android.content.res.Resources; 22 import android.graphics.BitmapFactory; 23 import android.graphics.Bitmap; 24 import android.graphics.drawable.Drawable; 25 import android.os.Bundle; 26 import android.os.AsyncTask; 27 import android.util.Log; 28 import android.view.LayoutInflater; 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.view.Window; 32 import android.view.View.OnClickListener; 33 import android.widget.AdapterView; 34 import android.widget.BaseAdapter; 35 import android.widget.Gallery; 36 import android.widget.ImageView; 37 38 import java.io.IOException; 39 import java.util.ArrayList; 40 41 import com.android.launcher.R; 42 43 public class WallpaperChooser extends Activity implements AdapterView.OnItemSelectedListener, 44 OnClickListener { 45 private static final String TAG = "Launcher.WallpaperChooser"; 46 47 private Gallery mGallery; 48 private ImageView mImageView; 49 private boolean mIsWallpaperSet; 50 51 private Bitmap mBitmap; 52 53 private ArrayList<Integer> mThumbs; 54 private ArrayList<Integer> mImages; 55 private WallpaperLoader mLoader; 56 57 @Override 58 public void onCreate(Bundle icicle) { 59 super.onCreate(icicle); 60 requestWindowFeature(Window.FEATURE_NO_TITLE); 61 62 findWallpapers(); 63 64 setContentView(R.layout.wallpaper_chooser); 65 66 mGallery = (Gallery) findViewById(R.id.gallery); 67 mGallery.setAdapter(new ImageAdapter(this)); 68 mGallery.setOnItemSelectedListener(this); 69 mGallery.setCallbackDuringFling(false); 70 71 findViewById(R.id.set).setOnClickListener(this); 72 73 mImageView = (ImageView) findViewById(R.id.wallpaper); 74 } 75 76 private void findWallpapers() { 77 mThumbs = new ArrayList<Integer>(24); 78 mImages = new ArrayList<Integer>(24); 79 80 final Resources resources = getResources(); 81 // Context.getPackageName() may return the "original" package name, 82 // com.android.launcher2; Resources needs the real package name, 83 // com.android.launcher. So we ask Resources for what it thinks the 84 // package name should be. 85 final String packageName = resources.getResourcePackageName(R.array.wallpapers); 86 87 addWallpapers(resources, packageName, R.array.wallpapers); 88 addWallpapers(resources, packageName, R.array.extra_wallpapers); 89 } 90 91 private void addWallpapers(Resources resources, String packageName, int list) { 92 final String[] extras = resources.getStringArray(list); 93 for (String extra : extras) { 94 int res = resources.getIdentifier(extra, "drawable", packageName); 95 if (res != 0) { 96 final int thumbRes = resources.getIdentifier(extra + "_small", 97 "drawable", packageName); 98 99 if (thumbRes != 0) { 100 mThumbs.add(thumbRes); 101 mImages.add(res); 102 // Log.d(TAG, "addWallpapers: [" + packageName + "]: " + extra + " (" + res + ")"); 103 } 104 } 105 } 106 } 107 108 @Override 109 protected void onResume() { 110 super.onResume(); 111 mIsWallpaperSet = false; 112 } 113 114 @Override 115 protected void onDestroy() { 116 super.onDestroy(); 117 118 if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) { 119 mLoader.cancel(true); 120 mLoader = null; 121 } 122 } 123 124 public void onItemSelected(AdapterView parent, View v, int position, long id) { 125 if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) { 126 mLoader.cancel(); 127 } 128 mLoader = (WallpaperLoader) new WallpaperLoader().execute(position); 129 } 130 131 /* 132 * When using touch if you tap an image it triggers both the onItemClick and 133 * the onTouchEvent causing the wallpaper to be set twice. Ensure we only 134 * set the wallpaper once. 135 */ 136 private void selectWallpaper(int position) { 137 if (mIsWallpaperSet) { 138 return; 139 } 140 141 mIsWallpaperSet = true; 142 try { 143 WallpaperManager wpm = (WallpaperManager)getSystemService(WALLPAPER_SERVICE); 144 wpm.setResource(mImages.get(position)); 145 setResult(RESULT_OK); 146 finish(); 147 } catch (IOException e) { 148 Log.e(TAG, "Failed to set wallpaper: " + e); 149 } 150 } 151 152 public void onNothingSelected(AdapterView parent) { 153 } 154 155 private class ImageAdapter extends BaseAdapter { 156 private LayoutInflater mLayoutInflater; 157 158 ImageAdapter(WallpaperChooser context) { 159 mLayoutInflater = context.getLayoutInflater(); 160 } 161 162 public int getCount() { 163 return mThumbs.size(); 164 } 165 166 public Object getItem(int position) { 167 return position; 168 } 169 170 public long getItemId(int position) { 171 return position; 172 } 173 174 public View getView(int position, View convertView, ViewGroup parent) { 175 ImageView image; 176 177 if (convertView == null) { 178 image = (ImageView) mLayoutInflater.inflate(R.layout.wallpaper_item, parent, false); 179 } else { 180 image = (ImageView) convertView; 181 } 182 183 int thumbRes = mThumbs.get(position); 184 image.setImageResource(thumbRes); 185 Drawable thumbDrawable = image.getDrawable(); 186 if (thumbDrawable != null) { 187 thumbDrawable.setDither(true); 188 } else { 189 Log.e(TAG, "Error decoding thumbnail resId=" + thumbRes + " for wallpaper #" 190 + position); 191 } 192 return image; 193 } 194 } 195 196 public void onClick(View v) { 197 selectWallpaper(mGallery.getSelectedItemPosition()); 198 } 199 200 class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> { 201 BitmapFactory.Options mOptions; 202 203 WallpaperLoader() { 204 mOptions = new BitmapFactory.Options(); 205 mOptions.inDither = false; 206 mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; 207 } 208 209 protected Bitmap doInBackground(Integer... params) { 210 if (isCancelled()) return null; 211 try { 212 return BitmapFactory.decodeResource(getResources(), 213 mImages.get(params[0]), mOptions); 214 } catch (OutOfMemoryError e) { 215 return null; 216 } 217 } 218 219 @Override 220 protected void onPostExecute(Bitmap b) { 221 if (b == null) return; 222 223 if (!isCancelled() && !mOptions.mCancel) { 224 // Help the GC 225 if (mBitmap != null) { 226 mBitmap.recycle(); 227 } 228 229 final ImageView view = mImageView; 230 view.setImageBitmap(b); 231 232 mBitmap = b; 233 234 final Drawable drawable = view.getDrawable(); 235 drawable.setFilterBitmap(true); 236 drawable.setDither(true); 237 238 view.postInvalidate(); 239 240 mLoader = null; 241 } else { 242 b.recycle(); 243 } 244 } 245 246 void cancel() { 247 mOptions.requestCancelDecode(); 248 super.cancel(true); 249 } 250 } 251 } 252