1 package de.example.exampletdd.fragment.overview;
3 import java.io.FileNotFoundException;
4 import java.io.IOException;
5 import java.net.MalformedURLException;
6 import java.net.URISyntaxException;
8 import java.text.DecimalFormat;
9 import java.text.NumberFormat;
10 import java.text.SimpleDateFormat;
11 import java.util.ArrayList;
12 import java.util.Calendar;
13 import java.util.Date;
14 import java.util.List;
15 import java.util.Locale;
17 import org.apache.http.client.ClientProtocolException;
19 import android.app.DialogFragment;
20 import android.app.ListFragment;
21 import android.content.ComponentName;
22 import android.content.Intent;
23 import android.content.SharedPreferences;
24 import android.graphics.Bitmap;
25 import android.graphics.BitmapFactory;
26 import android.net.http.AndroidHttpClient;
27 import android.os.AsyncTask;
28 import android.os.Bundle;
29 import android.os.Parcelable;
30 import android.preference.PreferenceManager;
31 import android.util.Log;
32 import android.view.View;
33 import android.widget.ListView;
35 import com.fasterxml.jackson.core.JsonParseException;
37 import de.example.exampletdd.R;
38 import de.example.exampletdd.activityinterface.GetWeather;
39 import de.example.exampletdd.fragment.ErrorDialogFragment;
40 import de.example.exampletdd.fragment.ProgressDialogFragment;
41 import de.example.exampletdd.fragment.specific.WeatherInformationSpecificDataFragment;
42 import de.example.exampletdd.httpclient.CustomHTTPClient;
43 import de.example.exampletdd.model.GeocodingData;
44 import de.example.exampletdd.model.forecastweather.ForecastWeatherData;
45 import de.example.exampletdd.parser.IJPOSWeatherParser;
46 import de.example.exampletdd.parser.JPOSWeatherParser;
47 import de.example.exampletdd.service.WeatherServiceParser;
48 import de.example.exampletdd.service.WeatherServicePersistenceFile;
50 public class WeatherInformationOverviewFragment extends ListFragment implements GetWeather {
51 private boolean mIsFahrenheit;
52 private String mDayForecast;
53 private WeatherServicePersistenceFile mWeatherServicePersistenceFile;
54 private Parcelable mListState;
57 public void onCreate(final Bundle savedInstanceState) {
58 super.onCreate(savedInstanceState);
60 final SharedPreferences sharedPreferences = PreferenceManager
61 .getDefaultSharedPreferences(this.getActivity());
62 final String keyPreference = this.getResources().getString(
63 R.string.weather_preferences_day_forecast_key);
64 this.mDayForecast = sharedPreferences.getString(keyPreference, "");
66 this.mWeatherServicePersistenceFile = new WeatherServicePersistenceFile(this.getActivity());
67 this.mWeatherServicePersistenceFile.removeForecastWeatherData();
71 public void onActivityCreated(final Bundle savedInstanceState) {
72 super.onActivityCreated(savedInstanceState);
74 final ListView listWeatherView = this.getListView();
75 listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
77 if (savedInstanceState != null) {
79 final ForecastWeatherData forecastWeatherData = (ForecastWeatherData) savedInstanceState
80 .getSerializable("ForecastWeatherData");
82 if (forecastWeatherData != null) {
84 this.mWeatherServicePersistenceFile
85 .storeForecastWeatherData(forecastWeatherData);
86 } catch (final IOException e) {
87 final DialogFragment newFragment = ErrorDialogFragment
88 .newInstance(R.string.error_dialog_generic_error);
89 newFragment.show(this.getFragmentManager(), "errorDialog");
93 this.mListState = savedInstanceState.getParcelable("ListState");
96 this.setHasOptionsMenu(false);
98 final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(
99 this.getActivity(), R.layout.weather_main_entry_list);
102 this.setEmptyText("Press download to receive weather information");
104 this.setListAdapter(adapter);
105 this.setListShown(true);
106 this.setListShownNoAnimation(true);
110 public void onListItemClick(final ListView l, final View v, final int position, final long id) {
111 final WeatherInformationSpecificDataFragment fragment = (WeatherInformationSpecificDataFragment) this.getFragmentManager()
112 .findFragmentById(R.id.weather_specific_data__fragment);
113 if (fragment == null) {
115 final Intent intent = new Intent("de.example.exampletdd.WEATHERINFO").
116 setComponent(new ComponentName("de.example.exampletdd",
117 "de.example.exampletdd.WeatherInformationSpecificDataActivity"));
118 intent.putExtra("CHOSEN_DAY", (int) id);
119 WeatherInformationOverviewFragment.this.getActivity().startActivity(intent);
122 fragment.getWeatherByDay((int) id);
127 public void onSaveInstanceState(final Bundle savedInstanceState) {
130 final ForecastWeatherData forecastWeatherData = this.mWeatherServicePersistenceFile
131 .getForecastWeatherData();
133 if (forecastWeatherData != null) {
134 savedInstanceState.putSerializable("ForecastWeatherData", forecastWeatherData);
137 this.mListState = this.getListView().onSaveInstanceState();
138 savedInstanceState.putParcelable("ListState", this.mListState);
140 super.onSaveInstanceState(savedInstanceState);
144 public void getRemoteWeatherInformation() {
146 final GeocodingData geocodingData = this.mWeatherServicePersistenceFile.getGeocodingData();
148 if (geocodingData != null) {
149 final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
150 final WeatherServiceParser weatherService = new WeatherServiceParser(
152 final AndroidHttpClient httpClient = AndroidHttpClient
153 .newInstance("Android Weather Information Agent");
154 final CustomHTTPClient HTTPweatherClient = new CustomHTTPClient(
157 final ForecastWeatherTask weatherTask = new ForecastWeatherTask(HTTPweatherClient,
161 weatherTask.execute(geocodingData);
166 public void getWeatherByDay(final int chosenDay) {
170 public void updateForecastWeatherData(final ForecastWeatherData forecastWeatherData) {
171 final List<WeatherOverviewEntry> entries = new ArrayList<WeatherOverviewEntry>();
172 final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(this.getActivity(),
173 R.layout.weather_main_entry_list);
176 final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
177 tempFormatter.applyPattern("#####.##");
178 final SimpleDateFormat dayNameFormatter = new SimpleDateFormat("EEE", Locale.US);
179 final SimpleDateFormat monthAndDayNumberormatter = new SimpleDateFormat("MMM d", Locale.US);
180 final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
181 final String symbol = this.mIsFahrenheit ? "ºF" : "ºC";
184 final Calendar calendar = Calendar.getInstance();
185 for (final de.example.exampletdd.model.forecastweather.List forecast : forecastWeatherData
190 if ((forecast.getWeather().size() > 0) &&
191 (forecast.getWeather().get(0).getIcon() != null) &&
192 (IconsList.getIcon(forecast.getWeather().get(0).getIcon()) != null)) {
193 final String icon = forecast.getWeather().get(0).getIcon();
194 picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon)
195 .getResourceDrawable());
197 picture = BitmapFactory.decodeResource(this.getResources(),
198 R.drawable.weather_severe_alert);
201 final Long forecastUNIXDate = (Long) forecast.getDt();
202 calendar.setTimeInMillis(forecastUNIXDate * 1000L);
203 final Date dayTime = calendar.getTime();
204 final String dayTextName = dayNameFormatter.format(dayTime);
205 final String monthAndDayNumberText = monthAndDayNumberormatter.format(dayTime);
207 Double maxTemp = null;
208 if (forecast.getTemp().getMax() != null) {
209 maxTemp = (Double) forecast.getTemp().getMax();
210 maxTemp = maxTemp - tempUnits;
213 Double minTemp = null;
214 if (forecast.getTemp().getMin() != null) {
215 minTemp = (Double) forecast.getTemp().getMin();
216 minTemp = minTemp - tempUnits;
219 if ((maxTemp != null) && (minTemp != null)) {
220 entries.add(new WeatherOverviewEntry(dayTextName, monthAndDayNumberText,
221 tempFormatter.format(maxTemp) + symbol, tempFormatter.format(minTemp) + symbol,
226 this.setListAdapter(null);
227 adapter.addAll(entries);
228 this.setListAdapter(adapter);
232 public void onResume() {
235 final SharedPreferences sharedPreferences = PreferenceManager
236 .getDefaultSharedPreferences(this.getActivity());
238 // 1. Update units of measurement.
239 String keyPreference = this.getResources().getString(
240 R.string.weather_preferences_units_key);
241 final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
242 final String celsius = this.getResources().getString(
243 R.string.weather_preferences_units_celsius);
244 if (unitsPreferenceValue.equals(celsius)) {
245 this.mIsFahrenheit = false;
247 this.mIsFahrenheit = true;
250 // 2. Update number day forecast.
251 keyPreference = this.getResources().getString(
252 R.string.weather_preferences_day_forecast_key);
253 this.mDayForecast = sharedPreferences.getString(keyPreference, "");
256 // 3. Update forecast weather data on display.
257 final ForecastWeatherData forecastWeatherData = this.mWeatherServicePersistenceFile
258 .getForecastWeatherData();
259 if ((this.mListState != null) && (forecastWeatherData != null)) {
260 this.updateForecastWeatherData(forecastWeatherData);
261 this.getListView().onRestoreInstanceState(this.mListState);
262 } else if (forecastWeatherData != null) {
263 this.updateForecastWeatherData(forecastWeatherData);
268 public class ForecastWeatherTask extends AsyncTask<Object, Void, ForecastWeatherData> {
269 private static final String TAG = "ForecastWeatherTask";
270 private final CustomHTTPClient weatherHTTPClient;
271 private final WeatherServiceParser weatherService;
272 private final DialogFragment newFragment;
274 public ForecastWeatherTask(final CustomHTTPClient weatherHTTPClient,
275 final WeatherServiceParser weatherService) {
276 this.weatherHTTPClient = weatherHTTPClient;
277 this.weatherService = weatherService;
278 this.newFragment = ProgressDialogFragment.newInstance(
279 R.string.progress_dialog_get_remote_data,
280 WeatherInformationOverviewFragment.this
281 .getString(R.string.progress_dialog_generic_message));
285 protected void onPreExecute() {
286 this.newFragment.show(WeatherInformationOverviewFragment.this.getActivity()
287 .getFragmentManager(), "progressDialog");
291 protected ForecastWeatherData doInBackground(final Object... params) {
292 ForecastWeatherData forecastWeatherData = null;
295 forecastWeatherData = this.doInBackgroundThrowable(params);
296 } catch (final ClientProtocolException e) {
297 Log.e(TAG, "doInBackground exception: ", e);
298 } catch (final MalformedURLException e) {
299 Log.e(TAG, "doInBackground exception: ", e);
300 } catch (final URISyntaxException e) {
301 Log.e(TAG, "doInBackground exception: ", e);
302 } catch (final JsonParseException e) {
303 Log.e(TAG, "doInBackground exception: ", e);
304 } catch (final IOException e) {
305 // logger infrastructure swallows UnknownHostException :/
306 Log.e(TAG, "doInBackground exception: " + e.getMessage(), e);
308 this.weatherHTTPClient.close();
311 return forecastWeatherData;
315 protected void onPostExecute(final ForecastWeatherData weatherData) {
316 this.weatherHTTPClient.close();
318 this.newFragment.dismiss();
320 if (weatherData != null) {
322 this.onPostExecuteThrowable(weatherData);
323 } catch (final IOException e) {
324 Log.e(TAG, "WeatherTask onPostExecute exception: ", e);
325 final DialogFragment newFragment = ErrorDialogFragment
326 .newInstance(R.string.error_dialog_generic_error);
327 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
330 final DialogFragment newFragment = ErrorDialogFragment
331 .newInstance(R.string.error_dialog_generic_error);
332 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
337 protected void onCancelled(final ForecastWeatherData weatherData) {
338 this.weatherHTTPClient.close();
340 final DialogFragment newFragment = ErrorDialogFragment
341 .newInstance(R.string.error_dialog_connection_tiemout);
342 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
345 private ForecastWeatherData doInBackgroundThrowable(final Object... params)
346 throws ClientProtocolException, MalformedURLException,
347 URISyntaxException, JsonParseException, IOException {
350 final GeocodingData geocodingData = (GeocodingData) params[0];
353 final String APIVersion = WeatherInformationOverviewFragment.this.getResources()
354 .getString(R.string.api_version);
356 final String urlAPI = WeatherInformationOverviewFragment.this.getResources()
357 .getString(R.string.uri_api_weather_forecast);
358 final String url = this.weatherService.createURIAPIForecastWeather(urlAPI, APIVersion,
359 geocodingData.getLatitude(), geocodingData.getLongitude(), WeatherInformationOverviewFragment.this.mDayForecast);
360 final String jsonData = this.weatherHTTPClient.retrieveDataAsString(new URL(url));
361 final ForecastWeatherData forecastWeatherData = this.weatherService
362 .retrieveForecastWeatherDataFromJPOS(jsonData);
364 return forecastWeatherData;
367 private void onPostExecuteThrowable(final ForecastWeatherData forecastWeatherData)
368 throws FileNotFoundException, IOException {
369 WeatherInformationOverviewFragment.this.mWeatherServicePersistenceFile
370 .storeForecastWeatherData(forecastWeatherData);
372 WeatherInformationOverviewFragment.this.updateForecastWeatherData(forecastWeatherData);