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
17package com.android.gallery3d.gadget;
18
19import android.annotation.TargetApi;
20import android.app.PendingIntent;
21import android.appwidget.AppWidgetManager;
22import android.appwidget.AppWidgetProvider;
23import android.content.Context;
24import android.content.Intent;
25import android.graphics.Bitmap;
26import android.graphics.BitmapFactory;
27import android.net.Uri;
28import android.util.Log;
29import android.widget.RemoteViews;
30
31import com.android.gallery3d.R;
32import com.android.gallery3d.common.ApiHelper;
33import com.android.gallery3d.gadget.WidgetDatabaseHelper.Entry;
34import com.android.gallery3d.onetimeinitializer.GalleryWidgetMigrator;
35
36public class PhotoAppWidgetProvider extends AppWidgetProvider {
37
38    private static final String TAG = "WidgetProvider";
39
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
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)
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
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
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