Load real data into the 1x1 Today widget, moving our work to an IntentService
This commit is contained in:
@@ -116,10 +116,12 @@
|
|||||||
android:label="@string/title_widget_today" >
|
android:label="@string/title_widget_today" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
<action android:name="com.example.android.sunshine.app.ACTION_DATA_UPDATED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="android.appwidget.provider"
|
<meta-data android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_info_today" />
|
android:resource="@xml/widget_info_today" />
|
||||||
</receiver>
|
</receiver>
|
||||||
|
<service android:name=".widget.TodayWidgetIntentService" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ import java.util.concurrent.ExecutionException;
|
|||||||
|
|
||||||
public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter {
|
public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||||
public final String LOG_TAG = SunshineSyncAdapter.class.getSimpleName();
|
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.
|
// Interval at which to sync with the weather, in seconds.
|
||||||
// 60 seconds (1 minute) * 180 = 3 hours
|
// 60 seconds (1 minute) * 180 = 3 hours
|
||||||
public static final int SYNC_INTERVAL = 60 * 180;
|
public static final int SYNC_INTERVAL = 60 * 180;
|
||||||
@@ -338,6 +340,7 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
WeatherContract.WeatherEntry.COLUMN_DATE + " <= ?",
|
WeatherContract.WeatherEntry.COLUMN_DATE + " <= ?",
|
||||||
new String[] {Long.toString(dayTime.setJulianDay(julianStartDay-1))});
|
new String[] {Long.toString(dayTime.setJulianDay(julianStartDay-1))});
|
||||||
|
|
||||||
|
updateWidgets();
|
||||||
notifyWeather();
|
notifyWeather();
|
||||||
}
|
}
|
||||||
Log.d(LOG_TAG, "Sync Complete. " + cVVector.size() + " Inserted");
|
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() {
|
private void notifyWeather() {
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
//checking the last update and notify if it' the first of the day
|
//checking the last update and notify if it' the first of the day
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,55 +15,39 @@
|
|||||||
*/
|
*/
|
||||||
package com.example.android.sunshine.app.widget;
|
package com.example.android.sunshine.app.widget;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.appwidget.AppWidgetManager;
|
import android.appwidget.AppWidgetManager;
|
||||||
import android.appwidget.AppWidgetProvider;
|
import android.appwidget.AppWidgetProvider;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Bundle;
|
||||||
import android.widget.RemoteViews;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import com.example.android.sunshine.app.MainActivity;
|
import com.example.android.sunshine.app.sync.SunshineSyncAdapter;
|
||||||
import com.example.android.sunshine.app.R;
|
|
||||||
import com.example.android.sunshine.app.Utility;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider for a widget showing today's weather.
|
* 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 {
|
public class TodayWidgetProvider extends AppWidgetProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||||
int weatherArtResourceId = R.drawable.art_clear;
|
context.startService(new Intent(context, TodayWidgetIntentService.class));
|
||||||
String description = "Clear";
|
}
|
||||||
double maxTemp = 24;
|
|
||||||
String formattedMaxTemperature = Utility.formatTemperature(context, maxTemp);
|
|
||||||
|
|
||||||
// Perform this loop procedure for each Today widget
|
@Override
|
||||||
for (int appWidgetId : appWidgetIds) {
|
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
|
||||||
int layoutId = R.layout.widget_today_small;
|
int appWidgetId, Bundle newOptions) {
|
||||||
RemoteViews views = new RemoteViews(context.getPackageName(), layoutId);
|
context.startService(new Intent(context, TodayWidgetIntentService.class));
|
||||||
|
}
|
||||||
|
|
||||||
// Add the data to the RemoteViews
|
@Override
|
||||||
views.setImageViewResource(R.id.widget_icon, weatherArtResourceId);
|
public void onReceive(@NonNull Context context, @NonNull Intent intent) {
|
||||||
// Content Descriptions for RemoteViews were only added in ICS MR1
|
super.onReceive(context, intent);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
if (SunshineSyncAdapter.ACTION_DATA_UPDATED.equals(intent.getAction())) {
|
||||||
setRemoteContentDescription(views, description);
|
context.startService(new Intent(context, TodayWidgetIntentService.class));
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
|
|
||||||
private void setRemoteContentDescription(RemoteViews views, String description) {
|
|
||||||
views.setContentDescription(R.id.widget_icon, description);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user