1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17d6db8eab6df048b9065834113a6d46a885af01d3Owen Linpackage com.android.gallery3d.gadget; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19a2cb30b688131380cab763a1b4da25f15a9fa45aOwen Linimport android.annotation.TargetApi; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.app.PendingIntent; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.appwidget.AppWidgetManager; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.appwidget.AppWidgetProvider; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Context; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Intent; 25d6db8eab6df048b9065834113a6d46a885af01d3Owen Linimport android.graphics.Bitmap; 26d6db8eab6df048b9065834113a6d46a885af01d3Owen Linimport android.graphics.BitmapFactory; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.net.Uri; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.util.Log; 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.widget.RemoteViews; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 312b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.R; 32a2cb30b688131380cab763a1b4da25f15a9fa45aOwen Linimport com.android.gallery3d.common.ApiHelper; 332b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.gadget.WidgetDatabaseHelper.Entry; 3440234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyanimport com.android.gallery3d.onetimeinitializer.GalleryWidgetMigrator; 352b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 36d6db8eab6df048b9065834113a6d46a885af01d3Owen Linpublic class PhotoAppWidgetProvider extends AppWidgetProvider { 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "WidgetProvider"; 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin static RemoteViews buildWidget(Context context, int id, Entry entry) { 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin switch (entry.type) { 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case WidgetDatabaseHelper.TYPE_ALBUM: 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case WidgetDatabaseHelper.TYPE_SHUFFLE: 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return buildStackWidget(context, id, entry); 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case WidgetDatabaseHelper.TYPE_SINGLE_PHOTO: 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return buildFrameWidget(context, id, entry); 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new RuntimeException("invalid type - " + entry.type); 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onUpdate(Context context, 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin AppWidgetManager appWidgetManager, int[] appWidgetIds) { 55a2cb30b688131380cab763a1b4da25f15a9fa45aOwen Lin 56a2cb30b688131380cab763a1b4da25f15a9fa45aOwen Lin if (ApiHelper.HAS_REMOTE_VIEWS_SERVICE) { 57a2cb30b688131380cab763a1b4da25f15a9fa45aOwen Lin // migrate gallery widgets from pre-JB releases to JB due to bucket ID change 58a2cb30b688131380cab763a1b4da25f15a9fa45aOwen Lin GalleryWidgetMigrator.migrateGalleryWidgets(context); 59a2cb30b688131380cab763a1b4da25f15a9fa45aOwen Lin } 6040234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin WidgetDatabaseHelper helper = new WidgetDatabaseHelper(context); 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int id : appWidgetIds) { 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Entry entry = helper.getEntry(id); 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (entry != null) { 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin RemoteViews views = buildWidget(context, id, entry); 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin appWidgetManager.updateAppWidget(id, views); 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.e(TAG, "cannot load widget: " + id); 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin helper.close(); 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin super.onUpdate(context, appWidgetManager, appWidgetIds); 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 78369d0e6b4ee4f034a418177516ea8a76a16953dfOwen Lin @SuppressWarnings("deprecation") 79a2cb30b688131380cab763a1b4da25f15a9fa45aOwen Lin @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static RemoteViews buildStackWidget(Context context, int widgetId, Entry entry) { 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin RemoteViews views = new RemoteViews( 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin context.getPackageName(), R.layout.appwidget_main); 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Intent intent = new Intent(context, WidgetService.class); 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin intent.putExtra(WidgetService.EXTRA_WIDGET_TYPE, entry.type); 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin intent.putExtra(WidgetService.EXTRA_ALBUM_PATH, entry.albumPath); 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin intent.setData(Uri.parse("widget://gallery/" + widgetId)); 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 90369d0e6b4ee4f034a418177516ea8a76a16953dfOwen Lin // We use the deprecated API for backward compatibility 91369d0e6b4ee4f034a418177516ea8a76a16953dfOwen Lin // The new API is available in ICE_CREAM_SANDWICH (15) 92369d0e6b4ee4f034a418177516ea8a76a16953dfOwen Lin views.setRemoteAdapter(widgetId, R.id.appwidget_stack_view, intent); 93369d0e6b4ee4f034a418177516ea8a76a16953dfOwen Lin 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin views.setEmptyView(R.id.appwidget_stack_view, R.id.appwidget_empty_view); 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Intent clickIntent = new Intent(context, WidgetClickHandler.class); 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin PendingIntent pendingIntent = PendingIntent.getActivity( 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT); 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin views.setPendingIntentTemplate(R.id.appwidget_stack_view, pendingIntent); 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return views; 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin static RemoteViews buildFrameWidget(Context context, int appWidgetId, Entry entry) { 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin RemoteViews views = new RemoteViews( 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin context.getPackageName(), R.layout.photo_frame); 107d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin try { 108d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin byte[] data = entry.imageData; 109d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); 110d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin views.setImageViewBitmap(R.id.photo, bitmap); 111d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin } catch (Throwable t) { 112d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin Log.w(TAG, "cannot load widget image: " + appWidgetId, t); 113d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin } 114d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin 115d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin if (entry.imageUri != null) { 116d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin try { 117d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin Uri uri = Uri.parse(entry.imageUri); 118d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin Intent clickIntent = new Intent(context, WidgetClickHandler.class) 119d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin .setData(uri); 120d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin PendingIntent pendingClickIntent = PendingIntent.getActivity(context, 0, 121d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin clickIntent, PendingIntent.FLAG_CANCEL_CURRENT); 122d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin views.setOnClickPendingIntent(R.id.photo, pendingClickIntent); 123d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin } catch (Throwable t) { 124d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin Log.w(TAG, "cannot load widget uri: " + appWidgetId, t); 125d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin } 126d6db8eab6df048b9065834113a6d46a885af01d3Owen Lin } 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return views; 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onDeleted(Context context, int[] appWidgetIds) { 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Clean deleted photos out of our database 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin WidgetDatabaseHelper helper = new WidgetDatabaseHelper(context); 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int appWidgetId : appWidgetIds) { 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin helper.deleteEntry(appWidgetId); 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin helper.close(); 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 13940234dd934d0dac0a65c896d9d287d58bc10b198Hung-ying Tyan} 140