diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4659c95..d41a398 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -116,10 +116,12 @@
android:label="@string/title_widget_today" >
+
+
diff --git a/app/src/main/java/com/example/android/sunshine/app/sync/SunshineSyncAdapter.java b/app/src/main/java/com/example/android/sunshine/app/sync/SunshineSyncAdapter.java
index e248235..c9275d0 100644
--- a/app/src/main/java/com/example/android/sunshine/app/sync/SunshineSyncAdapter.java
+++ b/app/src/main/java/com/example/android/sunshine/app/sync/SunshineSyncAdapter.java
@@ -52,6 +52,8 @@ import java.util.concurrent.ExecutionException;
public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter {
public final String LOG_TAG = SunshineSyncAdapter.class.getSimpleName();
+ public static final String ACTION_DATA_UPDATED =
+ "com.example.android.sunshine.app.ACTION_DATA_UPDATED";
// Interval at which to sync with the weather, in seconds.
// 60 seconds (1 minute) * 180 = 3 hours
public static final int SYNC_INTERVAL = 60 * 180;
@@ -338,6 +340,7 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter {
WeatherContract.WeatherEntry.COLUMN_DATE + " <= ?",
new String[] {Long.toString(dayTime.setJulianDay(julianStartDay-1))});
+ updateWidgets();
notifyWeather();
}
Log.d(LOG_TAG, "Sync Complete. " + cVVector.size() + " Inserted");
@@ -350,6 +353,14 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter {
}
}
+ private void updateWidgets() {
+ Context context = getContext();
+ // Setting the package ensures that only components in our app will receive the broadcast
+ Intent dataUpdatedIntent = new Intent(ACTION_DATA_UPDATED)
+ .setPackage(context.getPackageName());
+ context.sendBroadcast(dataUpdatedIntent);
+ }
+
private void notifyWeather() {
Context context = getContext();
//checking the last update and notify if it' the first of the day
diff --git a/app/src/main/java/com/example/android/sunshine/app/widget/TodayWidgetIntentService.java b/app/src/main/java/com/example/android/sunshine/app/widget/TodayWidgetIntentService.java
new file mode 100644
index 0000000..c07739a
--- /dev/null
+++ b/app/src/main/java/com/example/android/sunshine/app/widget/TodayWidgetIntentService.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.sunshine.app.widget;
+
+import android.annotation.TargetApi;
+import android.app.IntentService;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.widget.RemoteViews;
+
+import com.example.android.sunshine.app.MainActivity;
+import com.example.android.sunshine.app.R;
+import com.example.android.sunshine.app.Utility;
+import com.example.android.sunshine.app.data.WeatherContract;
+
+/**
+ * IntentService which handles updating all Today widgets with the latest data
+ */
+public class TodayWidgetIntentService extends IntentService {
+ private static final String[] FORECAST_COLUMNS = {
+ WeatherContract.WeatherEntry.COLUMN_WEATHER_ID,
+ WeatherContract.WeatherEntry.COLUMN_SHORT_DESC,
+ WeatherContract.WeatherEntry.COLUMN_MAX_TEMP
+ };
+ // these indices must match the projection
+ private static final int INDEX_WEATHER_ID = 0;
+ private static final int INDEX_SHORT_DESC = 1;
+ private static final int INDEX_MAX_TEMP = 2;
+
+ public TodayWidgetIntentService() {
+ super("TodayWidgetIntentService");
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ // Retrieve all of the Today widget ids: these are the widgets we need to update
+ AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
+ int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(this,
+ TodayWidgetProvider.class));
+
+ // Get today's data from the ContentProvider
+ String location = Utility.getPreferredLocation(this);
+ Uri weatherForLocationUri = WeatherContract.WeatherEntry.buildWeatherLocationWithStartDate(
+ location, System.currentTimeMillis());
+ Cursor data = getContentResolver().query(weatherForLocationUri, FORECAST_COLUMNS, null,
+ null, WeatherContract.WeatherEntry.COLUMN_DATE + " ASC");
+ if (data == null) {
+ return;
+ }
+ if (!data.moveToFirst()) {
+ data.close();
+ return;
+ }
+
+ // Extract the weather data from the Cursor
+ int weatherId = data.getInt(INDEX_WEATHER_ID);
+ int weatherArtResourceId = Utility.getArtResourceForWeatherCondition(weatherId);
+ String description = data.getString(INDEX_SHORT_DESC);
+ double maxTemp = data.getDouble(INDEX_MAX_TEMP);
+ String formattedMaxTemperature = Utility.formatTemperature(this, maxTemp);
+ data.close();
+
+ // Perform this loop procedure for each Today widget
+ for (int appWidgetId : appWidgetIds) {
+ int layoutId = R.layout.widget_today_small;
+ RemoteViews views = new RemoteViews(getPackageName(), layoutId);
+
+ // Add the data to the RemoteViews
+ views.setImageViewResource(R.id.widget_icon, weatherArtResourceId);
+ // Content Descriptions for RemoteViews were only added in ICS MR1
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
+ setRemoteContentDescription(views, description);
+ }
+ views.setTextViewText(R.id.widget_high_temperature, formattedMaxTemperature);
+
+ // Create an Intent to launch MainActivity
+ Intent launchIntent = new Intent(this, MainActivity.class);
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, launchIntent, 0);
+ views.setOnClickPendingIntent(R.id.widget, pendingIntent);
+
+ // Tell the AppWidgetManager to perform an update on the current app widget
+ appWidgetManager.updateAppWidget(appWidgetId, views);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
+ private void setRemoteContentDescription(RemoteViews views, String description) {
+ views.setContentDescription(R.id.widget_icon, description);
+ }
+}
diff --git a/app/src/main/java/com/example/android/sunshine/app/widget/TodayWidgetProvider.java b/app/src/main/java/com/example/android/sunshine/app/widget/TodayWidgetProvider.java
index 04ef261..ee74909 100644
--- a/app/src/main/java/com/example/android/sunshine/app/widget/TodayWidgetProvider.java
+++ b/app/src/main/java/com/example/android/sunshine/app/widget/TodayWidgetProvider.java
@@ -15,55 +15,39 @@
*/
package com.example.android.sunshine.app.widget;
-import android.annotation.TargetApi;
-import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
-import android.os.Build;
-import android.widget.RemoteViews;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
-import com.example.android.sunshine.app.MainActivity;
-import com.example.android.sunshine.app.R;
-import com.example.android.sunshine.app.Utility;
+import com.example.android.sunshine.app.sync.SunshineSyncAdapter;
/**
* Provider for a widget showing today's weather.
+ *
+ * Delegates widget updating to {@link TodayWidgetIntentService} to ensure that
+ * data retrieval is done on a background thread
*/
public class TodayWidgetProvider extends AppWidgetProvider {
+ @Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
- int weatherArtResourceId = R.drawable.art_clear;
- String description = "Clear";
- double maxTemp = 24;
- String formattedMaxTemperature = Utility.formatTemperature(context, maxTemp);
+ context.startService(new Intent(context, TodayWidgetIntentService.class));
+ }
- // Perform this loop procedure for each Today widget
- for (int appWidgetId : appWidgetIds) {
- int layoutId = R.layout.widget_today_small;
- RemoteViews views = new RemoteViews(context.getPackageName(), layoutId);
+ @Override
+ public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
+ int appWidgetId, Bundle newOptions) {
+ context.startService(new Intent(context, TodayWidgetIntentService.class));
+ }
- // Add the data to the RemoteViews
- views.setImageViewResource(R.id.widget_icon, weatherArtResourceId);
- // Content Descriptions for RemoteViews were only added in ICS MR1
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
- setRemoteContentDescription(views, description);
- }
- views.setTextViewText(R.id.widget_high_temperature, formattedMaxTemperature);
-
- // Create an Intent to launch MainActivity
- Intent launchIntent = new Intent(context, MainActivity.class);
- PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, launchIntent, 0);
- views.setOnClickPendingIntent(R.id.widget, pendingIntent);
-
- // Tell the AppWidgetManager to perform an update on the current app widget
- appWidgetManager.updateAppWidget(appWidgetId, views);
+ @Override
+ public void onReceive(@NonNull Context context, @NonNull Intent intent) {
+ super.onReceive(context, intent);
+ if (SunshineSyncAdapter.ACTION_DATA_UPDATED.equals(intent.getAction())) {
+ context.startService(new Intent(context, TodayWidgetIntentService.class));
}
}
-
- @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
- private void setRemoteContentDescription(RemoteViews views, String description) {
- views.setContentDescription(R.id.widget_icon, description);
- }
}