From e9f367e864077c6f3bf942f98b08d96e9fcd9c6f Mon Sep 17 00:00:00 2001 From: Lyla Date: Mon, 15 Dec 2014 19:58:10 -0800 Subject: [PATCH 01/15] 1.02 Add list item forecast layout --- app/src/main/res/layout/list_item_forecast.xml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 app/src/main/res/layout/list_item_forecast.xml diff --git a/app/src/main/res/layout/list_item_forecast.xml b/app/src/main/res/layout/list_item_forecast.xml new file mode 100644 index 000000000..965bd5714 --- /dev/null +++ b/app/src/main/res/layout/list_item_forecast.xml @@ -0,0 +1,8 @@ + + + \ No newline at end of file From fab554bb01c1edc403663ba1863d191c6a22cefe Mon Sep 17 00:00:00 2001 From: Lyla Date: Mon, 15 Dec 2014 19:58:35 -0800 Subject: [PATCH 02/15] 1.03 Update fragment layout --- app/src/main/res/layout/fragment_main.xml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index bb3dd4604..3fb5f3c1d 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -1,12 +1,18 @@ - - - + + + From de032c1248df4dcf2eb23dc692e8ecfdf01f0220 Mon Sep 17 00:00:00 2001 From: Lyla Date: Mon, 15 Dec 2014 17:34:22 -0800 Subject: [PATCH 03/15] 1.04 Add dummy data --- .../android/sunshine/app/MainActivity.java | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) 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 348cf7efb..deb5421a4 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 @@ -1,14 +1,34 @@ +/* + * Copyright (C) 2014 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; -import android.support.v7.app.ActionBarActivity; -import android.support.v4.app.Fragment; import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + public class MainActivity extends ActionBarActivity { @@ -55,7 +75,19 @@ public PlaceholderFragment() { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { + + // Create some dummy data for the ListView. Here's a sample weekly forecast + String[] data = { + "Mon 6/23 - Sunny - 31/17", + "Tue 6/24 - Foggy - 21/8", + "Wed 6/25 - Cloudy - 22/17", + "Thurs 6/26 - Rainy - 18/11", + "Fri 6/27 - Foggy - 21/10", + "Sat 6/28 - TRAPPED IN WEATHERSTATION - 23/18", + "Sun 6/29 - Sunny - 20/7" + }; + List weekForecast = new ArrayList(Arrays.asList(data)); View rootView = inflater.inflate(R.layout.fragment_main, container, false); return rootView; } From 0281f77274581dec4d93dfb0faff26d9c8b1bf8e Mon Sep 17 00:00:00 2001 From: Lyla Date: Mon, 15 Dec 2014 16:20:42 -0800 Subject: [PATCH 04/15] 1.05 Create ArrayAdapter to eventually use to populate the ListView --- .../android/sunshine/app/MainActivity.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) 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 deb5421a4..beb1e2bd4 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 @@ -23,13 +23,11 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; - +import android.widget.ArrayAdapter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; - - public class MainActivity extends ActionBarActivity { @Override @@ -70,6 +68,8 @@ public boolean onOptionsItemSelected(MenuItem item) { */ public static class PlaceholderFragment extends Fragment { + ArrayAdapter mForecastAdapter; + public PlaceholderFragment() { } @@ -88,6 +88,18 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, "Sun 6/29 - Sunny - 20/7" }; List weekForecast = new ArrayList(Arrays.asList(data)); + + + // Now that we have some dummy forecast data, create an ArrayAdapter. + // The ArrayAdapter will take data from a source (like our dummy forecast) and + // use it to populate the ListView it's attached to. + mForecastAdapter = + new ArrayAdapter( + getActivity(), // The current context (this activity) + R.layout.list_item_forecast, // The name of the layout ID. + R.id.list_item_forecast_textview, // The ID of the textview to populate. + weekForecast); + View rootView = inflater.inflate(R.layout.fragment_main, container, false); return rootView; } From 1d424934d97c8c772978837c0eebb292cbc7f808 Mon Sep 17 00:00:00 2001 From: Lyla Date: Wed, 17 Dec 2014 13:38:45 -0800 Subject: [PATCH 05/15] 1.06 Hook the adapter up to the ListView --- .../java/com/example/android/sunshine/app/MainActivity.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 beb1e2bd4..80b7e8967 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 @@ -24,6 +24,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; +import android.widget.ListView; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -101,6 +102,11 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, weekForecast); View rootView = inflater.inflate(R.layout.fragment_main, container, false); + + // Get a reference to the ListView, and attach this adapter to it. + ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast); + listView.setAdapter(mForecastAdapter); + return rootView; } } From ea6e195702dcb3e1ac1d9abff0242a2ab0c4a785 Mon Sep 17 00:00:00 2001 From: Lyla Date: Wed, 17 Dec 2014 13:41:12 -0800 Subject: [PATCH 06/15] 2.01 Add the network call code --- .../android/sunshine/app/MainActivity.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) 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 80b7e8967..0e4db7b33 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 @@ -18,6 +18,7 @@ import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v7.app.ActionBarActivity; +import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -25,6 +26,12 @@ import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListView; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -107,6 +114,65 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast); listView.setAdapter(mForecastAdapter); + // These two need to be declared outside the try/catch + // so that they can be closed in the finally block. + HttpURLConnection urlConnection = null; + BufferedReader reader = null; + + // Will contain the raw JSON response as a string. + String forecastJsonStr = null; + + try { + // Construct the URL for the OpenWeatherMap query + // Possible parameters are avaiable at OWM's forecast API page, at + // http://openweathermap.org/API#forecast + URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7"); + + // Create the request to OpenWeatherMap, and open the connection + urlConnection = (HttpURLConnection) url.openConnection(); + urlConnection.setRequestMethod("GET"); + urlConnection.connect(); + + // Read the input stream into a String + InputStream inputStream = urlConnection.getInputStream(); + StringBuffer buffer = new StringBuffer(); + if (inputStream == null) { + // Nothing to do. + return null; + } + reader = new BufferedReader(new InputStreamReader(inputStream)); + + String line; + while ((line = reader.readLine()) != null) { + // Since it's JSON, adding a newline isn't necessary (it won't affect parsing) + // But it does make debugging a *lot* easier if you print out the completed + // buffer for debugging. + buffer.append(line + "\n"); + } + + if (buffer.length() == 0) { + // Stream was empty. No point in parsing. + return null; + } + forecastJsonStr = buffer.toString(); + } catch (IOException e) { + Log.e("PlaceholderFragment", "Error ", e); + // If the code didn't successfully get the weather data, there's no point in attemping + // to parse it. + return null; + } finally{ + if (urlConnection != null) { + urlConnection.disconnect(); + } + if (reader != null) { + try { + reader.close(); + } catch (final IOException e) { + Log.e("PlaceholderFragment", "Error closing stream", e); + } + } + } + return rootView; } } From 370d9bf15029062dc3c451be61e6b794a15aec43 Mon Sep 17 00:00:00 2001 From: Lyla Date: Wed, 17 Dec 2014 13:43:38 -0800 Subject: [PATCH 07/15] 2.02 rename Placeholder -> Forecast --- .../com/example/android/sunshine/app/MainActivity.java | 10 +++++----- app/src/main/res/layout/fragment_main.xml | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) 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 0e4db7b33..d764c99a9 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 @@ -44,7 +44,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() - .add(R.id.container, new PlaceholderFragment()) + .add(R.id.container, new ForecastFragment()) .commit(); } } @@ -74,11 +74,11 @@ public boolean onOptionsItemSelected(MenuItem item) { /** * A placeholder fragment containing a simple view. */ - public static class PlaceholderFragment extends Fragment { + public static class ForecastFragment extends Fragment { ArrayAdapter mForecastAdapter; - public PlaceholderFragment() { + public ForecastFragment() { } @Override @@ -156,7 +156,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, } forecastJsonStr = buffer.toString(); } catch (IOException e) { - Log.e("PlaceholderFragment", "Error ", e); + Log.e("ForecastFragment", "Error ", e); // If the code didn't successfully get the weather data, there's no point in attemping // to parse it. return null; @@ -168,7 +168,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, try { reader.close(); } catch (final IOException e) { - Log.e("PlaceholderFragment", "Error closing stream", e); + Log.e("ForecastFragment", "Error closing stream", e); } } } diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index 3fb5f3c1d..372b60d63 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -7,8 +7,7 @@ android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" - tools:context=".MainActivity$PlaceholderFragment"> - + tools:context=".MainActivity$ForecastFragment"> Date: Wed, 17 Dec 2014 13:46:41 -0800 Subject: [PATCH 08/15] 2.02 refactor ForecastFragment into to separate file --- .../sunshine/app/ForecastFragment.java | 140 ++++++++++++++++++ .../android/sunshine/app/MainActivity.java | 122 --------------- 2 files changed, 140 insertions(+), 122 deletions(-) create mode 100644 app/src/main/java/com/example/android/sunshine/app/ForecastFragment.java 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 new file mode 100644 index 000000000..054c4bf0f --- /dev/null +++ b/app/src/main/java/com/example/android/sunshine/app/ForecastFragment.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2014 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; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListView; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Encapsulates fetching the forecast and displaying it as a {@link ListView} layout. + */ +public class ForecastFragment extends Fragment { + + private ArrayAdapter mForecastAdapter; + + public ForecastFragment() { + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + // Create some dummy data for the ListView. Here's a sample weekly forecast + String[] data = { + "Mon 6/23 - Sunny - 31/17", + "Tue 6/24 - Foggy - 21/8", + "Wed 6/25 - Cloudy - 22/17", + "Thurs 6/26 - Rainy - 18/11", + "Fri 6/27 - Foggy - 21/10", + "Sat 6/28 - TRAPPED IN WEATHERSTATION - 23/18", + "Sun 6/29 - Sunny - 20/7" + }; + List weekForecast = new ArrayList(Arrays.asList(data)); + + // Now that we have some dummy forecast data, create an ArrayAdapter. + // The ArrayAdapter will take data from a source (like our dummy forecast) and + // use it to populate the ListView it's attached to. + mForecastAdapter = + new ArrayAdapter( + getActivity(), // The current context (this activity) + R.layout.list_item_forecast, // The name of the layout ID. + R.id.list_item_forecast_textview, // The ID of the textview to populate. + weekForecast); + + View rootView = inflater.inflate(R.layout.fragment_main, container, false); + + // Get a reference to the ListView, and attach this adapter to it. + ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast); + listView.setAdapter(mForecastAdapter); + + // These two need to be declared outside the try/catch + // so that they can be closed in the finally block. + HttpURLConnection urlConnection = null; + BufferedReader reader = null; + + // Will contain the raw JSON response as a string. + String forecastJsonStr = null; + + try { + // Construct the URL for the OpenWeatherMap query + // Possible parameters are avaiable at OWM's forecast API page, at + // http://openweathermap.org/API#forecast + URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7"); + + // Create the request to OpenWeatherMap, and open the connection + urlConnection = (HttpURLConnection) url.openConnection(); + urlConnection.setRequestMethod("GET"); + urlConnection.connect(); + + // Read the input stream into a String + InputStream inputStream = urlConnection.getInputStream(); + StringBuffer buffer = new StringBuffer(); + if (inputStream == null) { + // Nothing to do. + return null; + } + reader = new BufferedReader(new InputStreamReader(inputStream)); + + String line; + while ((line = reader.readLine()) != null) { + // Since it's JSON, adding a newline isn't necessary (it won't affect parsing) + // But it does make debugging a *lot* easier if you print out the completed + // buffer for debugging. + buffer.append(line + "\n"); + } + + if (buffer.length() == 0) { + // Stream was empty. No point in parsing. + return null; + } + forecastJsonStr = buffer.toString(); + } catch (IOException e) { + Log.e("ForecastFragment", "Error ", e); + // If the code didn't successfully get the weather data, there's no point in attemping + // to parse it. + return null; + } finally{ + if (urlConnection != null) { + urlConnection.disconnect(); + } + if (reader != null) { + try { + reader.close(); + } catch (final IOException e) { + Log.e("ForecastFragment", "Error closing stream", e); + } + } + } + + return rootView; + } +} 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 d764c99a9..e8729e77d 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 @@ -16,25 +16,9 @@ package com.example.android.sunshine.app; import android.os.Bundle; -import android.support.v4.app.Fragment; import android.support.v7.app.ActionBarActivity; -import android.util.Log; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ListView; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; public class MainActivity extends ActionBarActivity { @@ -70,110 +54,4 @@ public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } - - /** - * A placeholder fragment containing a simple view. - */ - public static class ForecastFragment extends Fragment { - - ArrayAdapter mForecastAdapter; - - public ForecastFragment() { - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - - // Create some dummy data for the ListView. Here's a sample weekly forecast - String[] data = { - "Mon 6/23 - Sunny - 31/17", - "Tue 6/24 - Foggy - 21/8", - "Wed 6/25 - Cloudy - 22/17", - "Thurs 6/26 - Rainy - 18/11", - "Fri 6/27 - Foggy - 21/10", - "Sat 6/28 - TRAPPED IN WEATHERSTATION - 23/18", - "Sun 6/29 - Sunny - 20/7" - }; - List weekForecast = new ArrayList(Arrays.asList(data)); - - - // Now that we have some dummy forecast data, create an ArrayAdapter. - // The ArrayAdapter will take data from a source (like our dummy forecast) and - // use it to populate the ListView it's attached to. - mForecastAdapter = - new ArrayAdapter( - getActivity(), // The current context (this activity) - R.layout.list_item_forecast, // The name of the layout ID. - R.id.list_item_forecast_textview, // The ID of the textview to populate. - weekForecast); - - View rootView = inflater.inflate(R.layout.fragment_main, container, false); - - // Get a reference to the ListView, and attach this adapter to it. - ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast); - listView.setAdapter(mForecastAdapter); - - // These two need to be declared outside the try/catch - // so that they can be closed in the finally block. - HttpURLConnection urlConnection = null; - BufferedReader reader = null; - - // Will contain the raw JSON response as a string. - String forecastJsonStr = null; - - try { - // Construct the URL for the OpenWeatherMap query - // Possible parameters are avaiable at OWM's forecast API page, at - // http://openweathermap.org/API#forecast - URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7"); - - // Create the request to OpenWeatherMap, and open the connection - urlConnection = (HttpURLConnection) url.openConnection(); - urlConnection.setRequestMethod("GET"); - urlConnection.connect(); - - // Read the input stream into a String - InputStream inputStream = urlConnection.getInputStream(); - StringBuffer buffer = new StringBuffer(); - if (inputStream == null) { - // Nothing to do. - return null; - } - reader = new BufferedReader(new InputStreamReader(inputStream)); - - String line; - while ((line = reader.readLine()) != null) { - // Since it's JSON, adding a newline isn't necessary (it won't affect parsing) - // But it does make debugging a *lot* easier if you print out the completed - // buffer for debugging. - buffer.append(line + "\n"); - } - - if (buffer.length() == 0) { - // Stream was empty. No point in parsing. - return null; - } - forecastJsonStr = buffer.toString(); - } catch (IOException e) { - Log.e("ForecastFragment", "Error ", e); - // If the code didn't successfully get the weather data, there's no point in attemping - // to parse it. - return null; - } finally{ - if (urlConnection != null) { - urlConnection.disconnect(); - } - if (reader != null) { - try { - reader.close(); - } catch (final IOException e) { - Log.e("ForecastFragment", "Error closing stream", e); - } - } - } - - return rootView; - } - } } From 1e4314fb371b6d92400f34d54a77ad5f158fe36d Mon Sep 17 00:00:00 2001 From: Sarah Spikes Date: Mon, 2 Jun 2014 16:59:55 -0700 Subject: [PATCH 09/15] 2.02 Refactor logging string into constant --- .../sunshine/app/ForecastFragment.java | 120 ++++++++++-------- 1 file changed, 65 insertions(+), 55 deletions(-) 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 054c4bf0f..50cc234fc 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 @@ -15,6 +15,7 @@ */ package com.example.android.sunshine.app; +import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.util.Log; @@ -76,65 +77,74 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast); listView.setAdapter(mForecastAdapter); - // These two need to be declared outside the try/catch - // so that they can be closed in the finally block. - HttpURLConnection urlConnection = null; - BufferedReader reader = null; - - // Will contain the raw JSON response as a string. - String forecastJsonStr = null; - - try { - // Construct the URL for the OpenWeatherMap query - // Possible parameters are avaiable at OWM's forecast API page, at - // http://openweathermap.org/API#forecast - URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7"); - - // Create the request to OpenWeatherMap, and open the connection - urlConnection = (HttpURLConnection) url.openConnection(); - urlConnection.setRequestMethod("GET"); - urlConnection.connect(); - - // Read the input stream into a String - InputStream inputStream = urlConnection.getInputStream(); - StringBuffer buffer = new StringBuffer(); - if (inputStream == null) { - // Nothing to do. - return null; - } - reader = new BufferedReader(new InputStreamReader(inputStream)); - - String line; - while ((line = reader.readLine()) != null) { - // Since it's JSON, adding a newline isn't necessary (it won't affect parsing) - // But it does make debugging a *lot* easier if you print out the completed - // buffer for debugging. - buffer.append(line + "\n"); - } + return rootView; + } + + public class FetchWeatherTask extends AsyncTask { + + private final String LOG_TAG = FetchWeatherTask.class.getSimpleName(); + + @Override + protected Void doInBackground(Void... params) { + // These two need to be declared outside the try/catch + // so that they can be closed in the finally block. + HttpURLConnection urlConnection = null; + BufferedReader reader = null; + + // Will contain the raw JSON response as a string. + String forecastJsonStr = null; + + try { + // Construct the URL for the OpenWeatherMap query + // Possible parameters are avaiable at OWM's forecast API page, at + // http://openweathermap.org/API#forecast + URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7"); + + // Create the request to OpenWeatherMap, and open the connection + urlConnection = (HttpURLConnection) url.openConnection(); + urlConnection.setRequestMethod("GET"); + urlConnection.connect(); + + // Read the input stream into a String + InputStream inputStream = urlConnection.getInputStream(); + StringBuffer buffer = new StringBuffer(); + if (inputStream == null) { + // Nothing to do. + return null; + } + reader = new BufferedReader(new InputStreamReader(inputStream)); + + String line; + while ((line = reader.readLine()) != null) { + // Since it's JSON, adding a newline isn't necessary (it won't affect parsing) + // But it does make debugging a *lot* easier if you print out the completed + // buffer for debugging. + buffer.append(line + "\n"); + } - if (buffer.length() == 0) { - // Stream was empty. No point in parsing. + if (buffer.length() == 0) { + // Stream was empty. No point in parsing. + return null; + } + forecastJsonStr = buffer.toString(); + } catch (IOException e) { + Log.e(LOG_TAG, "Error ", e); + // If the code didn't successfully get the weather data, there's no point in attemping + // to parse it. return null; - } - forecastJsonStr = buffer.toString(); - } catch (IOException e) { - Log.e("ForecastFragment", "Error ", e); - // If the code didn't successfully get the weather data, there's no point in attemping - // to parse it. - return null; - } finally{ - if (urlConnection != null) { - urlConnection.disconnect(); - } - if (reader != null) { - try { - reader.close(); - } catch (final IOException e) { - Log.e("ForecastFragment", "Error closing stream", e); + } finally { + if (urlConnection != null) { + urlConnection.disconnect(); + } + if (reader != null) { + try { + reader.close(); + } catch (final IOException e) { + Log.e(LOG_TAG, "Error closing stream", e); + } } } + return null; } - - return rootView; } } From fa5e923fac2b38edb8f2b8db1c93a57725da9da5 Mon Sep 17 00:00:00 2001 From: Sarah Spikes Date: Wed, 28 May 2014 11:08:11 -0700 Subject: [PATCH 10/15] 2.03 Add xml for refresh menu item --- app/src/main/res/menu/forecastfragment.xml | 8 ++++++++ app/src/main/res/values/strings.xml | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/menu/forecastfragment.xml diff --git a/app/src/main/res/menu/forecastfragment.xml b/app/src/main/res/menu/forecastfragment.xml new file mode 100644 index 000000000..50bd1256d --- /dev/null +++ b/app/src/main/res/menu/forecastfragment.xml @@ -0,0 +1,8 @@ + + + + + \ 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 ec03bdf4d..94bda40e4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,8 +1,21 @@ + Sunshine - Hello world! + + Settings + + Refresh + Hello world! + From f7f49a8085563095510dab8ea1f81cac8b00fa9e Mon Sep 17 00:00:00 2001 From: Sarah Spikes Date: Fri, 30 May 2014 13:42:32 -0700 Subject: [PATCH 11/15] 2.04 Inflate menu --- .../sunshine/app/ForecastFragment.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) 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 50cc234fc..2e611d2ec 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 @@ -20,6 +20,9 @@ import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; @@ -45,6 +48,30 @@ public class ForecastFragment extends Fragment { public ForecastFragment() { } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Add this line in order for this fragment to handle menu events. + setHasOptionsMenu(true); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.forecastfragment, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + if (id == R.id.action_refresh) { + return true; + } + return super.onOptionsItemSelected(item); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { From f18784f490e71f6816fa1fe5fb9b5dafff38b93d Mon Sep 17 00:00:00 2001 From: Sarah Spikes Date: Wed, 28 May 2014 12:50:07 -0700 Subject: [PATCH 12/15] 2.05 Execute FetchWeatherTask --- .../java/com/example/android/sunshine/app/ForecastFragment.java | 2 ++ 1 file changed, 2 insertions(+) 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 2e611d2ec..f30d0cc0a 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 @@ -67,6 +67,8 @@ public boolean onOptionsItemSelected(MenuItem item) { // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_refresh) { + FetchWeatherTask weatherTask = new FetchWeatherTask(); + weatherTask.execute(); return true; } return super.onOptionsItemSelected(item); From d1579a4199da55c05b8e71ff2a5f1f404064d88c Mon Sep 17 00:00:00 2001 From: Sarah Spikes Date: Fri, 30 May 2014 13:08:08 -0700 Subject: [PATCH 13/15] 2.06 Add Internet permission --- app/src/main/AndroidManifest.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fcad107a6..54ce75263 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,9 @@ + + + Date: Thu, 29 May 2014 00:45:54 -0700 Subject: [PATCH 14/15] 2.07 Build URL with params --- .../sunshine/app/ForecastFragment.java | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) 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 f30d0cc0a..371d2d36d 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 @@ -15,6 +15,7 @@ */ package com.example.android.sunshine.app; +import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -68,7 +69,7 @@ public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_refresh) { FetchWeatherTask weatherTask = new FetchWeatherTask(); - weatherTask.execute(); + weatherTask.execute("94043"); return true; } return super.onOptionsItemSelected(item); @@ -109,12 +110,18 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, return rootView; } - public class FetchWeatherTask extends AsyncTask { + public class FetchWeatherTask extends AsyncTask { private final String LOG_TAG = FetchWeatherTask.class.getSimpleName(); @Override - protected Void doInBackground(Void... params) { + protected Void doInBackground(String... params) { + + // If there's no zip code, there's nothing to look up. Verify size of params. + if (params.length == 0) { + return null; + } + // These two need to be declared outside the try/catch // so that they can be closed in the finally block. HttpURLConnection urlConnection = null; @@ -123,11 +130,31 @@ protected Void doInBackground(Void... params) { // Will contain the raw JSON response as a string. String forecastJsonStr = null; + String format = "json"; + String units = "metric"; + int numDays = 7; + try { // Construct the URL for the OpenWeatherMap query // Possible parameters are avaiable at OWM's forecast API page, at // http://openweathermap.org/API#forecast - URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7"); + final String FORECAST_BASE_URL = + "http://api.openweathermap.org/data/2.5/forecast/daily?"; + final String QUERY_PARAM = "q"; + 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, params[0]) + .appendQueryParameter(FORMAT_PARAM, format) + .appendQueryParameter(UNITS_PARAM, units) + .appendQueryParameter(DAYS_PARAM, Integer.toString(numDays)) + .build(); + + URL url = new URL(builtUri.toString()); + + Log.v(LOG_TAG, "Built URI " + builtUri.toString()); // Create the request to OpenWeatherMap, and open the connection urlConnection = (HttpURLConnection) url.openConnection(); From affe306abd3afc412b83b009f17ea0704cd3998c Mon Sep 17 00:00:00 2001 From: Chris Lei Date: Tue, 13 Oct 2015 16:05:10 -0700 Subject: [PATCH 15/15] Add API Key Parameter to OpenWeatherMap API Call --- app/build.gradle | 3 +++ .../com/example/android/sunshine/app/ForecastFragment.java | 2 ++ 2 files changed, 5 insertions(+) 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/ForecastFragment.java b/app/src/main/java/com/example/android/sunshine/app/ForecastFragment.java index 371d2d36d..5ad101677 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 @@ -144,12 +144,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());