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