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.Iterator;
15 import java.util.List;
16 import java.util.Locale;
18 import org.apache.http.client.ClientProtocolException;
20 import android.app.DialogFragment;
21 import android.app.ListFragment;
22 import android.content.ComponentName;
23 import android.content.Intent;
24 import android.content.SharedPreferences;
25 import android.graphics.Bitmap;
26 import android.graphics.BitmapFactory;
27 import android.net.http.AndroidHttpClient;
28 import android.os.AsyncTask;
29 import android.os.Bundle;
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.currentweather.CurrentWeatherData;
45 import de.example.exampletdd.model.forecastweather.ForecastWeatherData;
46 import de.example.exampletdd.parser.IJPOSWeatherParser;
47 import de.example.exampletdd.parser.JPOSWeatherParser;
48 import de.example.exampletdd.service.WeatherServiceParser;
49 import de.example.exampletdd.service.WeatherServicePersistenceFile;
51 public class WeatherInformationOverviewFragment extends ListFragment implements GetWeather {
52 private boolean mIsFahrenheit;
53 private WeatherServicePersistenceFile mWeatherServicePersistenceFile;
56 public void onCreate(final Bundle savedInstanceState) {
57 super.onCreate(savedInstanceState);
59 // final SharedPreferences sharedPreferences = PreferenceManager
60 // .getDefaultSharedPreferences(this.getActivity());
61 // final String keyPreference = this.getResources().getString(
62 // R.string.weather_preferences_language_key);
63 // this.mLanguage = sharedPreferences.getString(
64 // 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();
76 listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
78 if (savedInstanceState != null) {
80 final ForecastWeatherData forecastWeatherData = (ForecastWeatherData) savedInstanceState
81 .getSerializable("ForecastWeatherData");
82 final CurrentWeatherData currentWeatherData = (CurrentWeatherData) savedInstanceState
83 .getSerializable("CurrentWeatherData");
85 if ((forecastWeatherData != null) && (currentWeatherData != null)) {
87 this.mWeatherServicePersistenceFile
88 .storeForecastWeatherData(forecastWeatherData);
89 this.mWeatherServicePersistenceFile.storeCurrentWeatherData(currentWeatherData);
90 } catch (final IOException e) {
91 final DialogFragment newFragment = ErrorDialogFragment
92 .newInstance(R.string.error_dialog_generic_error);
93 newFragment.show(this.getFragmentManager(), "errorDialog");
98 this.setHasOptionsMenu(false);
100 final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(
101 this.getActivity(), R.layout.weather_main_entry_list);
104 this.setEmptyText("Press download to receive weather information");
106 this.setListAdapter(adapter);
107 this.setListShown(true);
108 this.setListShownNoAnimation(true);
112 public void onListItemClick(final ListView l, final View v, final int position, final long id) {
113 final WeatherInformationSpecificDataFragment fragment = (WeatherInformationSpecificDataFragment) this.getFragmentManager()
114 .findFragmentById(R.id.weather_specific_data__fragment);
115 if (fragment == null) {
117 final Intent intent = new Intent("de.example.exampletdd.WEATHERINFO").
118 setComponent(new ComponentName("de.example.exampletdd",
119 "de.example.exampletdd.WeatherInformationSpecificDataActivity"));
120 intent.putExtra("CHOSEN_DAY", id);
121 WeatherInformationOverviewFragment.this.getActivity().startActivity(intent);
124 fragment.getWeatherByDay(position);
129 public void onSaveInstanceState(final Bundle savedInstanceState) {
132 final ForecastWeatherData forecastWeatherData = this.mWeatherServicePersistenceFile
133 .getForecastWeatherData();
135 final CurrentWeatherData currentWeatherData = this.mWeatherServicePersistenceFile
136 .getCurrentWeatherData();
138 if ((forecastWeatherData != null) && (currentWeatherData != null)) {
139 savedInstanceState.putSerializable("ForecastWeatherData", forecastWeatherData);
140 savedInstanceState.putSerializable("CurrentWeatherData", currentWeatherData);
143 super.onSaveInstanceState(savedInstanceState);
147 public void getRemoteWeatherInformation() {
149 final GeocodingData geocodingData = this.mWeatherServicePersistenceFile.getGeocodingData();
151 if (geocodingData != null) {
152 final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
153 final WeatherServiceParser weatherService = new WeatherServiceParser(
155 final AndroidHttpClient httpClient = AndroidHttpClient
156 .newInstance("Android Weather Information Agent");
157 final CustomHTTPClient HTTPweatherClient = new CustomHTTPClient(
160 final WeatherTask weatherTask = new WeatherTask(HTTPweatherClient, weatherService);
163 weatherTask.execute(geocodingData);
168 public void getWeatherByDay(final int chosenDay) {
172 public void updateForecastWeatherData(final WeatherData weatherData) {
173 final List<WeatherOverviewEntry> entries = new ArrayList<WeatherOverviewEntry>();
174 final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(this.getActivity(),
175 R.layout.weather_main_entry_list);
177 final Bitmap picture = BitmapFactory.decodeResource(
178 this.getResources(), R.drawable.ic_02d);
179 final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.getDefault());
180 tempFormatter.applyPattern("#####.##");
181 final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MMM d", Locale.getDefault());
182 final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
183 final String symbol = this.mIsFahrenheit ? "ºF" : "ºC";
185 final CurrentWeatherData currentWeatherData = weatherData.getCurrentWeatherData();
187 String formatMaxTemp;
188 String formatMinTemp;
190 if (currentWeatherData.getMain().getTemp_max() != null) {
191 double maxTemp = (Double) currentWeatherData.getMain().getTemp_max();
192 maxTemp = maxTemp - tempUnits;
193 formatMaxTemp = tempFormatter.format(maxTemp) + symbol;
195 formatMaxTemp = "no data";
197 if (currentWeatherData.getMain().getTemp_min() != null) {
198 double minTemp = (Double) currentWeatherData.getMain().getTemp_min();
199 minTemp = minTemp - tempUnits;
200 formatMinTemp = tempFormatter.format(minTemp) + symbol;
202 formatMinTemp = "no data";
205 entries.add(new WeatherOverviewEntry(dateFormat.format(currentWeatherData.getDate()),
206 formatMaxTemp, formatMinTemp, picture));
209 final ForecastWeatherData forecastWeatherData = weatherData.getForecastWeatherData();
211 final Calendar calendar = Calendar.getInstance();
212 calendar.setTime(currentWeatherData.getDate());
214 final int forecastSize = forecastWeatherData.getList().size();
215 final int chosenForecastDays = 14;
216 final int index = forecastSize < chosenForecastDays ? forecastSize : chosenForecastDays;
217 for (int i = 0; i < index; i++) {
218 calendar.add(Calendar.DAY_OF_MONTH, 1);
220 final de.example.exampletdd.model.forecastweather.List forecast = forecastWeatherData
223 if (forecast.getTemp().getMax() != null) {
224 double maxTemp = (Double) forecast.getTemp().getMax();
225 maxTemp = maxTemp - tempUnits;
226 formatMaxTemp = tempFormatter.format(maxTemp) + symbol;
228 formatMaxTemp = "no data";
231 if (forecast.getTemp().getMin() != null) {
232 double minTemp = (Double) forecast.getTemp().getMin();
233 minTemp = minTemp - tempUnits;
234 formatMinTemp = tempFormatter.format(minTemp) + symbol;
236 formatMinTemp = "no data";
239 final Date day = calendar.getTime();
240 entries.add(new WeatherOverviewEntry(dateFormat.format(day), formatMaxTemp,
241 formatMinTemp, picture));
244 final int leftDays = chosenForecastDays - index;
245 for (int i = 0; i < leftDays; i++) {
246 calendar.add(Calendar.DAY_OF_MONTH, 1);
247 final Date day = calendar.getTime();
248 entries.add(new WeatherOverviewEntry(dateFormat.format(day), "no data", "no data", picture));
251 this.setListAdapter(null);
252 adapter.addAll(entries);
253 this.setListAdapter(adapter);
257 public void onResume() {
260 final SharedPreferences sharedPreferences = PreferenceManager
261 .getDefaultSharedPreferences(this.getActivity());
263 // 1. Update units of measurement.
264 final String keyPreference = this.getResources().getString(
265 R.string.weather_preferences_units_key);
266 final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
267 final String celsius = this.getResources().getString(
268 R.string.weather_preferences_units_celsius);
269 if (unitsPreferenceValue.equals(celsius)) {
270 this.mIsFahrenheit = false;
272 this.mIsFahrenheit = true;
276 // 2. Update forecast weather data on display.
277 final ForecastWeatherData forecastWeatherData = this.mWeatherServicePersistenceFile
278 .getForecastWeatherData();
279 final CurrentWeatherData currentWeatherData = this.mWeatherServicePersistenceFile
280 .getCurrentWeatherData();
281 if ((forecastWeatherData != null) && (currentWeatherData != null)) {
282 final WeatherData weatherData = new WeatherData(forecastWeatherData, currentWeatherData);
283 this.updateForecastWeatherData(weatherData);
287 // 3. If language changed, try to retrieve new data for new language
288 // (new strings with the chosen language)
289 // keyPreference = this.getResources().getString(
290 // R.string.weather_preferences_language_key);
291 // final String languagePreferenceValue = sharedPreferences.getString(
292 // keyPreference, "");
293 // if (!languagePreferenceValue.equals(this.mLanguage)) {
294 // this.mLanguage = languagePreferenceValue;
295 // this.getWeather();
299 public class WeatherTask extends AsyncTask<Object, Void, WeatherData> {
300 private static final String TAG = "WeatherTask";
301 private final CustomHTTPClient weatherHTTPClient;
302 private final WeatherServiceParser weatherService;
303 private final DialogFragment newFragment;
305 public WeatherTask(final CustomHTTPClient weatherHTTPClient,
306 final WeatherServiceParser weatherService) {
307 this.weatherHTTPClient = weatherHTTPClient;
308 this.weatherService = weatherService;
309 this.newFragment = ProgressDialogFragment.newInstance(
310 R.string.progress_dialog_get_remote_data,
311 WeatherInformationOverviewFragment.this
312 .getString(R.string.progress_dialog_generic_message));
316 protected void onPreExecute() {
317 this.newFragment.show(WeatherInformationOverviewFragment.this.getActivity()
318 .getFragmentManager(), "progressDialog");
322 protected WeatherData doInBackground(final Object... params) {
323 WeatherData weatherData = null;
326 weatherData = this.doInBackgroundThrowable(params);
327 } catch (final ClientProtocolException e) {
328 Log.e(TAG, "doInBackground exception: ", e);
329 } catch (final MalformedURLException e) {
330 Log.e(TAG, "doInBackground exception: ", e);
331 } catch (final URISyntaxException e) {
332 Log.e(TAG, "doInBackground exception: ", e);
333 } catch (final JsonParseException e) {
334 Log.e(TAG, "doInBackground exception: ", e);
335 } catch (final IOException e) {
336 // logger infrastructure swallows UnknownHostException :/
337 Log.e(TAG, "doInBackground exception: " + e.getMessage(), e);
339 this.weatherHTTPClient.close();
346 protected void onPostExecute(final WeatherData weatherData) {
347 this.weatherHTTPClient.close();
349 this.newFragment.dismiss();
351 if (weatherData != null) {
353 this.onPostExecuteThrowable(weatherData);
354 } catch (final IOException e) {
355 Log.e(TAG, "WeatherTask onPostExecute exception: ", e);
356 final DialogFragment newFragment = ErrorDialogFragment
357 .newInstance(R.string.error_dialog_generic_error);
358 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
361 final DialogFragment newFragment = ErrorDialogFragment
362 .newInstance(R.string.error_dialog_generic_error);
363 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
368 protected void onCancelled(final WeatherData weatherData) {
369 this.weatherHTTPClient.close();
371 final DialogFragment newFragment = ErrorDialogFragment
372 .newInstance(R.string.error_dialog_connection_tiemout);
373 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
376 private WeatherData doInBackgroundThrowable(final Object... params)
377 throws ClientProtocolException, MalformedURLException,
378 URISyntaxException, JsonParseException, IOException {
379 // final SharedPreferences sharedPreferences = PreferenceManager
380 // .getDefaultSharedPreferences(WeatherInformationOverviewFragment.this
383 // final String keyPreference =
384 // WeatherInformationOverviewFragment.this
385 // .getActivity().getString(
386 // R.string.weather_preferences_language_key);
387 // final String languagePreferenceValue =
388 // sharedPreferences.getString(keyPreference, "");
391 final GeocodingData geocodingData = (GeocodingData) params[0];
394 final Calendar now = Calendar.getInstance();
395 final String APIVersion = WeatherInformationOverviewFragment.this.getResources()
396 .getString(R.string.api_version);
398 String urlAPI = WeatherInformationOverviewFragment.this.getResources()
399 .getString(R.string.uri_api_weather_forecast);
400 String url = this.weatherService.createURIAPIForecastWeather(urlAPI, APIVersion,
401 geocodingData.getLatitude(), geocodingData.getLongitude(), "14");
402 String jsonData = this.weatherHTTPClient.retrieveDataAsString(new URL(url));
403 final ForecastWeatherData forecastWeatherData = this.weatherService
404 .retrieveForecastWeatherDataFromJPOS(jsonData);
405 final Iterator<de.example.exampletdd.model.forecastweather.List> iterator =
406 forecastWeatherData.getList().iterator();
407 while (iterator.hasNext()) {
408 final de.example.exampletdd.model.forecastweather.List forecast = iterator.next();
410 final Long forecastUNIXDate = (Long) forecast.getDt();
411 final Calendar forecastCalendar = Calendar.getInstance();
412 forecastCalendar.setTimeInMillis(forecastUNIXDate * 1000L);
413 if (now.compareTo(forecastCalendar) == 1) {
420 urlAPI = WeatherInformationOverviewFragment.this.getResources().getString(
421 R.string.uri_api_weather_today);
422 url = this.weatherService.createURIAPITodayWeather(urlAPI, APIVersion,
423 geocodingData.getLatitude(), geocodingData.getLongitude());
424 jsonData = this.weatherHTTPClient.retrieveDataAsString(new URL(url));
425 final CurrentWeatherData currentWeatherData = this.weatherService
426 .retrieveCurrentWeatherDataFromJPOS(jsonData);
427 currentWeatherData.setDate(now.getTime());
429 final WeatherData weatherData = new WeatherData(forecastWeatherData, currentWeatherData);
434 private void onPostExecuteThrowable(final WeatherData weatherData)
435 throws FileNotFoundException, IOException {
436 WeatherInformationOverviewFragment.this.mWeatherServicePersistenceFile
437 .storeForecastWeatherData(weatherData.getForecastWeatherData());
438 WeatherInformationOverviewFragment.this.mWeatherServicePersistenceFile
439 .storeCurrentWeatherData(weatherData.getCurrentWeatherData());
441 WeatherInformationOverviewFragment.this.updateForecastWeatherData(weatherData);
445 private class WeatherData {
446 private final ForecastWeatherData forecastWeatherData;
447 private final CurrentWeatherData currentWeatherData;
449 private WeatherData(final ForecastWeatherData forecastWeatherData, final CurrentWeatherData currentWeatherData) {
450 this.forecastWeatherData = forecastWeatherData;
451 this.currentWeatherData = currentWeatherData;
454 private ForecastWeatherData getForecastWeatherData() {
455 return this.forecastWeatherData;
458 private CurrentWeatherData getCurrentWeatherData() {
459 return this.currentWeatherData;