1 /* 2 * Copyright (C) 2011 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.gallery3d.gadget; 18 19 import android.app.Activity; 20 import android.appwidget.AppWidgetManager; 21 import android.content.Intent; 22 import android.content.res.Resources; 23 import android.graphics.Bitmap; 24 import android.net.Uri; 25 import android.os.Bundle; 26 import android.util.Log; 27 import android.widget.RemoteViews; 28 29 import com.android.gallery3d.R; 30 import com.android.gallery3d.app.AlbumPicker; 31 import com.android.gallery3d.app.DialogPicker; 32 import com.android.gallery3d.app.GalleryApp; 33 import com.android.gallery3d.common.ApiHelper; 34 import com.android.gallery3d.data.DataManager; 35 import com.android.gallery3d.data.LocalAlbum; 36 import com.android.gallery3d.data.MediaSet; 37 import com.android.gallery3d.data.Path; 38 import com.android.gallery3d.filtershow.FilterShowActivity; 39 import com.android.gallery3d.filtershow.crop.CropExtras; 40 41 public class WidgetConfigure extends Activity { 42 @SuppressWarnings("unused") 43 private static final String TAG = "WidgetConfigure"; 44 45 public static final String KEY_WIDGET_TYPE = "widget-type"; 46 private static final String KEY_PICKED_ITEM = "picked-item"; 47 48 private static final int REQUEST_WIDGET_TYPE = 1; 49 private static final int REQUEST_CHOOSE_ALBUM = 2; 50 private static final int REQUEST_CROP_IMAGE = 3; 51 private static final int REQUEST_GET_PHOTO = 4; 52 53 public static final int RESULT_ERROR = RESULT_FIRST_USER; 54 55 // Scale up the widget size since we only specified the minimized 56 // size of the gadget. The real size could be larger. 57 // Note: There is also a limit on the size of data that can be 58 // passed in Binder's transaction. 59 private static float WIDGET_SCALE_FACTOR = 1.5f; 60 private static int MAX_WIDGET_SIDE = 360; 61 62 private int mAppWidgetId = -1; 63 private Uri mPickedItem; 64 65 @Override 66 protected void onCreate(Bundle savedState) { 67 super.onCreate(savedState); 68 mAppWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); 69 70 if (mAppWidgetId == -1) { 71 setResult(Activity.RESULT_CANCELED); 72 finish(); 73 return; 74 } 75 76 if (savedState == null) { 77 if (ApiHelper.HAS_REMOTE_VIEWS_SERVICE) { 78 Intent intent = new Intent(this, WidgetTypeChooser.class); 79 startActivityForResult(intent, REQUEST_WIDGET_TYPE); 80 } else { // Choose the photo type widget 81 setWidgetType(new Intent() 82 .putExtra(KEY_WIDGET_TYPE, R.id.widget_type_photo)); 83 } 84 } else { 85 mPickedItem = savedState.getParcelable(KEY_PICKED_ITEM); 86 } 87 } 88 89 protected void onSaveInstanceStates(Bundle outState) { 90 super.onSaveInstanceState(outState); 91 outState.putParcelable(KEY_PICKED_ITEM, mPickedItem); 92 } 93 94 private void updateWidgetAndFinish(WidgetDatabaseHelper.Entry entry) { 95 AppWidgetManager manager = AppWidgetManager.getInstance(this); 96 RemoteViews views = PhotoAppWidgetProvider.buildWidget(this, mAppWidgetId, entry); 97 manager.updateAppWidget(mAppWidgetId, views); 98 setResult(RESULT_OK, new Intent().putExtra( 99 AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId)); 100 finish(); 101 } 102 103 @Override 104 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 105 if (resultCode != RESULT_OK) { 106 setResult(resultCode, new Intent().putExtra( 107 AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId)); 108 finish(); 109 return; 110 } 111 112 if (requestCode == REQUEST_WIDGET_TYPE) { 113 setWidgetType(data); 114 } else if (requestCode == REQUEST_CHOOSE_ALBUM) { 115 setChoosenAlbum(data); 116 } else if (requestCode == REQUEST_GET_PHOTO) { 117 setChoosenPhoto(data); 118 } else if (requestCode == REQUEST_CROP_IMAGE) { 119 setPhotoWidget(data); 120 } else { 121 throw new AssertionError("unknown request: " + requestCode); 122 } 123 } 124 125 private void setPhotoWidget(Intent data) { 126 // Store the cropped photo in our database 127 Bitmap bitmap = (Bitmap) data.getParcelableExtra("data"); 128 WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this); 129 try { 130 helper.setPhoto(mAppWidgetId, mPickedItem, bitmap); 131 updateWidgetAndFinish(helper.getEntry(mAppWidgetId)); 132 } finally { 133 helper.close(); 134 } 135 } 136 137 private void setChoosenPhoto(Intent data) { 138 Resources res = getResources(); 139 140 float width = res.getDimension(R.dimen.appwidget_width); 141 float height = res.getDimension(R.dimen.appwidget_height); 142 143 // We try to crop a larger image (by scale factor), but there is still 144 // a bound on the binder limit. 145 float scale = Math.min(WIDGET_SCALE_FACTOR, 146 MAX_WIDGET_SIDE / Math.max(width, height)); 147 148 int widgetWidth = Math.round(width * scale); 149 int widgetHeight = Math.round(height * scale); 150 151 mPickedItem = data.getData(); 152 Intent request = new Intent(FilterShowActivity.CROP_ACTION, mPickedItem) 153 .putExtra(CropExtras.KEY_OUTPUT_X, widgetWidth) 154 .putExtra(CropExtras.KEY_OUTPUT_Y, widgetHeight) 155 .putExtra(CropExtras.KEY_ASPECT_X, widgetWidth) 156 .putExtra(CropExtras.KEY_ASPECT_Y, widgetHeight) 157 .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true) 158 .putExtra(CropExtras.KEY_SCALE, true) 159 .putExtra(CropExtras.KEY_RETURN_DATA, true); 160 startActivityForResult(request, REQUEST_CROP_IMAGE); 161 } 162 163 private void setChoosenAlbum(Intent data) { 164 String albumPath = data.getStringExtra(AlbumPicker.KEY_ALBUM_PATH); 165 WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this); 166 try { 167 String relativePath = null; 168 GalleryApp galleryApp = (GalleryApp) getApplicationContext(); 169 DataManager manager = galleryApp.getDataManager(); 170 Path path = Path.fromString(albumPath); 171 MediaSet mediaSet = (MediaSet) manager.getMediaObject(path); 172 if (mediaSet instanceof LocalAlbum) { 173 int bucketId = Integer.parseInt(path.getSuffix()); 174 // If the chosen album is a local album, find relative path 175 // Otherwise, leave the relative path field empty 176 relativePath = LocalAlbum.getRelativePath(bucketId); 177 Log.i(TAG, "Setting widget, album path: " + albumPath 178 + ", relative path: " + relativePath); 179 } 180 helper.setWidget(mAppWidgetId, 181 WidgetDatabaseHelper.TYPE_ALBUM, albumPath, relativePath); 182 updateWidgetAndFinish(helper.getEntry(mAppWidgetId)); 183 } finally { 184 helper.close(); 185 } 186 } 187 188 private void setWidgetType(Intent data) { 189 int widgetType = data.getIntExtra(KEY_WIDGET_TYPE, R.id.widget_type_shuffle); 190 if (widgetType == R.id.widget_type_album) { 191 Intent intent = new Intent(this, AlbumPicker.class); 192 startActivityForResult(intent, REQUEST_CHOOSE_ALBUM); 193 } else if (widgetType == R.id.widget_type_shuffle) { 194 WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this); 195 try { 196 helper.setWidget(mAppWidgetId, WidgetDatabaseHelper.TYPE_SHUFFLE, null, null); 197 updateWidgetAndFinish(helper.getEntry(mAppWidgetId)); 198 } finally { 199 helper.close(); 200 } 201 } else { 202 // Explicitly send the intent to the DialogPhotoPicker 203 Intent request = new Intent(this, DialogPicker.class) 204 .setAction(Intent.ACTION_GET_CONTENT) 205 .setType("image/*"); 206 startActivityForResult(request, REQUEST_GET_PHOTO); 207 } 208 } 209 } 210