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.crop.CropActivity;
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
onCreate(Bundle savedState)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 
onSaveInstanceStates(Bundle outState)89     protected void onSaveInstanceStates(Bundle outState) {
90         super.onSaveInstanceState(outState);
91         outState.putParcelable(KEY_PICKED_ITEM, mPickedItem);
92     }
93 
updateWidgetAndFinish(WidgetDatabaseHelper.Entry entry)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
onActivityResult(int requestCode, int resultCode, Intent data)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 
setPhotoWidget(Intent data)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 
setChoosenPhoto(Intent data)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(CropActivity.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 
setChoosenAlbum(Intent data)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 
setWidgetType(Intent data)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