1 /* 2 * Copyright (C) 2010 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.annotation.TargetApi; 20 import android.app.PendingIntent; 21 import android.appwidget.AppWidgetManager; 22 import android.appwidget.AppWidgetProvider; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.graphics.Bitmap; 26 import android.graphics.BitmapFactory; 27 import android.net.Uri; 28 import android.util.Log; 29 import android.widget.RemoteViews; 30 31 import com.android.gallery3d.R; 32 import com.android.gallery3d.common.ApiHelper; 33 import com.android.gallery3d.gadget.WidgetDatabaseHelper.Entry; 34 import com.android.gallery3d.onetimeinitializer.GalleryWidgetMigrator; 35 36 public class PhotoAppWidgetProvider extends AppWidgetProvider { 37 38 private static final String TAG = "WidgetProvider"; 39 buildWidget(Context context, int id, Entry entry)40 static RemoteViews buildWidget(Context context, int id, Entry entry) { 41 42 switch (entry.type) { 43 case WidgetDatabaseHelper.TYPE_ALBUM: 44 case WidgetDatabaseHelper.TYPE_SHUFFLE: 45 return buildStackWidget(context, id, entry); 46 case WidgetDatabaseHelper.TYPE_SINGLE_PHOTO: 47 return buildFrameWidget(context, id, entry); 48 } 49 throw new RuntimeException("invalid type - " + entry.type); 50 } 51 52 @Override onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)53 public void onUpdate(Context context, 54 AppWidgetManager appWidgetManager, int[] appWidgetIds) { 55 56 if (ApiHelper.HAS_REMOTE_VIEWS_SERVICE) { 57 // migrate gallery widgets from pre-JB releases to JB due to bucket ID change 58 GalleryWidgetMigrator.migrateGalleryWidgets(context); 59 } 60 61 WidgetDatabaseHelper helper = new WidgetDatabaseHelper(context); 62 try { 63 for (int id : appWidgetIds) { 64 Entry entry = helper.getEntry(id); 65 if (entry != null) { 66 RemoteViews views = buildWidget(context, id, entry); 67 appWidgetManager.updateAppWidget(id, views); 68 } else { 69 Log.e(TAG, "cannot load widget: " + id); 70 } 71 } 72 } finally { 73 helper.close(); 74 } 75 super.onUpdate(context, appWidgetManager, appWidgetIds); 76 } 77 78 @SuppressWarnings("deprecation") 79 @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) buildStackWidget(Context context, int widgetId, Entry entry)80 private static RemoteViews buildStackWidget(Context context, int widgetId, Entry entry) { 81 RemoteViews views = new RemoteViews( 82 context.getPackageName(), R.layout.appwidget_main); 83 84 Intent intent = new Intent(context, WidgetService.class); 85 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); 86 intent.putExtra(WidgetService.EXTRA_WIDGET_TYPE, entry.type); 87 intent.putExtra(WidgetService.EXTRA_ALBUM_PATH, entry.albumPath); 88 intent.setData(Uri.parse("widget://gallery/" + widgetId)); 89 90 // We use the deprecated API for backward compatibility 91 // The new API is available in ICE_CREAM_SANDWICH (15) 92 views.setRemoteAdapter(widgetId, R.id.appwidget_stack_view, intent); 93 94 views.setEmptyView(R.id.appwidget_stack_view, R.id.appwidget_empty_view); 95 96 Intent clickIntent = new Intent(context, WidgetClickHandler.class); 97 PendingIntent pendingIntent = PendingIntent.getActivity( 98 context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT); 99 views.setPendingIntentTemplate(R.id.appwidget_stack_view, pendingIntent); 100 101 return views; 102 } 103 buildFrameWidget(Context context, int appWidgetId, Entry entry)104 static RemoteViews buildFrameWidget(Context context, int appWidgetId, Entry entry) { 105 RemoteViews views = new RemoteViews( 106 context.getPackageName(), R.layout.photo_frame); 107 try { 108 byte[] data = entry.imageData; 109 Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); 110 views.setImageViewBitmap(R.id.photo, bitmap); 111 } catch (Throwable t) { 112 Log.w(TAG, "cannot load widget image: " + appWidgetId, t); 113 } 114 115 if (entry.imageUri != null) { 116 try { 117 Uri uri = Uri.parse(entry.imageUri); 118 Intent clickIntent = new Intent(context, WidgetClickHandler.class) 119 .setData(uri); 120 PendingIntent pendingClickIntent = PendingIntent.getActivity(context, 0, 121 clickIntent, PendingIntent.FLAG_CANCEL_CURRENT); 122 views.setOnClickPendingIntent(R.id.photo, pendingClickIntent); 123 } catch (Throwable t) { 124 Log.w(TAG, "cannot load widget uri: " + appWidgetId, t); 125 } 126 } 127 return views; 128 } 129 130 @Override onDeleted(Context context, int[] appWidgetIds)131 public void onDeleted(Context context, int[] appWidgetIds) { 132 // Clean deleted photos out of our database 133 WidgetDatabaseHelper helper = new WidgetDatabaseHelper(context); 134 for (int appWidgetId : appWidgetIds) { 135 helper.deleteEntry(appWidgetId); 136 } 137 helper.close(); 138 } 139 } 140