From 7ec710824728676726f72c85082da8611eca7433 Mon Sep 17 00:00:00 2001 From: Dan Galpin Date: Mon, 25 May 2015 04:13:31 -0700 Subject: [PATCH 01/13] Load real data into the 1x1 Today widget, moving our work to an IntentService --- app/src/main/AndroidManifest.xml | 2 + .../app/sync/SunshineSyncAdapter.java | 11 ++ .../app/widget/TodayWidgetIntentService.java | 108 ++++++++++++++++++ .../app/widget/TodayWidgetProvider.java | 54 +++------ 4 files changed, 140 insertions(+), 35 deletions(-) create mode 100644 app/src/main/java/com/example/android/sunshine/app/widget/TodayWidgetIntentService.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4659c958..d41a3984 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 e2482357..c9275d0e 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 @@ 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 @@ private void getWeatherDataFromJson(String forecastJsonStr, 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 @@ private void getWeatherDataFromJson(String forecastJsonStr, } } + 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 00000000..c07739a3 --- /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 04ef261b..ee749096 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); - - // 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); + context.startService(new Intent(context, TodayWidgetIntentService.class)); + } - // Tell the AppWidgetManager to perform an update on the current app widget - appWidgetManager.updateAppWidget(appWidgetId, views); - } + @Override + public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, + int appWidgetId, Bundle newOptions) { + 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 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)); + } } } From 5628b0b2a42b934f01c617e7409217a42f9d1275 Mon Sep 17 00:00:00 2001 From: Dan Galpin Date: Mon, 25 May 2015 04:55:41 -0700 Subject: [PATCH 02/13] Allow the Today widget to resize horizontally, change the default size to 2x1 --- .../app/widget/TodayWidgetIntentService.java | 47 +++++++++- .../app/widget/TodayWidgetProvider.java | 2 +- .../drawable-nodpi/widget_preview_today.png | Bin 0 -> 19003 bytes app/src/main/res/layout/widget_today.xml | 66 ++++++++++++++ .../main/res/layout/widget_today_large.xml | 82 ++++++++++++++++++ app/src/main/res/values/dimens.xml | 5 +- app/src/main/res/xml/widget_info_today.xml | 10 ++- 7 files changed, 206 insertions(+), 6 deletions(-) create mode 100644 app/src/main/res/drawable-nodpi/widget_preview_today.png create mode 100644 app/src/main/res/layout/widget_today.xml create mode 100644 app/src/main/res/layout/widget_today_large.xml 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 index c07739a3..0ab88541 100644 --- 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 @@ -24,6 +24,9 @@ import android.database.Cursor; import android.net.Uri; import android.os.Build; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.util.TypedValue; import android.widget.RemoteViews; import com.example.android.sunshine.app.MainActivity; @@ -38,12 +41,14 @@ 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 + WeatherContract.WeatherEntry.COLUMN_MAX_TEMP, + WeatherContract.WeatherEntry.COLUMN_MIN_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; + private static final int INDEX_MIN_TEMP = 3; public TodayWidgetIntentService() { super("TodayWidgetIntentService"); @@ -75,12 +80,25 @@ protected void onHandleIntent(Intent intent) { int weatherArtResourceId = Utility.getArtResourceForWeatherCondition(weatherId); String description = data.getString(INDEX_SHORT_DESC); double maxTemp = data.getDouble(INDEX_MAX_TEMP); + double minTemp = data.getDouble(INDEX_MIN_TEMP); String formattedMaxTemperature = Utility.formatTemperature(this, maxTemp); + String formattedMinTemperature = Utility.formatTemperature(this, minTemp); data.close(); // Perform this loop procedure for each Today widget for (int appWidgetId : appWidgetIds) { - int layoutId = R.layout.widget_today_small; + // Find the correct layout based on the widget's width + int widgetWidth = getWidgetWidth(appWidgetManager, appWidgetId); + int defaultWidth = getResources().getDimensionPixelSize(R.dimen.widget_today_default_width); + int largeWidth = getResources().getDimensionPixelSize(R.dimen.widget_today_large_width); + int layoutId; + if (widgetWidth >= largeWidth) { + layoutId = R.layout.widget_today_large; + } else if (widgetWidth >= defaultWidth) { + layoutId = R.layout.widget_today; + } else { + layoutId = R.layout.widget_today_small; + } RemoteViews views = new RemoteViews(getPackageName(), layoutId); // Add the data to the RemoteViews @@ -89,7 +107,9 @@ protected void onHandleIntent(Intent intent) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { setRemoteContentDescription(views, description); } + views.setTextViewText(R.id.widget_description, description); views.setTextViewText(R.id.widget_high_temperature, formattedMaxTemperature); + views.setTextViewText(R.id.widget_low_temperature, formattedMinTemperature); // Create an Intent to launch MainActivity Intent launchIntent = new Intent(this, MainActivity.class); @@ -101,6 +121,29 @@ protected void onHandleIntent(Intent intent) { } } + private int getWidgetWidth(AppWidgetManager appWidgetManager, int appWidgetId) { + // Prior to Jelly Bean, widgets were always their default size + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { + return getResources().getDimensionPixelSize(R.dimen.widget_today_default_width); + } + // For Jelly Bean and higher devices, widgets can be resized - the current size can be + // retrieved from the newly added App Widget Options + return getWidgetWidthFromOptions(appWidgetManager, appWidgetId); + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + private int getWidgetWidthFromOptions(AppWidgetManager appWidgetManager, int appWidgetId) { + Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId); + if (options.containsKey(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)) { + int minWidthDp = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH); + // The width returned is in dp, but we'll convert it to pixels to match the other widths + DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, minWidthDp, + displayMetrics); + } + return getResources().getDimensionPixelSize(R.dimen.widget_today_default_width); + } + @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 ee749096..81c1dfe6 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 @@ -25,7 +25,7 @@ import com.example.android.sunshine.app.sync.SunshineSyncAdapter; /** - * Provider for a widget showing today's weather. + * Provider for a horizontally expandable widget showing today's weather. * * Delegates widget updating to {@link TodayWidgetIntentService} to ensure that * data retrieval is done on a background thread diff --git a/app/src/main/res/drawable-nodpi/widget_preview_today.png b/app/src/main/res/drawable-nodpi/widget_preview_today.png new file mode 100644 index 0000000000000000000000000000000000000000..7be01f0d3e30ba8db9e6e57434098b996bc35282 GIT binary patch literal 19003 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 z

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 RJ>Y3j44$rjF6*2UngB*X>}vo3 literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/widget_today.xml b/app/src/main/res/layout/widget_today.xml new file mode 100644 index 00000000..caf01ed0 --- /dev/null +++ b/app/src/main/res/layout/widget_today.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/widget_today_large.xml b/app/src/main/res/layout/widget_today_large.xml new file mode 100644 index 00000000..3838aafd --- /dev/null +++ b/app/src/main/res/layout/widget_today_large.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 12b07d17..1c7cbb21 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -54,6 +54,9 @@ 360dp - 40dp + 110dp 40dp + 40dp + @dimen/widget_today_default_height + 220dp diff --git a/app/src/main/res/xml/widget_info_today.xml b/app/src/main/res/xml/widget_info_today.xml index 9812f0b5..c36d5643 100644 --- a/app/src/main/res/xml/widget_info_today.xml +++ b/app/src/main/res/xml/widget_info_today.xml @@ -14,7 +14,13 @@ limitations under the License. --> \ No newline at end of file + android:previewImage="@drawable/widget_preview_today" + android:resizeMode="horizontal" + android:updatePeriodMillis="0" + tools:ignore="UnusedAttribute" /> From 52efa534a292e1741d455dc252123fd374162cf6 Mon Sep 17 00:00:00 2001 From: Dan Galpin Date: Mon, 25 May 2015 05:54:56 -0700 Subject: [PATCH 03/13] Integrate Detail widget, showing a full list of weather information and allowing clicking through to individual days --- app/src/main/AndroidManifest.xml | 17 ++ .../android/sunshine/app/ForecastAdapter.java | 5 +- .../sunshine/app/ForecastFragment.java | 50 ++--- .../android/sunshine/app/MainActivity.java | 14 +- .../example/android/sunshine/app/Utility.java | 4 +- .../app/widget/DetailWidgetProvider.java | 89 +++++++++ .../DetailWidgetRemoteViewsService.java | 175 ++++++++++++++++++ .../drawable-nodpi/widget_preview_detail.png | Bin 0 -> 101100 bytes app/src/main/res/layout/widget_detail.xml | 58 ++++++ .../res/layout/widget_detail_list_item.xml | 93 ++++++++++ app/src/main/res/values-sw600dp/bools.xml | 4 + app/src/main/res/values-v11/bools.xml | 4 + app/src/main/res/values/bools.xml | 5 + app/src/main/res/values/dimens.xml | 15 ++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/widget_info_detail.xml | 29 +++ 16 files changed, 535 insertions(+), 28 deletions(-) create mode 100644 app/src/main/java/com/example/android/sunshine/app/widget/DetailWidgetProvider.java create mode 100644 app/src/main/java/com/example/android/sunshine/app/widget/DetailWidgetRemoteViewsService.java create mode 100644 app/src/main/res/drawable-nodpi/widget_preview_detail.png create mode 100644 app/src/main/res/layout/widget_detail.xml create mode 100644 app/src/main/res/layout/widget_detail_list_item.xml create mode 100644 app/src/main/res/values-sw600dp/bools.xml create mode 100644 app/src/main/res/values-v11/bools.xml create mode 100644 app/src/main/res/values/bools.xml create mode 100644 app/src/main/res/xml/widget_info_detail.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d41a3984..925588ff 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -122,6 +122,23 @@ android:resource="@xml/widget_info_today" /> + + + + + + + + + diff --git a/app/src/main/java/com/example/android/sunshine/app/ForecastAdapter.java b/app/src/main/java/com/example/android/sunshine/app/ForecastAdapter.java index 7c8b3705..8bcb4b93 100644 --- a/app/src/main/java/com/example/android/sunshine/app/ForecastAdapter.java +++ b/app/src/main/java/com/example/android/sunshine/app/ForecastAdapter.java @@ -127,13 +127,16 @@ public void onBindViewHolder(ForecastAdapterViewHolder forecastAdapterViewHolder mCursor.moveToPosition(position); int weatherId = mCursor.getInt(ForecastFragment.COL_WEATHER_CONDITION_ID); int defaultImage; + boolean useLongToday; switch (getItemViewType(position)) { case VIEW_TYPE_TODAY: defaultImage = Utility.getArtResourceForWeatherCondition(weatherId); + useLongToday = true; break; default: defaultImage = Utility.getIconResourceForWeatherCondition(weatherId); + useLongToday = false; } if ( Utility.usingLocalGraphics(mContext) ) { @@ -154,7 +157,7 @@ public void onBindViewHolder(ForecastAdapterViewHolder forecastAdapterViewHolder long dateInMillis = mCursor.getLong(ForecastFragment.COL_WEATHER_DATE); // Find TextView and set formatted date on it - forecastAdapterViewHolder.mDateView.setText(Utility.getFriendlyDayString(mContext, dateInMillis)); + forecastAdapterViewHolder.mDateView.setText(Utility.getFriendlyDayString(mContext, dateInMillis, useLongToday)); // Read weather forecast from cursor String description = Utility.getStringForWeatherCondition(mContext, weatherId); diff --git a/app/src/main/java/com/example/android/sunshine/app/ForecastFragment.java b/app/src/main/java/com/example/android/sunshine/app/ForecastFragment.java index 13ed1d2b..2c4537e3 100644 --- a/app/src/main/java/com/example/android/sunshine/app/ForecastFragment.java +++ b/app/src/main/java/com/example/android/sunshine/app/ForecastFragment.java @@ -26,7 +26,6 @@ import android.os.Bundle; import android.preference.PreferenceManager; import android.support.design.widget.AppBarLayout; -import android.support.design.widget.CoordinatorLayout; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; @@ -55,12 +54,11 @@ public class ForecastFragment extends Fragment implements LoaderManager.LoaderCallbacks, SharedPreferences.OnSharedPreferenceChangeListener { public static final String LOG_TAG = ForecastFragment.class.getSimpleName(); private ForecastAdapter mForecastAdapter; - private RecyclerView mRecyclerView; - private int mPosition = RecyclerView.NO_POSITION; private boolean mUseTodayLayout, mAutoSelectView; private int mChoiceMode; private boolean mHoldForTransition; + private long mInitialSelectedDate = -1; private static final String SELECTED_KEY = "selected_position"; @@ -196,7 +194,6 @@ public void onClick(Long date, ForecastAdapter.ForecastAdapterViewHolder vh) { locationSetting, date), vh ); - mPosition = vh.getAdapterPosition(); } }, emptyView, mChoiceMode); @@ -246,11 +243,6 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { // or magically appeared to take advantage of room, but data or place in the app was never // actually *lost*. if (savedInstanceState != null) { - if (savedInstanceState.containsKey(SELECTED_KEY)) { - // The Recycler View probably hasn't even been populated yet. Actually perform the - // swapout in onLoadFinished. - mPosition = savedInstanceState.getInt(SELECTED_KEY); - } mForecastAdapter.onRestoreInstanceState(savedInstanceState); } @@ -304,11 +296,6 @@ private void openPreferredLocationInMap() { @Override public void onSaveInstanceState(Bundle outState) { // When tablets rotate, the currently selected list item needs to be saved. - // When no item is selected, mPosition will be set to RecyclerView.NO_POSITION, - // so check for that before storing. - if (mPosition != RecyclerView.NO_POSITION) { - outState.putInt(SELECTED_KEY, mPosition); - } mForecastAdapter.onSaveInstanceState(outState); super.onSaveInstanceState(outState); } @@ -340,11 +327,6 @@ public Loader onCreateLoader(int i, Bundle bundle) { @Override public void onLoadFinished(Loader loader, Cursor data) { mForecastAdapter.swapCursor(data); - if (mPosition != RecyclerView.NO_POSITION) { - // If we don't need to restart the loader, and there's a desired position to restore - // to, do so now. - mRecyclerView.smoothScrollToPosition(mPosition); - } updateEmptyView(); if ( data.getCount() == 0 ) { getActivity().supportStartPostponedEnterTransition(); @@ -356,11 +338,27 @@ public boolean onPreDraw() { // we see Children. if (mRecyclerView.getChildCount() > 0) { mRecyclerView.getViewTreeObserver().removeOnPreDrawListener(this); - int itemPosition = mForecastAdapter.getSelectedItemPosition(); - if ( RecyclerView.NO_POSITION == itemPosition ) itemPosition = 0; - RecyclerView.ViewHolder vh = mRecyclerView.findViewHolderForAdapterPosition(itemPosition); - if ( null != vh && mAutoSelectView ) { - mForecastAdapter.selectView( vh ); + int position = mForecastAdapter.getSelectedItemPosition(); + if (position == RecyclerView.NO_POSITION && + -1 != mInitialSelectedDate) { + Cursor data = mForecastAdapter.getCursor(); + int count = data.getCount(); + int dateColumn = data.getColumnIndex(WeatherContract.WeatherEntry.COLUMN_DATE); + for ( int i = 0; i < count; i++ ) { + data.moveToPosition(i); + if ( data.getLong(dateColumn) == mInitialSelectedDate ) { + position = i; + break; + } + } + } + if (position == RecyclerView.NO_POSITION) position = 0; + // If we don't need to restart the loader, and there's a desired position to restore + // to, do so now. + mRecyclerView.smoothScrollToPosition(position); + RecyclerView.ViewHolder vh = mRecyclerView.findViewHolderForAdapterPosition(position); + if (null != vh && mAutoSelectView) { + mForecastAdapter.selectView(vh); } if ( mHoldForTransition ) { getActivity().supportStartPostponedEnterTransition(); @@ -396,6 +394,10 @@ public void setUseTodayLayout(boolean useTodayLayout) { } } + public void setInitialSelectedDate(long initialSelectedDate) { + mInitialSelectedDate = initialSelectedDate; + } + /* Updates the empty list view with contextually relevant information that the user can use to determine why they aren't seeing weather. diff --git a/app/src/main/java/com/example/android/sunshine/app/MainActivity.java b/app/src/main/java/com/example/android/sunshine/app/MainActivity.java index 6460c9e5..d90301c6 100644 --- a/app/src/main/java/com/example/android/sunshine/app/MainActivity.java +++ b/app/src/main/java/com/example/android/sunshine/app/MainActivity.java @@ -34,6 +34,7 @@ import android.view.MenuItem; import android.view.View; +import com.example.android.sunshine.app.data.WeatherContract; import com.example.android.sunshine.app.sync.SunshineSyncAdapter; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; @@ -63,6 +64,7 @@ public class MainActivity extends AppCompatActivity implements ForecastFragment. protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mLocation = Utility.getPreferredLocation(this); + Uri contentUri = getIntent() != null ? getIntent().getData() : null; setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar); @@ -78,8 +80,14 @@ protected void onCreate(Bundle savedInstanceState) { // adding or replacing the detail fragment using a // fragment transaction. if (savedInstanceState == null) { + DetailFragment fragment = new DetailFragment(); + if (contentUri != null) { + Bundle args = new Bundle(); + args.putParcelable(DetailFragment.DETAIL_URI, contentUri); + fragment.setArguments(args); + } getSupportFragmentManager().beginTransaction() - .replace(R.id.weather_detail_container, new DetailFragment(), DETAILFRAGMENT_TAG) + .replace(R.id.weather_detail_container, fragment, DETAILFRAGMENT_TAG) .commit(); } } else { @@ -90,6 +98,10 @@ protected void onCreate(Bundle savedInstanceState) { ForecastFragment forecastFragment = ((ForecastFragment)getSupportFragmentManager() .findFragmentById(R.id.fragment_forecast)); forecastFragment.setUseTodayLayout(!mTwoPane); + if (contentUri != null) { + forecastFragment.setInitialSelectedDate( + WeatherContract.WeatherEntry.getDateFromUri(contentUri)); + } SunshineSyncAdapter.initializeSyncAdapter(this); diff --git a/app/src/main/java/com/example/android/sunshine/app/Utility.java b/app/src/main/java/com/example/android/sunshine/app/Utility.java index 7e1dacbe..4368a376 100644 --- a/app/src/main/java/com/example/android/sunshine/app/Utility.java +++ b/app/src/main/java/com/example/android/sunshine/app/Utility.java @@ -72,7 +72,7 @@ static String formatDate(long dateInMilliseconds) { * @param dateInMillis The date in milliseconds * @return a user-friendly representation of the date. */ - public static String getFriendlyDayString(Context context, long dateInMillis) { + public static String getFriendlyDayString(Context context, long dateInMillis, boolean displayLongToday) { // The day string for forecast uses the following logic: // For today: "Today, June 8" // For tomorrow: "Tomorrow" @@ -87,7 +87,7 @@ public static String getFriendlyDayString(Context context, long dateInMillis) { // If the date we're building the String for is today's date, the format // is "Today, June 24" - if (julianDay == currentJulianDay) { + if (displayLongToday && julianDay == currentJulianDay) { String today = context.getString(R.string.today); int formatId = R.string.format_full_friendly_date; return String.format(context.getString( diff --git a/app/src/main/java/com/example/android/sunshine/app/widget/DetailWidgetProvider.java b/app/src/main/java/com/example/android/sunshine/app/widget/DetailWidgetProvider.java new file mode 100644 index 00000000..85896eba --- /dev/null +++ b/app/src/main/java/com/example/android/sunshine/app/widget/DetailWidgetProvider.java @@ -0,0 +1,89 @@ +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.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.v4.app.TaskStackBuilder; +import android.widget.RemoteViews; + +import com.example.android.sunshine.app.DetailActivity; +import com.example.android.sunshine.app.MainActivity; +import com.example.android.sunshine.app.R; +import com.example.android.sunshine.app.sync.SunshineSyncAdapter; + +/** + * Provider for a scrollable weather detail widget + */ +@TargetApi(Build.VERSION_CODES.HONEYCOMB) +public class DetailWidgetProvider extends AppWidgetProvider { + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // Perform this loop procedure for each App Widget that belongs to this provider + for (int appWidgetId : appWidgetIds) { + RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_detail); + + // Create an Intent to launch MainActivity + Intent intent = new Intent(context, MainActivity.class); + PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + views.setOnClickPendingIntent(R.id.widget, pendingIntent); + + // Set up the collection + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + setRemoteAdapter(context, views); + } else { + setRemoteAdapterV11(context, views); + } + boolean useDetailActivity = context.getResources() + .getBoolean(R.bool.use_detail_activity); + Intent clickIntentTemplate = useDetailActivity + ? new Intent(context, DetailActivity.class) + : new Intent(context, MainActivity.class); + PendingIntent clickPendingIntentTemplate = TaskStackBuilder.create(context) + .addNextIntentWithParentStack(clickIntentTemplate) + .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); + views.setPendingIntentTemplate(R.id.widget_list, clickPendingIntentTemplate); + views.setEmptyView(R.id.widget_list, R.id.widget_empty); + + // 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())) { + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); + int[] appWidgetIds = appWidgetManager.getAppWidgetIds( + new ComponentName(context, getClass())); + appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_list); + } + } + + /** + * Sets the remote adapter used to fill in the list items + * + * @param views RemoteViews to set the RemoteAdapter + */ + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + private void setRemoteAdapter(Context context, @NonNull final RemoteViews views) { + views.setRemoteAdapter(R.id.widget_list, + new Intent(context, DetailWidgetRemoteViewsService.class)); + } + + /** + * Sets the remote adapter used to fill in the list items + * + * @param views RemoteViews to set the RemoteAdapter + */ + @SuppressWarnings("deprecation") + private void setRemoteAdapterV11(Context context, @NonNull final RemoteViews views) { + views.setRemoteAdapter(0, R.id.widget_list, + new Intent(context, DetailWidgetRemoteViewsService.class)); + } +} diff --git a/app/src/main/java/com/example/android/sunshine/app/widget/DetailWidgetRemoteViewsService.java b/app/src/main/java/com/example/android/sunshine/app/widget/DetailWidgetRemoteViewsService.java new file mode 100644 index 00000000..f31c3ba9 --- /dev/null +++ b/app/src/main/java/com/example/android/sunshine/app/widget/DetailWidgetRemoteViewsService.java @@ -0,0 +1,175 @@ +package com.example.android.sunshine.app.widget; + +import android.annotation.TargetApi; +import android.content.Intent; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Binder; +import android.os.Build; +import android.util.Log; +import android.widget.AdapterView; +import android.widget.RemoteViews; +import android.widget.RemoteViewsService; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.Target; +import com.example.android.sunshine.app.R; +import com.example.android.sunshine.app.Utility; +import com.example.android.sunshine.app.data.WeatherContract; + +import java.util.concurrent.ExecutionException; + +/** + * RemoteViewsService controlling the data being shown in the scrollable weather detail widget + */ +@TargetApi(Build.VERSION_CODES.HONEYCOMB) +public class DetailWidgetRemoteViewsService extends RemoteViewsService { + public final String LOG_TAG = DetailWidgetRemoteViewsService.class.getSimpleName(); + private static final String[] FORECAST_COLUMNS = { + WeatherContract.WeatherEntry.TABLE_NAME + "." + WeatherContract.WeatherEntry._ID, + WeatherContract.WeatherEntry.COLUMN_DATE, + WeatherContract.WeatherEntry.COLUMN_WEATHER_ID, + WeatherContract.WeatherEntry.COLUMN_SHORT_DESC, + WeatherContract.WeatherEntry.COLUMN_MAX_TEMP, + WeatherContract.WeatherEntry.COLUMN_MIN_TEMP + }; + // these indices must match the projection + static final int INDEX_WEATHER_ID = 0; + static final int INDEX_WEATHER_DATE = 1; + static final int INDEX_WEATHER_CONDITION_ID = 2; + static final int INDEX_WEATHER_DESC = 3; + static final int INDEX_WEATHER_MAX_TEMP = 4; + static final int INDEX_WEATHER_MIN_TEMP = 5; + + @Override + public RemoteViewsFactory onGetViewFactory(Intent intent) { + return new RemoteViewsFactory() { + private Cursor data = null; + + @Override + public void onCreate() { + // Nothing to do + } + + @Override + public void onDataSetChanged() { + if (data != null) { + data.close(); + } + // This method is called by the app hosting the widget (e.g., the launcher) + // However, our ContentProvider is not exported so it doesn't have access to the + // data. Therefore we need to clear (and finally restore) the calling identity so + // that calls use our process and permission + final long identityToken = Binder.clearCallingIdentity(); + String location = Utility.getPreferredLocation(DetailWidgetRemoteViewsService.this); + Uri weatherForLocationUri = WeatherContract.WeatherEntry + .buildWeatherLocationWithStartDate(location, System.currentTimeMillis()); + data = getContentResolver().query(weatherForLocationUri, + FORECAST_COLUMNS, + null, + null, + WeatherContract.WeatherEntry.COLUMN_DATE + " ASC"); + Binder.restoreCallingIdentity(identityToken); + } + + @Override + public void onDestroy() { + if (data != null) { + data.close(); + data = null; + } + } + + @Override + public int getCount() { + return data == null ? 0 : data.getCount(); + } + + @Override + public RemoteViews getViewAt(int position) { + if (position == AdapterView.INVALID_POSITION || + data == null || !data.moveToPosition(position)) { + return null; + } + RemoteViews views = new RemoteViews(getPackageName(), + R.layout.widget_detail_list_item); + int weatherId = data.getInt(INDEX_WEATHER_CONDITION_ID); + int weatherArtResourceId = Utility.getIconResourceForWeatherCondition(weatherId); + Bitmap weatherArtImage = null; + if ( !Utility.usingLocalGraphics(DetailWidgetRemoteViewsService.this) ) { + String weatherArtResourceUrl = Utility.getArtUrlForWeatherCondition( + DetailWidgetRemoteViewsService.this, weatherId); + try { + weatherArtImage = Glide.with(DetailWidgetRemoteViewsService.this) + .load(weatherArtResourceUrl) + .asBitmap() + .error(weatherArtResourceId) + .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).get(); + } catch (InterruptedException | ExecutionException e) { + Log.e(LOG_TAG, "Error retrieving large icon from " + weatherArtResourceUrl, e); + } + } + String description = data.getString(INDEX_WEATHER_DESC); + long dateInMillis = data.getLong(INDEX_WEATHER_DATE); + String formattedDate = Utility.getFriendlyDayString( + DetailWidgetRemoteViewsService.this, dateInMillis, false); + double maxTemp = data.getDouble(INDEX_WEATHER_MAX_TEMP); + double minTemp = data.getDouble(INDEX_WEATHER_MIN_TEMP); + String formattedMaxTemperature = + Utility.formatTemperature(DetailWidgetRemoteViewsService.this, maxTemp); + String formattedMinTemperature = + Utility.formatTemperature(DetailWidgetRemoteViewsService.this, minTemp); + if (weatherArtImage != null) { + views.setImageViewBitmap(R.id.widget_icon, weatherArtImage); + } else { + views.setImageViewResource(R.id.widget_icon, weatherArtResourceId); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + setRemoteContentDescription(views, description); + } + views.setTextViewText(R.id.widget_date, formattedDate); + views.setTextViewText(R.id.widget_description, description); + views.setTextViewText(R.id.widget_high_temperature, formattedMaxTemperature); + views.setTextViewText(R.id.widget_low_temperature, formattedMinTemperature); + + final Intent fillInIntent = new Intent(); + String locationSetting = + Utility.getPreferredLocation(DetailWidgetRemoteViewsService.this); + Uri weatherUri = WeatherContract.WeatherEntry.buildWeatherLocationWithDate( + locationSetting, + dateInMillis); + fillInIntent.setData(weatherUri); + views.setOnClickFillInIntent(R.id.widget_list_item, fillInIntent); + return views; + } + + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) + private void setRemoteContentDescription(RemoteViews views, String description) { + views.setContentDescription(R.id.widget_icon, description); + } + + @Override + public RemoteViews getLoadingView() { + return new RemoteViews(getPackageName(), R.layout.widget_detail_list_item); + } + + @Override + public int getViewTypeCount() { + return 1; + } + + @Override + public long getItemId(int position) { + if (data.moveToPosition(position)) + return data.getLong(INDEX_WEATHER_ID); + return position; + } + + @Override + public boolean hasStableIds() { + return true; + } + }; + } +} diff --git a/app/src/main/res/drawable-nodpi/widget_preview_detail.png b/app/src/main/res/drawable-nodpi/widget_preview_detail.png new file mode 100644 index 0000000000000000000000000000000000000000..7e5a79690729f3570bbd17bd69a9281aee928521 GIT binary patch literal 101100 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%0AOc=M5cw)F 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/widget_detail.xml b/app/src/main/res/layout/widget_detail.xml new file mode 100644 index 00000000..364d33c0 --- /dev/null +++ b/app/src/main/res/layout/widget_detail.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/widget_detail_list_item.xml b/app/src/main/res/layout/widget_detail_list_item.xml new file mode 100644 index 00000000..2231b659 --- /dev/null +++ b/app/src/main/res/layout/widget_detail_list_item.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-sw600dp/bools.xml b/app/src/main/res/values-sw600dp/bools.xml new file mode 100644 index 00000000..a2b6639a --- /dev/null +++ b/app/src/main/res/values-sw600dp/bools.xml @@ -0,0 +1,4 @@ + + + false + \ No newline at end of file diff --git a/app/src/main/res/values-v11/bools.xml b/app/src/main/res/values-v11/bools.xml new file mode 100644 index 00000000..d187294a --- /dev/null +++ b/app/src/main/res/values-v11/bools.xml @@ -0,0 +1,4 @@ + + + true + \ No newline at end of file diff --git a/app/src/main/res/values/bools.xml b/app/src/main/res/values/bools.xml new file mode 100644 index 00000000..11c11a98 --- /dev/null +++ b/app/src/main/res/values/bools.xml @@ -0,0 +1,5 @@ + + + false + true + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 1c7cbb21..b547465a 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -59,4 +59,19 @@ 40dp @dimen/widget_today_default_height 220dp + + 250dp + 180dp + 220dp + @dimen/widget_detail_default_height + + + 24dp + + + 38dp + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 27c9e53d..52c512f8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -138,6 +138,7 @@ Sunshine Today + Sunshine Details No Weather Information Available diff --git a/app/src/main/res/xml/widget_info_detail.xml b/app/src/main/res/xml/widget_info_detail.xml new file mode 100644 index 00000000..54ad27db --- /dev/null +++ b/app/src/main/res/xml/widget_info_detail.xml @@ -0,0 +1,29 @@ + + + + \ No newline at end of file From 089e1a7cc72c82d8a8d49a91e3633b3458c33688 Mon Sep 17 00:00:00 2001 From: Dan Galpin Date: Mon, 25 May 2015 06:03:14 -0700 Subject: [PATCH 04/13] Add a Muzei extension, changing the wallpaper with the weather Requires installation of Muzei: https://play.google.com/store/apps/details?id=net.nurik.roman.muzei --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 12 +++ .../example/android/sunshine/app/Utility.java | 38 ++++++++- .../app/muzei/WeatherMuzeiSource.java | 79 ++++++++++++++++++ .../app/sync/SunshineSyncAdapter.java | 12 +++ app/src/main/res/drawable-nodpi/ic_muzei.png | Bin 0 -> 22644 bytes app/src/main/res/values/strings.xml | 3 + 7 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/example/android/sunshine/app/muzei/WeatherMuzeiSource.java create mode 100755 app/src/main/res/drawable-nodpi/ic_muzei.png diff --git a/app/build.gradle b/app/build.gradle index dbf29c76..e97a2342 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,4 +29,5 @@ dependencies { compile 'com.android.support:design:22.2.0' compile 'com.android.support:recyclerview-v7:22.2.0' compile 'com.google.android.gms:play-services-gcm:7.0.0' + compile 'com.google.android.apps.muzei:muzei-api:2.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 925588ff..029a49d4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -110,6 +110,17 @@ + + + + + + + + + = 300 && weatherId <= 321) { stringId = R.string.condition_3xx; - } else switch(weatherId) { + } else switch (weatherId) { case 500: stringId = R.string.condition_500; break; @@ -502,6 +502,42 @@ public static String getStringForWeatherCondition(Context context, int weatherId return context.getString(stringId); } + /* + * Helper method to provide the correct image according to the weather condition id returned + * by the OpenWeatherMap call. + * + * @param weatherId from OpenWeatherMap API response + * @return A string URL to an appropriate image or null if no mapping is found + */ + public static String getImageUrlForWeatherCondition(int weatherId) { + // Based on weather code data found at: + // http://bugs.openweathermap.org/projects/api/wiki/Weather_Condition_Codes + if (weatherId >= 200 && weatherId <= 232) { + return "http://upload.wikimedia.org/wikipedia/commons/2/28/Thunderstorm_in_Annemasse,_France.jpg"; + } else if (weatherId >= 300 && weatherId <= 321) { + return "http://upload.wikimedia.org/wikipedia/commons/a/a0/Rain_on_leaf_504605006.jpg"; + } else if (weatherId >= 500 && weatherId <= 504) { + return "http://upload.wikimedia.org/wikipedia/commons/6/6c/Rain-on-Thassos.jpg"; + } else if (weatherId == 511) { + return "http://upload.wikimedia.org/wikipedia/commons/b/b8/Fresh_snow.JPG"; + } else if (weatherId >= 520 && weatherId <= 531) { + return "http://upload.wikimedia.org/wikipedia/commons/6/6c/Rain-on-Thassos.jpg"; + } else if (weatherId >= 600 && weatherId <= 622) { + return "http://upload.wikimedia.org/wikipedia/commons/b/b8/Fresh_snow.JPG"; + } else if (weatherId >= 701 && weatherId <= 761) { + return "http://upload.wikimedia.org/wikipedia/commons/e/e6/Westminster_fog_-_London_-_UK.jpg"; + } else if (weatherId == 761 || weatherId == 781) { + return "http://upload.wikimedia.org/wikipedia/commons/d/dc/Raised_dust_ahead_of_a_severe_thunderstorm_1.jpg"; + } else if (weatherId == 800) { + return "http://upload.wikimedia.org/wikipedia/commons/7/7e/A_few_trees_and_the_sun_(6009964513).jpg"; + } else if (weatherId == 801) { + return "http://upload.wikimedia.org/wikipedia/commons/e/e7/Cloudy_Blue_Sky_(5031259890).jpg"; + } else if (weatherId >= 802 && weatherId <= 804) { + return "http://upload.wikimedia.org/wikipedia/commons/5/54/Cloudy_hills_in_Elis,_Greece_2.jpg"; + } + return null; + } + /** * Returns true if the network is available or about to become available. * diff --git a/app/src/main/java/com/example/android/sunshine/app/muzei/WeatherMuzeiSource.java b/app/src/main/java/com/example/android/sunshine/app/muzei/WeatherMuzeiSource.java new file mode 100644 index 00000000..dcfc24cb --- /dev/null +++ b/app/src/main/java/com/example/android/sunshine/app/muzei/WeatherMuzeiSource.java @@ -0,0 +1,79 @@ +/* + * 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.muzei; + +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; + +import com.example.android.sunshine.app.MainActivity; +import com.example.android.sunshine.app.Utility; +import com.example.android.sunshine.app.data.WeatherContract; +import com.example.android.sunshine.app.sync.SunshineSyncAdapter; +import com.google.android.apps.muzei.api.Artwork; +import com.google.android.apps.muzei.api.MuzeiArtSource; + +/** + * Muzei source that changes your background based on the current weather conditions + */ +public class WeatherMuzeiSource extends MuzeiArtSource { + private static final String[] FORECAST_COLUMNS = new String[]{ + WeatherContract.WeatherEntry.COLUMN_WEATHER_ID, + WeatherContract.WeatherEntry.COLUMN_SHORT_DESC + }; + // these indices must match the projection + private static final int INDEX_WEATHER_ID = 0; + private static final int INDEX_SHORT_DESC = 1; + + public WeatherMuzeiSource() { + super("WeatherMuzeiSource"); + } + + @Override + protected void onHandleIntent(Intent intent) { + super.onHandleIntent(intent); + boolean dataUpdated = intent != null && + SunshineSyncAdapter.ACTION_DATA_UPDATED.equals(intent.getAction()); + if (dataUpdated && isEnabled()) { + onUpdate(UPDATE_REASON_OTHER); + } + } + + @Override + protected void onUpdate(int reason) { + String location = Utility.getPreferredLocation(this); + Uri weatherForLocationUri = WeatherContract.WeatherEntry.buildWeatherLocationWithStartDate( + location, System.currentTimeMillis()); + Cursor cursor = getContentResolver().query(weatherForLocationUri, FORECAST_COLUMNS, null, + null, WeatherContract.WeatherEntry.COLUMN_DATE + " ASC"); + if (cursor.moveToFirst()) { + int weatherId = cursor.getInt(INDEX_WEATHER_ID); + String desc = cursor.getString(INDEX_SHORT_DESC); + + String imageUrl = Utility.getImageUrlForWeatherCondition(weatherId); + // Only publish a new wallpaper if we have a valid image + if (imageUrl != null) { + publishArtwork(new Artwork.Builder() + .imageUri(Uri.parse(imageUrl)) + .title(desc) + .byline(location) + .viewIntent(new Intent(this, MainActivity.class)) + .build()); + } + } + cursor.close(); + } +} 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 c9275d0e..5968effe 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 @@ -34,6 +34,7 @@ import com.example.android.sunshine.app.R; import com.example.android.sunshine.app.Utility; import com.example.android.sunshine.app.data.WeatherContract; +import com.example.android.sunshine.app.muzei.WeatherMuzeiSource; import org.json.JSONArray; import org.json.JSONException; @@ -341,6 +342,7 @@ private void getWeatherDataFromJson(String forecastJsonStr, new String[] {Long.toString(dayTime.setJulianDay(julianStartDay-1))}); updateWidgets(); + updateMuzei(); notifyWeather(); } Log.d(LOG_TAG, "Sync Complete. " + cVVector.size() + " Inserted"); @@ -361,6 +363,16 @@ private void updateWidgets() { context.sendBroadcast(dataUpdatedIntent); } + private void updateMuzei() { + // Muzei is only compatible with Jelly Bean MR1+ devices, so there's no need to update the + // Muzei background on lower API level devices + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + Context context = getContext(); + context.startService(new Intent(ACTION_DATA_UPDATED) + .setClass(context, WeatherMuzeiSource.class)); + } + } + 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/res/drawable-nodpi/ic_muzei.png b/app/src/main/res/drawable-nodpi/ic_muzei.png new file mode 100755 index 0000000000000000000000000000000000000000..b0fe3c498636ce7c0c66f15c7764537c95a0ddf1 GIT binary patch literal 22644 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 52c512f8..a94d15e6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -140,6 +140,9 @@ Sunshine Today Sunshine Details + + Today\'s weather + No Weather Information Available No weather information available. The network is not available to fetch weather data. From 6752c12310ff82e59976ffa468b17be250b0ede6 Mon Sep 17 00:00:00 2001 From: Joanna Smith Date: Tue, 16 Jun 2015 00:03:04 -0700 Subject: [PATCH 05/13] Creating a new widget layout for the location text preference --- app/build.gradle | 1 + .../app/LocationEditTextPreference.java | 30 ++++++++++++++++++ .../res/drawable-hdpi/ic_current_location.png | Bin 0 -> 549 bytes .../res/drawable-mdpi/ic_current_location.png | Bin 0 -> 341 bytes .../drawable-xhdpi/ic_current_location.png | Bin 0 -> 660 bytes .../drawable-xxhdpi/ic_current_location.png | Bin 0 -> 976 bytes .../main/res/layout/pref_current_location.xml | 27 ++++++++++++++++ app/src/main/res/values/strings.xml | 3 ++ 8 files changed, 61 insertions(+) create mode 100644 app/src/main/res/drawable-hdpi/ic_current_location.png create mode 100644 app/src/main/res/drawable-mdpi/ic_current_location.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_current_location.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_current_location.png create mode 100644 app/src/main/res/layout/pref_current_location.xml diff --git a/app/build.gradle b/app/build.gradle index 0f98c48a..9618e3f7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,4 +31,5 @@ dependencies { compile 'com.android.support:recyclerview-v7:22.2.0' compile 'com.google.android.apps.muzei:muzei-api:2.0' compile 'com.google.android.gms:play-services-gcm:7.5.0' + compile 'com.google.android.gms:play-services-location:7.5.0' } diff --git a/app/src/main/java/com/example/android/sunshine/app/LocationEditTextPreference.java b/app/src/main/java/com/example/android/sunshine/app/LocationEditTextPreference.java index eb84c05e..381c0a25 100644 --- a/app/src/main/java/com/example/android/sunshine/app/LocationEditTextPreference.java +++ b/app/src/main/java/com/example/android/sunshine/app/LocationEditTextPreference.java @@ -24,8 +24,14 @@ import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; +import android.widget.Toast; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; public class LocationEditTextPreference extends EditTextPreference { static final private int DEFAULT_MINIMUM_LOCATION_LENGTH = 2; @@ -42,8 +48,32 @@ public LocationEditTextPreference(Context context, AttributeSet attrs) { } finally { a.recycle(); } + + // Check to see if Google Play services is available. The Place Picker API is available + // through Google Play services, so if this is false, we'll just carry on as though this + // feature does not exist. If it is true, however, we can add a widget to our preference. + GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); + int resultCode = apiAvailability.isGooglePlayServicesAvailable(getContext()); + if (resultCode == ConnectionResult.SUCCESS) { + // Add the get current location widget to our location preference + setWidgetLayoutResource(R.layout.pref_current_location); + } } + @Override + protected View onCreateView(ViewGroup parent) { + View view = super.onCreateView(parent); + View currentLocation = view.findViewById(R.id.current_location); + currentLocation.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // We'll use a toast for now so that we can test our new preference widget. + Toast.makeText(getContext(), "Woo!", Toast.LENGTH_LONG).show(); + } + }); + + return view; + } @Override protected void showDialog(Bundle state) { diff --git a/app/src/main/res/drawable-hdpi/ic_current_location.png b/app/src/main/res/drawable-hdpi/ic_current_location.png new file mode 100644 index 0000000000000000000000000000000000000000..85e38726dd4240d78e9f802db94a6987b027d0ef GIT binary patch literal 549 zcmV+=0^0qFP)q+FWCCT}XAvHG*iR93pm_1S5Hp zGX{g3?7{FW1~WTE1v&0B)$aWAV|TJUEMI4Vh=>I~Eg~f)`bUbsvBa4vI%APZJ|NE; zS0tp?c;%8+^1MTZHfhFaF~^AZ80bfR8dQmisnWF0?lOWOivMAs61I>7o-}(5etQc3 zW(t=Q*GlZ*QPJi9WQ;5UCnl3HONKmcUCkIi0XHVsB!|$`+Jp$PIdkEDiW5@$l+e}KHK>XL2GeFWdrUB7$wV6n8>Ei0iSS^K z=Z7{5y;D_$J7-ZHp=ORx?M)`Kf-yqJS=6;x2@N7&(Tl%`L%Ya#YYk`7z30|sQ4g80 z*Lne78Wk85Q(Xo|0QUIf@zkeKuOA|f-32DEnDS;fBGv_$1n#m_CUSyLx zUAo+}P64FMv&k;wl-GS<6W|kYt7j@lhB^8sazfy#`K4`S29I5>#|uP4vFFe9;gv>NR1ZS{7KkmM6)zWGe(^m-XX^d7xb_zdYrRNjt`h% no>RS36~_OkuMzu0>#O_)RZ4aRmaPDG00000NkvXXu0mjf7M<-G literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_current_location.png b/app/src/main/res/drawable-mdpi/ic_current_location.png new file mode 100644 index 0000000000000000000000000000000000000000..5684aa7dc5d4dd20ffac6d3191a20b810fa3b56c GIT binary patch literal 341 zcmV-b0jmCqP)%+^Dn#{hi&+J@;JCoEaj|OrYZL7kDW!#0DpPlLFTqv(5ld zAjt|ff|$5qnIwEe*UG7d=7p)6Mf5+2YK8}7}aF5bzPJQLg7;+9r@&{7z|1J zU}*a)K}1wSB}VX7?ptDQsMOEs$JcXc0 zV2FJLGxFJJ)tW{hf?H#O8w9!5yYU4a1oy@Q4Fv9gR3M9>ZY*UlM_nxwYhB(^tOj)t-4}Irl~@CEvS9>iDv{ft<02T9Penfl z7b>}gE={qeQ9gUP=*sff8!fA4O(qD-v(F6;8hGq7M%bhrU=gDvo?2KZgRNKG$#1>{ zZ7fI|PDx?I;Y=DghlK;JM8@LuXZl-VBh96x)S19!k~>-Z6$eYbc#_uSkP)JcQr2ec zCvUJv54F%xR@r8T94;<7X4z4%m7Jc}bjYPZU==>QI6TNaKiY18%^Z)AV2LVz%*iV( ulHduvV~rziwk|2NO8>wAC-9}f^Y90NP?&Wf5nE#b0000126oEP)hbF_M~pKs-ng5!67dvJ&uMT#<#ewipzY&>qA?Z$U`K zdMF~c|3D-m8bNHSG5r-vDk3(RT)dc=YC_ki*N10clJ}k2?4j=Gdz=|~;GLOwHsM{= zAgbDF4AdB?F;I$b%8YOqQQc*PGCPT=qlg}^@d8<+7hGjeJ;vHZnZFRvW;sok4HI#k zzmdS6(MQAv*v2FhvkBU%u_DVzf|fW;%|v{SIC{eb7dSu%IWlC((ZNA3a)&pFqsv5) zTod0R*nZ{&n*q1?>E|JW?K)`^iX7ui(Swh@Oe3amNyskNGG$WuN;AM~1l=VPC?e?o zWCx+Tm_^WiOibI%lXagK;@H9iM72m8F+@z7ao!`YW`0CeW5jUWELICiY%vR0B+w@G zCb7&8lKKdJdp{*ZkTRkw18(h{XN-APS>-unoMS8C_9>z&5g_6*`n{9FrHvn`Af^hp zXvHPXFY3G*0`wrN9$fm?*xg=n43~X~YB%1l=}iKcL1dji$7M>LaRpB){WZu5s`Vir z6{%KI#~1L_t#@=bW3_pHiY!sUYGFm4u|50=o1ohFh-WvcHW~h;ji^g5V6{_0Jgd-( zHKdLY<3<0lIe>K@31|?jR~;S44G?#9V2vRG-Nx!f-1!ZZ!i9g~uByu(;_?NuPM_iO zDEtlr*n_C{;!L*B+XX@gA=pw0Z^q;YwkRgcuke?+-5_ujYs-pypm_Sqy zXeO>^ezH4U9PKQbk#fY5H{-mdKum`bvv6I6>Nbn@mO~_P8A11&0n+$t;tcjLvR{!% z#C60p%|3kW=U2q^4T+^4BMDQKXaU@EoZ=DU7$-$dT*CdmJjoEfbdo1amOP#GGQ>US zclTSqq=r6W5lPTX4pC!mj3Y4{rND+L@)QZ|2}jvL8A{9`p8Y{T8R}p+S6D#SXn|pN yQD@sJF>LOvafUfb2X)Z+zkOq%#z60ghW`K~?beCrQMK^^0000 + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a5ab50de..cd9580a9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -48,6 +48,9 @@ 94043 + + Use my location + Invalid Location (%1$s)" Validating Location... (%1$s)" From 5ac9eb20648a1085e26dc114adf7d1f46018975b Mon Sep 17 00:00:00 2001 From: Joanna Smith Date: Tue, 16 Jun 2015 00:20:27 -0700 Subject: [PATCH 06/13] Setting up the required framework for the PlacePicker integration --- app/src/main/AndroidManifest.xml | 3 ++ .../app/LocationEditTextPreference.java | 35 +++++++++++++++++-- .../sunshine/app/SettingsActivity.java | 24 +++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 03b126d2..a8893d32 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,6 +39,9 @@ android:protectionLevel="signature" /> + + + Date: Tue, 16 Jun 2015 21:39:26 -0700 Subject: [PATCH 07/13] Providing the answer for the PlacePicker implementation quiz --- .../android/sunshine/app/LocationEditTextPreference.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/example/android/sunshine/app/LocationEditTextPreference.java b/app/src/main/java/com/example/android/sunshine/app/LocationEditTextPreference.java index 3b663df4..b91398c8 100644 --- a/app/src/main/java/com/example/android/sunshine/app/LocationEditTextPreference.java +++ b/app/src/main/java/com/example/android/sunshine/app/LocationEditTextPreference.java @@ -74,7 +74,7 @@ public void onClick(View v) { // Launch the Place Picker so that the user can specify their location, and then // return the result to SettingsActivity. - // TODO(student): Create a PlacePicker.IntentBuilder object here. + PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder(); // We are in a view right now, not an activity. So we need to get ourselves @@ -83,9 +83,8 @@ public void onClick(View v) { // intent comes to the right place for us to process it. Activity settingsActivity = (SettingsActivity) context; try { - // TODO(student): Launch the intent using your settingsActivity object to access - // startActivityForResult(). You'll need to build your builder object and use - // the request code we declared in SettingsActivity. + settingsActivity.startActivityForResult( + builder.build(context), SettingsActivity.PLACE_PICKER_REQUEST); } catch (GooglePlayServicesNotAvailableException | GooglePlayServicesRepairableException e) { From fac9721e57a9218adab88738fe1bcc7c1b45b29c Mon Sep 17 00:00:00 2001 From: Joanna Smith Date: Tue, 16 Jun 2015 21:57:23 -0700 Subject: [PATCH 08/13] Updating the syncadapter to use the latlng variable stored in sharedpreferences --- .../sunshine/app/SettingsActivity.java | 36 +++++++++++++++++-- .../example/android/sunshine/app/Utility.java | 24 +++++++++++++ .../app/sync/SunshineSyncAdapter.java | 29 ++++++++++++--- app/src/main/res/values/strings.xml | 4 +++ 4 files changed, 87 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java b/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java index 49304c8f..6c515e62 100644 --- a/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java +++ b/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java @@ -24,12 +24,13 @@ import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; -import android.util.Log; +import android.text.TextUtils; import com.example.android.sunshine.app.data.WeatherContract; import com.example.android.sunshine.app.sync.SunshineSyncAdapter; import com.google.android.gms.location.places.Place; import com.google.android.gms.location.places.ui.PlacePicker; +import com.google.android.gms.maps.model.LatLng; /** * A {@link PreferenceActivity} that presents a set of application settings. @@ -137,7 +138,12 @@ public boolean onPreferenceChange(Preference preference, Object value) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if ( key.equals(getString(R.string.pref_location_key)) ) { // we've changed the location - // first clear locationStatus + // Wipe out any potential PlacePicker latlng values so that we can use this text entry. + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.remove(getString(R.string.pref_location_latitude)); + editor.remove(getString(R.string.pref_location_longitude)); + editor.commit(); + Utility.resetLocationStatus(this); SunshineSyncAdapter.syncImmediately(this); } else if ( key.equals(getString(R.string.pref_units_key)) ) { @@ -167,12 +173,38 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { Place place = PlacePicker.getPlace(data, this); String address = place.getAddress().toString(); + // TODO(student): Get the LatLng object from the place -- this is a placeholder. + LatLng latLong = new LatLng(37.422503f, -122.083939f); + + // If the provided place doesn't have an address, we'll form a display-friendly + // string from the latlng values. + if (TextUtils.isEmpty(address)) { + address = String.format("(%.2f, %.2f)",latLong.latitude, latLong.longitude); + } SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(getString(R.string.pref_location_key), address); + + // Also store the latitude and longitude so that we can use these to get a precise + // result from our weather service. We cannot expect the weather service to + // understand addresses that Google formats. + // TODO(student) Store the latitude and longitude as float values according to the + // keys defined in strings.xml. + + + editor.commit(); + + // Tell the SyncAdapter that we've changed the location, so that we can update + // our UI with new values. We need to do this manually because we are responding + // to the PlacePicker widget result here instead of allowing the + // LocationEditTextPreference to handle these changes and invoke our callbacks. + Preference locationPreference = findPreference(getString(R.string.pref_location_key)); + setPreferenceSummary(locationPreference, address); + Utility.resetLocationStatus(this); + SunshineSyncAdapter.syncImmediately(this); } } else { super.onActivityResult(requestCode, resultCode, data); diff --git a/app/src/main/java/com/example/android/sunshine/app/Utility.java b/app/src/main/java/com/example/android/sunshine/app/Utility.java index 08968d01..5f559620 100644 --- a/app/src/main/java/com/example/android/sunshine/app/Utility.java +++ b/app/src/main/java/com/example/android/sunshine/app/Utility.java @@ -30,6 +30,30 @@ import java.util.Locale; public class Utility { + // We'll default our latlong to 0. Yay, "Earth!" + public static float DEFAULT_LATLONG = 0F; + + public static boolean isLocationLatLonAvailable(Context context) { + SharedPreferences prefs + = PreferenceManager.getDefaultSharedPreferences(context); + return prefs.contains(context.getString(R.string.pref_location_latitude)) + && prefs.contains(context.getString(R.string.pref_location_longitude)); + } + + public static float getLocationLatitude(Context context) { + SharedPreferences prefs + = PreferenceManager.getDefaultSharedPreferences(context); + return prefs.getFloat(context.getString(R.string.pref_location_latitude), + DEFAULT_LATLONG); + } + + public static float getLocationLongitude(Context context) { + SharedPreferences prefs + = PreferenceManager.getDefaultSharedPreferences(context); + return prefs.getFloat(context.getString(R.string.pref_location_longitude), + DEFAULT_LATLONG); + } + public static String getPreferredLocation(Context context) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); return prefs.getString(context.getString(R.string.pref_location_key), 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 5968effe..399cb336 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 @@ -93,7 +93,13 @@ public SunshineSyncAdapter(Context context, boolean autoInitialize) { @Override public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { Log.d(LOG_TAG, "Starting sync"); - String locationQuery = Utility.getPreferredLocation(getContext()); + + // We no longer need just the location String, but also potentially the latitude and + // longitude, in case we are syncing based on a new Place Picker API result. + Context context = getContext(); + String locationQuery = Utility.getPreferredLocation(context); + String locationLatitude = String.valueOf(Utility.getLocationLatitude(context)); + String locationLongitude = String.valueOf(Utility.getLocationLongitude(context)); // These two need to be declared outside the try/catch // so that they can be closed in the finally block. @@ -114,13 +120,28 @@ public void onPerformSync(Account account, Bundle extras, String authority, Cont final String FORECAST_BASE_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?"; final String QUERY_PARAM = "q"; + final String LAT_PARAM = "lat"; + final String LON_PARAM = "lon"; final String FORMAT_PARAM = "mode"; final String UNITS_PARAM = "units"; final String DAYS_PARAM = "cnt"; - Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon() - .appendQueryParameter(QUERY_PARAM, locationQuery) - .appendQueryParameter(FORMAT_PARAM, format) + Uri.Builder uriBuilder = Uri.parse(FORECAST_BASE_URL).buildUpon(); + + // Instead of always building the query based off of the location string, we want to + // potentially build a query using a lat/lon value. This will be the case when we are + // syncing based off of a new location from the Place Picker API. So we need to check + // if we have a lat/lon to work with, and use those when we do. Otherwise, the weather + // service may not understand the location address provided by the Place Picker API + // and the user could end up with no weather! The horror! + if (Utility.isLocationLatLonAvailable(context)) { + uriBuilder.appendQueryParameter(LAT_PARAM, locationLatitude) + .appendQueryParameter(LON_PARAM, locationLongitude); + } else { + uriBuilder.appendQueryParameter(QUERY_PARAM, locationQuery); + } + + Uri builtUri = uriBuilder.appendQueryParameter(FORMAT_PARAM, format) .appendQueryParameter(UNITS_PARAM, units) .appendQueryParameter(DAYS_PARAM, Integer.toString(numDays)) .build(); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cd9580a9..e969a0d1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -45,6 +45,10 @@ loc-status + + loc-latitude + loc-longitude + 94043 From 03184fde50c2430d6c0f4f94784b3c9dbfc23550 Mon Sep 17 00:00:00 2001 From: Joanna Smith Date: Tue, 16 Jun 2015 00:42:43 -0700 Subject: [PATCH 09/13] Solution to syncadapter quiz --- .../android/sunshine/app/SettingsActivity.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java b/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java index 6c515e62..1f0cb206 100644 --- a/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java +++ b/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java @@ -173,8 +173,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { Place place = PlacePicker.getPlace(data, this); String address = place.getAddress().toString(); - // TODO(student): Get the LatLng object from the place -- this is a placeholder. - LatLng latLong = new LatLng(37.422503f, -122.083939f); + LatLng latLong = place.getLatLng(); // If the provided place doesn't have an address, we'll form a display-friendly // string from the latlng values. @@ -190,11 +189,10 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Also store the latitude and longitude so that we can use these to get a precise // result from our weather service. We cannot expect the weather service to // understand addresses that Google formats. - // TODO(student) Store the latitude and longitude as float values according to the - // keys defined in strings.xml. - - - + editor.putFloat(getString(R.string.pref_location_latitude), + (float) latLong.latitude); + editor.putFloat(getString(R.string.pref_location_longitude), + (float) latLong.longitude); editor.commit(); // Tell the SyncAdapter that we've changed the location, so that we can update From 3610a563f55df0f555b6ee5822cd06ccda37c7b8 Mon Sep 17 00:00:00 2001 From: Joanna Smith Date: Tue, 16 Jun 2015 10:49:32 -0700 Subject: [PATCH 10/13] Moving the latlng wipe to the correct location --- .../example/android/sunshine/app/sync/SunshineSyncAdapter.java | 1 + 1 file changed, 1 insertion(+) 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 399cb336..4a1232a9 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 @@ -248,6 +248,7 @@ private void getWeatherDataFromJson(String forecastJsonStr, try { JSONObject forecastJson = new JSONObject(forecastJsonStr); + Context context = getContext(); // do we have an error? if ( forecastJson.has(OWM_MESSAGE_CODE) ) { From 2e8fe23bdaa47ea466db3f6002bc13a032eca1dc Mon Sep 17 00:00:00 2001 From: Joanna Smith Date: Tue, 16 Jun 2015 11:01:33 -0700 Subject: [PATCH 11/13] Adding attributions --- .../sunshine/app/SettingsActivity.java | 35 ++++++++++++++++++- app/src/main/res/values/strings.xml | 3 ++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java b/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java index 1f0cb206..ae20b520 100644 --- a/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java +++ b/app/src/main/java/com/example/android/sunshine/app/SettingsActivity.java @@ -24,8 +24,11 @@ import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; +import android.support.design.widget.Snackbar; import android.text.TextUtils; - +import android.util.Log; +import android.view.View; +import android.widget.ImageView; import com.example.android.sunshine.app.data.WeatherContract; import com.example.android.sunshine.app.sync.SunshineSyncAdapter; import com.google.android.gms.location.places.Place; @@ -43,6 +46,7 @@ public class SettingsActivity extends PreferenceActivity implements Preference.OnPreferenceChangeListener, SharedPreferences.OnSharedPreferenceChangeListener { protected final static int PLACE_PICKER_REQUEST = 9090; + private ImageView mAttribution; @Override public void onCreate(Bundle savedInstanceState) { @@ -55,6 +59,19 @@ public void onCreate(Bundle savedInstanceState) { bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key))); bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key))); bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_art_pack_key))); + + + // If we are using a PlacePicker location, we need to show attributions. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mAttribution = new ImageView(this); + mAttribution.setImageResource(R.drawable.powered_by_google_light); + + if (!Utility.isLocationLatLonAvailable(this)) { + mAttribution.setVisibility(View.GONE); + } + + setListFooter(mAttribution); + } } // Registers a shared preference change listener that gets notified when preferences change @@ -144,6 +161,11 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin editor.remove(getString(R.string.pref_location_longitude)); editor.commit(); + // Remove attributions for our any PlacePicker locations. + if (mAttribution != null) { + mAttribution.setVisibility(View.GONE); + } + Utility.resetLocationStatus(this); SunshineSyncAdapter.syncImmediately(this); } else if ( key.equals(getString(R.string.pref_units_key)) ) { @@ -201,6 +223,17 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { // LocationEditTextPreference to handle these changes and invoke our callbacks. Preference locationPreference = findPreference(getString(R.string.pref_location_key)); setPreferenceSummary(locationPreference, address); + + // Add attributions for our new PlacePicker location. + if (mAttribution != null) { + mAttribution.setVisibility(View.VISIBLE); + } else { + // For pre-Honeycomb devices, we cannot add a footer, so we will use a snackbar + View rootView = findViewById(android.R.id.content); + Snackbar.make(rootView, getString(R.string.attribution_text), + Snackbar.LENGTH_LONG).show(); + } + Utility.resetLocationStatus(this); SunshineSyncAdapter.syncImmediately(this); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e969a0d1..93ab7dea 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -233,4 +233,7 @@ Heads up: %1$s in %2$s! // TODO: Get the SenderID from the Developer Console + + Powered by Google + From 745380e35d16527f3aa40a2d0b081200e9a80de4 Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Wed, 28 Oct 2015 15:55:27 -0700 Subject: [PATCH 12/13] Add API Key Parameter to OpenWeatherMap API Call --- app/build.gradle | 3 +++ .../example/android/sunshine/app/sync/SunshineSyncAdapter.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 9618e3f7..79af6450 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,6 +18,9 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + buildTypes.each { + it.buildConfigField 'String', 'OPEN_WEATHER_MAP_API_KEY', MyOpenWeatherMapApiKey + } } dependencies { 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 4a1232a9..9aa52c96 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 @@ -30,6 +30,7 @@ import android.util.Log; import com.bumptech.glide.Glide; +import com.example.android.sunshine.app.BuildConfig; import com.example.android.sunshine.app.MainActivity; import com.example.android.sunshine.app.R; import com.example.android.sunshine.app.Utility; @@ -125,6 +126,7 @@ public void onPerformSync(Account account, Bundle extras, String authority, Cont final String FORMAT_PARAM = "mode"; final String UNITS_PARAM = "units"; final String DAYS_PARAM = "cnt"; + final String APPID_PARAM = "APPID"; Uri.Builder uriBuilder = Uri.parse(FORECAST_BASE_URL).buildUpon(); @@ -144,6 +146,7 @@ public void onPerformSync(Account account, Bundle extras, String authority, Cont Uri builtUri = uriBuilder.appendQueryParameter(FORMAT_PARAM, format) .appendQueryParameter(UNITS_PARAM, units) .appendQueryParameter(DAYS_PARAM, Integer.toString(numDays)) + .appendQueryParameter(APPID_PARAM, BuildConfig.OPEN_WEATHER_MAP_API_KEY) .build(); URL url = new URL(builtUri.toString()); From b503732795fe5fac22b856dc53b444cb4a582d87 Mon Sep 17 00:00:00 2001 From: SudKul <48475411+SudKul@users.noreply.github.com> Date: Thu, 21 Oct 2021 19:02:53 +0530 Subject: [PATCH 13/13] Create CODEOWNERS --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..2a6bcb28 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @udacity/active-public-content \ No newline at end of file