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