PageRenderTime 27ms CodeModel.GetById 17ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/Sky/src/org/jsharkey/sky/TinyAppWidget.java

http://android-sky.googlecode.com/
Java | 169 lines | 107 code | 27 blank | 35 comment | 19 complexity | 606031f570a7c8763f68ce74ca0c851f MD5 | raw file
  1/*
  2 * Copyright (C) 2009 Jeff Sharkey, http://jsharkey.org/
  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 org.jsharkey.sky;
 18
 19import org.jsharkey.sky.ForecastProvider.AppWidgets;
 20import org.jsharkey.sky.ForecastProvider.AppWidgetsColumns;
 21import org.jsharkey.sky.ForecastProvider.ForecastsColumns;
 22
 23import android.app.PendingIntent;
 24import android.appwidget.AppWidgetManager;
 25import android.appwidget.AppWidgetProvider;
 26import android.content.ComponentName;
 27import android.content.ContentResolver;
 28import android.content.ContentUris;
 29import android.content.Context;
 30import android.content.Intent;
 31import android.content.res.Resources;
 32import android.database.Cursor;
 33import android.net.Uri;
 34import android.util.Log;
 35import android.view.View;
 36import android.widget.RemoteViews;
 37
 38/**
 39 * Definition of a tiny-sized forecast widget. Passes any requested updates to
 40 * {@link UpdateService} to perform on background thread and prevent ANR.
 41 */
 42public class TinyAppWidget extends AppWidgetProvider {
 43    private static final String TAG = "TinyAppWidget";
 44
 45    private static final String[] PROJECTION_APPWIDGETS = new String[] {
 46        AppWidgetsColumns.UNITS,
 47    };
 48
 49    private static final int COL_UNITS = 0;
 50
 51    private static final String[] PROJECTION_FORECASTS = new String[] {
 52        ForecastsColumns.CONDITIONS,
 53        ForecastsColumns.TEMP_HIGH,
 54        ForecastsColumns.TEMP_LOW,
 55    };
 56
 57    private static final int COL_CONDITIONS = 0;
 58    private static final int COL_TEMP_HIGH = 1;
 59    private static final int COL_TEMP_LOW = 2;
 60
 61    /**
 62     * {@inheritDoc}
 63     */
 64    @Override
 65    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
 66        // If no specific widgets requested, collect list of all
 67        if (appWidgetIds == null) {
 68            appWidgetIds = appWidgetManager.getAppWidgetIds(
 69                    new ComponentName(context, TinyAppWidget.class));
 70        }
 71
 72        // Request update for these widgets and launch updater service
 73        UpdateService.requestUpdate(appWidgetIds);
 74        context.startService(new Intent(context, UpdateService.class));
 75    }
 76
 77    /**
 78     * {@inheritDoc}
 79     */
 80    @Override
 81    public void onDeleted(Context context, int[] appWidgetIds) {
 82        ContentResolver resolver = context.getContentResolver();
 83        for (int appWidgetId : appWidgetIds) {
 84            Log.d(TAG, "Deleting appWidgetId=" + appWidgetId);
 85            Uri appWidgetUri = ContentUris.withAppendedId(AppWidgets.CONTENT_URI, appWidgetId);
 86            resolver.delete(appWidgetUri, null, null);
 87        }
 88    }
 89
 90    /**
 91     * Build an update for the given tiny widget. Should only be called from a
 92     * service or thread to prevent ANR during database queries.
 93     */
 94    public static RemoteViews buildUpdate(Context context, Uri appWidgetUri) {
 95        Log.d(TAG, "Building tiny widget update");
 96
 97        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_tiny);
 98
 99        boolean daytime = ForecastUtils.isDaytime();
100        boolean forecastFilled = false;
101
102        ContentResolver resolver = context.getContentResolver();
103        Resources res = context.getResources();
104
105        Cursor cursor = null;
106        int tempUnits = AppWidgetsColumns.UNITS_FAHRENHEIT;
107
108        // Pull out desired temperature units
109        try {
110            cursor = resolver.query(appWidgetUri, PROJECTION_APPWIDGETS, null, null, null);
111            if (cursor != null && cursor.moveToFirst()) {
112                tempUnits = cursor.getInt(COL_UNITS);
113            }
114        } finally {
115            if (cursor != null) {
116                cursor.close();
117            }
118        }
119
120        // Find the forecast nearest now and build update using it
121        try {
122            Uri forecastAtUri = Uri.withAppendedPath(appWidgetUri, AppWidgets.TWIG_FORECAST_AT);
123            Uri forecastAtNowUri = Uri.withAppendedPath(forecastAtUri,
124                    Long.toString(System.currentTimeMillis()));
125            cursor = resolver.query(forecastAtNowUri, PROJECTION_FORECASTS, null, null, null);
126            if (cursor != null && cursor.moveToFirst()) {
127
128                String conditions = cursor.getString(COL_CONDITIONS);
129                int iconResource = ForecastUtils.getIconForForecast(conditions, daytime);
130                int tempHigh = cursor.getInt(COL_TEMP_HIGH);
131                int tempLow = cursor.getInt(COL_TEMP_LOW);
132
133                views.setImageViewResource(R.id.icon, iconResource);
134
135                if (tempHigh == Integer.MIN_VALUE || tempLow == Integer.MIN_VALUE) {
136                    views.setViewVisibility(R.id.temp_block, View.GONE);
137                } else {
138                    views.setViewVisibility(R.id.temp_block, View.VISIBLE);
139                    views.setTextViewText(R.id.high,
140                            ForecastUtils.formatTemp(res, tempHigh, tempUnits));
141                    views.setTextViewText(R.id.low,
142                            ForecastUtils.formatTemp(res, tempLow, tempUnits));
143                }
144
145                forecastFilled = true;
146            }
147        } finally {
148            if (cursor != null) {
149                cursor.close();
150            }
151        }
152
153        // If not filled correctly, show error message and hide other fields
154        if (!forecastFilled) {
155            views = new RemoteViews(context.getPackageName(), R.layout.widget_loading);
156            views.setTextViewText(R.id.loading, res.getString(R.string.widget_error));
157        }
158
159        // Connect click intent to launch details
160        Intent detailIntent = new Intent(context, DetailsActivity.class);
161        detailIntent.setData(appWidgetUri);
162
163        PendingIntent pending = PendingIntent.getActivity(context, 0, detailIntent, 0);
164
165        views.setOnClickPendingIntent(R.id.widget, pending);
166
167        return views;
168    }
169}