PageRenderTime 11ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

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

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