Integrate Glide to load weather art icons from an external source

This commit is contained in:
Dan Galpin
2015-05-24 17:47:02 -07:00
parent e666cf879b
commit 822d52bb4b
11 changed files with 101 additions and 12 deletions

View File

@@ -21,6 +21,7 @@ android {
dependencies { dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.github.bumptech.glide:glide:3.5.2'
compile 'com.android.support:appcompat-v7:21.0.2' compile 'com.android.support:appcompat-v7:21.0.2'
compile 'com.android.support:support-annotations:22.0.0' compile 'com.android.support:support-annotations:22.0.0'
} }

View File

@@ -34,6 +34,7 @@ import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.example.android.sunshine.app.data.WeatherContract; import com.example.android.sunshine.app.data.WeatherContract;
import com.example.android.sunshine.app.data.WeatherContract.WeatherEntry; import com.example.android.sunshine.app.data.WeatherContract.WeatherEntry;
@@ -184,7 +185,11 @@ public class DetailFragment extends Fragment implements LoaderManager.LoaderCall
int weatherId = data.getInt(COL_WEATHER_CONDITION_ID); int weatherId = data.getInt(COL_WEATHER_CONDITION_ID);
// Use weather art image // Use weather art image
mIconView.setImageResource(Utility.getArtResourceForWeatherCondition(weatherId)); Glide.with(this)
.load(Utility.getArtUrlForWeatherCondition(getActivity(), weatherId))
.error(Utility.getArtResourceForWeatherCondition(weatherId))
.crossFade()
.into(mIconView);
// Read date from cursor and update views for day of week and date // Read date from cursor and update views for day of week and date
long date = data.getLong(COL_WEATHER_DATE); long date = data.getLong(COL_WEATHER_DATE);

View File

@@ -24,6 +24,8 @@ import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.bumptech.glide.Glide;
/** /**
* {@link ForecastAdapter} exposes a list of weather forecasts * {@link ForecastAdapter} exposes a list of weather forecasts
* from a {@link Cursor} to a {@link android.widget.ListView}. * from a {@link Cursor} to a {@link android.widget.ListView}.
@@ -91,21 +93,28 @@ public class ForecastAdapter extends CursorAdapter {
int viewType = getItemViewType(cursor.getPosition()); int viewType = getItemViewType(cursor.getPosition());
int weatherId = cursor.getInt(ForecastFragment.COL_WEATHER_CONDITION_ID); int weatherId = cursor.getInt(ForecastFragment.COL_WEATHER_CONDITION_ID);
int fallbackIconId;
switch (viewType) { switch (viewType) {
case VIEW_TYPE_TODAY: { case VIEW_TYPE_TODAY: {
// Get weather icon // Get weather icon
viewHolder.iconView.setImageResource(Utility.getArtResourceForWeatherCondition( fallbackIconId = Utility.getArtResourceForWeatherCondition(
weatherId)); weatherId);
break; break;
} }
case VIEW_TYPE_FUTURE_DAY: { default: {
// Get weather icon // Get weather icon
viewHolder.iconView.setImageResource(Utility.getIconResourceForWeatherCondition( fallbackIconId = Utility.getIconResourceForWeatherCondition(
weatherId)); weatherId);
break; break;
} }
} }
Glide.with(mContext)
.load(Utility.getArtUrlForWeatherCondition(mContext, weatherId))
.error(fallbackIconId)
.crossFade()
.into(viewHolder.iconView);
// Read date from cursor // Read date from cursor
long dateInMillis = cursor.getLong(ForecastFragment.COL_WEATHER_DATE); long dateInMillis = cursor.getLong(ForecastFragment.COL_WEATHER_DATE);
// Find TextView and set formatted date on it // Find TextView and set formatted date on it

View File

@@ -216,6 +216,43 @@ public class Utility {
return -1; return -1;
} }
/**
* Helper method to provide the art urls according to the weather condition id returned
* by the OpenWeatherMap call.
*
* @param context Context to use for retrieving the URL format
* @param weatherId from OpenWeatherMap API response
* @return url for the corresponding weather artwork. null if no relation is found.
*/
public static String getArtUrlForWeatherCondition(Context context, 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 context.getString(R.string.format_art_url, "storm");
} else if (weatherId >= 300 && weatherId <= 321) {
return context.getString(R.string.format_art_url, "light_rain");
} else if (weatherId >= 500 && weatherId <= 504) {
return context.getString(R.string.format_art_url, "rain");
} else if (weatherId == 511) {
return context.getString(R.string.format_art_url, "snow");
} else if (weatherId >= 520 && weatherId <= 531) {
return context.getString(R.string.format_art_url, "rain");
} else if (weatherId >= 600 && weatherId <= 622) {
return context.getString(R.string.format_art_url, "snow");
} else if (weatherId >= 701 && weatherId <= 761) {
return context.getString(R.string.format_art_url, "fog");
} else if (weatherId == 761 || weatherId == 781) {
return context.getString(R.string.format_art_url, "storm");
} else if (weatherId == 800) {
return context.getString(R.string.format_art_url, "clear");
} else if (weatherId == 801) {
return context.getString(R.string.format_art_url, "light_clouds");
} else if (weatherId >= 802 && weatherId <= 804) {
return context.getString(R.string.format_art_url, "clouds");
}
return null;
}
/** /**
* Helper method to provide the art resource id according to the weather condition id returned * Helper method to provide the art resource id according to the weather condition id returned
* by the OpenWeatherMap call. * by the OpenWeatherMap call.

View File

@@ -2,6 +2,7 @@ package com.example.android.sunshine.app.sync;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.annotation.SuppressLint;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.AbstractThreadedSyncAdapter; import android.content.AbstractThreadedSyncAdapter;
@@ -28,6 +29,7 @@ import android.support.v4.app.TaskStackBuilder;
import android.text.format.Time; import android.text.format.Time;
import android.util.Log; import android.util.Log;
import com.bumptech.glide.Glide;
import com.example.android.sunshine.app.MainActivity; import com.example.android.sunshine.app.MainActivity;
import com.example.android.sunshine.app.R; import com.example.android.sunshine.app.R;
import com.example.android.sunshine.app.Utility; import com.example.android.sunshine.app.Utility;
@@ -46,6 +48,7 @@ import java.lang.annotation.RetentionPolicy;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.util.Vector; import java.util.Vector;
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();
@@ -377,8 +380,33 @@ public class SunshineSyncAdapter extends AbstractThreadedSyncAdapter {
int iconId = Utility.getIconResourceForWeatherCondition(weatherId); int iconId = Utility.getIconResourceForWeatherCondition(weatherId);
Resources resources = context.getResources(); Resources resources = context.getResources();
Bitmap largeIcon = BitmapFactory.decodeResource(resources, int artResourceId = Utility.getArtResourceForWeatherCondition(weatherId);
Utility.getArtResourceForWeatherCondition(weatherId)); String artUrl = Utility.getArtUrlForWeatherCondition(context, weatherId);
// On Honeycomb and higher devices, we can retrieve the size of the large icon
// Prior to that, we use a fixed size
@SuppressLint("InlinedApi")
int largeIconWidth = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB
? resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_width)
: resources.getDimensionPixelSize(R.dimen.notification_large_icon_default);
@SuppressLint("InlinedApi")
int largeIconHeight = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB
? resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_height)
: resources.getDimensionPixelSize(R.dimen.notification_large_icon_default);
// Retrieve the large icon
Bitmap largeIcon;
try {
largeIcon = Glide.with(context)
.load(artUrl)
.asBitmap()
.error(artResourceId)
.fitCenter()
.into(largeIconWidth, largeIconHeight).get();
} catch (InterruptedException | ExecutionException e) {
Log.e(LOG_TAG, "Error retrieving large icon from " + artUrl, e);
largeIcon = BitmapFactory.decodeResource(resources, artResourceId);
}
String title = context.getString(R.string.app_name); String title = context.getString(R.string.app_name);
// Define the text of the forecast. // Define the text of the forecast.

View File

@@ -83,7 +83,8 @@
<ImageView <ImageView
android:id="@+id/detail_icon" android:id="@+id/detail_icon"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<TextView <TextView
android:id="@+id/detail_forecast_textview" android:id="@+id/detail_forecast_textview"

View File

@@ -111,7 +111,8 @@
<ImageView <ImageView
android:id="@+id/detail_icon" android:id="@+id/detail_icon"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" /> android:layout_width="wrap_content"
android:adjustViewBounds="true" />
<TextView <TextView
android:fontFamily="sans-serif-condensed" android:fontFamily="sans-serif-condensed"

View File

@@ -31,7 +31,8 @@
android:id="@+id/list_item_icon" android:id="@+id/list_item_icon"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"
android:adjustViewBounds="true"/>
</FrameLayout> </FrameLayout>

View File

@@ -71,7 +71,8 @@
android:id="@+id/list_item_icon" android:id="@+id/list_item_icon"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/> android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"/>
<TextView <TextView
android:id="@+id/list_item_forecast_textview" android:id="@+id/list_item_forecast_textview"

View File

@@ -17,4 +17,6 @@
<!-- Default screen margins, per the Android Design guidelines. --> <!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="notification_large_icon_default">48dp</dimen>
</resources> </resources>

View File

@@ -81,6 +81,9 @@
<string name="pref_units_imperial" translatable="false">imperial</string> <string name="pref_units_imperial" translatable="false">imperial</string>
<!-- Format for retrieving art from an external source [CHAR LIMIT=NONE] -->
<string name="format_art_url" translatable="false">https://raw.githubusercontent.com/udacity/Sunshine-Version-2/sunshine_master/app/src/main/res/drawable-xxhdpi/art_<xliff:g id="description">%s</xliff:g>.png</string>
<!-- Language-specific constants --> <!-- Language-specific constants -->
<string name="today">Today</string> <string name="today">Today</string>