Load real data into the 1x1 Today widget, moving our work to an IntentService

This commit is contained in:
Dan Galpin
2015-05-25 04:13:31 -07:00
parent 3ce8bff71c
commit 7ec7108247
4 changed files with 140 additions and 35 deletions

View File

@@ -116,10 +116,12 @@
android:label="@string/title_widget_today" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.example.android.sunshine.app.ACTION_DATA_UPDATED" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget_info_today" />
</receiver>
<service android:name=".widget.TodayWidgetIntentService" />
</application>
</manifest>

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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);
// 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);
// 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);
}
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);
@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, Bundle newOptions) {
context.startService(new Intent(context, TodayWidgetIntentService.class));
}
@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));
}
}
}