diff --git a/app/build.gradle b/app/build.gradle
index 19167f951..f7ffae8fd 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -17,6 +17,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/FetchWeatherTask.java b/app/src/main/java/com/example/android/sunshine/app/FetchWeatherTask.java
index bd325b2a4..c4169ee00 100644
--- a/app/src/main/java/com/example/android/sunshine/app/FetchWeatherTask.java
+++ b/app/src/main/java/com/example/android/sunshine/app/FetchWeatherTask.java
@@ -278,12 +278,14 @@ protected Void doInBackground(String... params) {
final String FORMAT_PARAM = "mode";
final String UNITS_PARAM = "units";
final String DAYS_PARAM = "cnt";
+ final String APPID_PARAM = "APPID";
Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM, params[0])
.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());
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 8b54df847..80ddf992b 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
@@ -6,6 +6,8 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
/**
* {@link ForecastAdapter} exposes a list of weather forecasts
@@ -16,29 +18,6 @@ public ForecastAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
}
- /**
- * Prepare the weather high/lows for presentation.
- */
- private String formatHighLows(double high, double low) {
- boolean isMetric = Utility.isMetric(mContext);
- String highLowStr = Utility.formatTemperature(high, isMetric) + "/" + Utility.formatTemperature(low, isMetric);
- return highLowStr;
- }
-
- /*
- This is ported from FetchWeatherTask --- but now we go straight from the cursor to the
- string.
- */
- private String convertCursorRowToUXFormat(Cursor cursor) {
- String highAndLow = formatHighLows(
- cursor.getDouble(ForecastFragment.COL_WEATHER_MAX_TEMP),
- cursor.getDouble(ForecastFragment.COL_WEATHER_MIN_TEMP));
-
- return Utility.formatDate(cursor.getLong(ForecastFragment.COL_WEATHER_DATE)) +
- " - " + cursor.getString(ForecastFragment.COL_WEATHER_DESC) +
- " - " + highAndLow;
- }
-
/*
Remember that these views are reused as needed.
*/
@@ -57,7 +36,35 @@ public void bindView(View view, Context context, Cursor cursor) {
// our view is pretty simple here --- just a text view
// we'll keep the UI functional with a simple (and slow!) binding.
- //TextView tv = (TextView)view;
- //tv.setText(convertCursorRowToUXFormat(cursor));
+ // Read weather icon ID from cursor
+ int weatherId = cursor.getInt(ForecastFragment.COL_WEATHER_ID);
+ // Use placeholder image for now
+ ImageView iconView = (ImageView) view.findViewById(R.id.list_item_icon);
+ iconView.setImageResource(R.drawable.ic_launcher);
+
+ // Read date from cursor
+ long dateInMillis = cursor.getLong(ForecastFragment.COL_WEATHER_DATE);
+ // Find TextView and set formatted date on it
+ TextView dateView = (TextView) view.findViewById(R.id.list_item_date_textview);
+ dateView.setText(Utility.getFriendlyDayString(context, dateInMillis));
+
+ // Read weather forecast from cursor
+ String description = cursor.getString(ForecastFragment.COL_WEATHER_DESC);
+ // Find TextView and set weather forecast on it
+ TextView descriptionView = (TextView) view.findViewById(R.id.list_item_forecast_textview);
+ descriptionView.setText(description);
+
+ // Read user preference for metric or imperial temperature units
+ boolean isMetric = Utility.isMetric(context);
+
+ // Read high temperature from cursor
+ double high = cursor.getDouble(ForecastFragment.COL_WEATHER_MAX_TEMP);
+ TextView highView = (TextView) view.findViewById(R.id.list_item_high_textview);
+ highView.setText(Utility.formatTemperature(high, isMetric));
+
+ // Read low temperature from cursor
+ double low = cursor.getDouble(ForecastFragment.COL_WEATHER_MIN_TEMP);
+ TextView lowView = (TextView) view.findViewById(R.id.list_item_low_textview);
+ lowView.setText(Utility.formatTemperature(low, isMetric));
}
}
\ No newline at end of file
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 317d9ee18..30b9a7f21 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
@@ -18,8 +18,10 @@
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
+import android.text.format.Time;
import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.Date;
public class Utility {
@@ -46,8 +48,98 @@ static String formatTemperature(double temperature, boolean isMetric) {
return String.format("%.0f", temp);
}
- static String formatDate(long dateInMillis) {
- Date date = new Date(dateInMillis);
+ static String formatDate(long dateInMilliseconds) {
+ Date date = new Date(dateInMilliseconds);
return DateFormat.getDateInstance().format(date);
}
+
+ // Format used for storing dates in the database. ALso used for converting those strings
+ // back into date objects for comparison/processing.
+ public static final String DATE_FORMAT = "yyyyMMdd";
+
+ /**
+ * Helper method to convert the database representation of the date into something to display
+ * to users. As classy and polished a user experience as "20140102" is, we can do better.
+ *
+ * @param context Context to use for resource localization
+ * @param dateInMillis The date in milliseconds
+ * @return a user-friendly representation of the date.
+ */
+ public static String getFriendlyDayString(Context context, long dateInMillis) {
+ // The day string for forecast uses the following logic:
+ // For today: "Today, June 8"
+ // For tomorrow: "Tomorrow"
+ // For the next 5 days: "Wednesday" (just the day name)
+ // For all days after that: "Mon Jun 8"
+
+ Time time = new Time();
+ time.setToNow();
+ long currentTime = System.currentTimeMillis();
+ int julianDay = Time.getJulianDay(dateInMillis, time.gmtoff);
+ int currentJulianDay = Time.getJulianDay(currentTime, time.gmtoff);
+
+ // If the date we're building the String for is today's date, the format
+ // is "Today, June 24"
+ if (julianDay == currentJulianDay) {
+ String today = context.getString(R.string.today);
+ int formatId = R.string.format_full_friendly_date;
+ return String.format(context.getString(
+ formatId,
+ today,
+ getFormattedMonthDay(context, dateInMillis)));
+ } else if ( julianDay < currentJulianDay + 7 ) {
+ // If the input date is less than a week in the future, just return the day name.
+ return getDayName(context, dateInMillis);
+ } else {
+ // Otherwise, use the form "Mon Jun 3"
+ SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE MMM dd");
+ return shortenedDateFormat.format(dateInMillis);
+ }
+ }
+
+ /**
+ * Given a day, returns just the name to use for that day.
+ * E.g "today", "tomorrow", "wednesday".
+ *
+ * @param context Context to use for resource localization
+ * @param dateInMillis The date in milliseconds
+ * @return
+ */
+ public static String getDayName(Context context, long dateInMillis) {
+ // If the date is today, return the localized version of "Today" instead of the actual
+ // day name.
+
+ Time t = new Time();
+ t.setToNow();
+ int julianDay = Time.getJulianDay(dateInMillis, t.gmtoff);
+ int currentJulianDay = Time.getJulianDay(System.currentTimeMillis(), t.gmtoff);
+ if (julianDay == currentJulianDay) {
+ return context.getString(R.string.today);
+ } else if ( julianDay == currentJulianDay +1 ) {
+ return context.getString(R.string.tomorrow);
+ } else {
+ Time time = new Time();
+ time.setToNow();
+ // Otherwise, the format is just the day of the week (e.g "Wednesday".
+ SimpleDateFormat dayFormat = new SimpleDateFormat("EEEE");
+ return dayFormat.format(dateInMillis);
+ }
+ }
+
+ /**
+ * Converts db date format to the format "Month day", e.g "June 24".
+ * @param context Context to use for resource localization
+ * @param dateInMillis The db formatted date string, expected to be of the form specified
+ * in Utility.DATE_FORMAT
+ * @return The day in the form of a string formatted "December 6"
+ */
+ public static String getFormattedMonthDay(Context context, long dateInMillis ) {
+ Time time = new Time();
+ time.setToNow();
+ SimpleDateFormat dbDateFormat = new SimpleDateFormat(Utility.DATE_FORMAT);
+ SimpleDateFormat monthDayFormat = new SimpleDateFormat("MMMM dd");
+ String monthDayString = monthDayFormat.format(dateInMillis);
+ return monthDayString;
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/list_item_forecast.xml b/app/src/main/res/layout/list_item_forecast.xml
index d7bb57759..9e7515765 100644
--- a/app/src/main/res/layout/list_item_forecast.xml
+++ b/app/src/main/res/layout/list_item_forecast.xml
@@ -12,8 +12,7 @@
+ android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"/>
@@ -44,14 +41,12 @@
+ android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"/>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 14ae616c2..12a2c8bf6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,5 +1,5 @@
-
+
imperial
-
+
+
+ Today
+
+
+ Tomorrow
+
+
+ %1$s, %2$s
+
+
\ No newline at end of file