227e374a2d38eda0989319a2acd88f9508d63efa
[JavaForFun] /
1 package de.example.exampletdd.fragment.overview;
2
3 import java.io.FileNotFoundException;
4 import java.io.IOException;
5 import java.net.MalformedURLException;
6 import java.net.URISyntaxException;
7 import java.net.URL;
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;
17
18 import org.apache.http.client.ClientProtocolException;
19
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;
34
35 import com.fasterxml.jackson.core.JsonParseException;
36
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;
50
51 public class WeatherInformationOverviewFragment extends ListFragment implements GetWeather {
52     private boolean mIsFahrenheit;
53     private WeatherServicePersistenceFile mWeatherServicePersistenceFile;
54
55     @Override
56     public void onCreate(final Bundle savedInstanceState) {
57         super.onCreate(savedInstanceState);
58
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, "");
65
66         this.mWeatherServicePersistenceFile = new WeatherServicePersistenceFile(this.getActivity());
67         this.mWeatherServicePersistenceFile.removeForecastWeatherData();
68     }
69
70     @Override
71     public void onActivityCreated(final Bundle savedInstanceState) {
72         super.onActivityCreated(savedInstanceState);
73
74         final ListView listWeatherView = this.getListView();
75
76         listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
77
78         if (savedInstanceState != null) {
79             // Restore state
80             final ForecastWeatherData forecastWeatherData = (ForecastWeatherData) savedInstanceState
81                     .getSerializable("ForecastWeatherData");
82             final CurrentWeatherData currentWeatherData = (CurrentWeatherData) savedInstanceState
83                     .getSerializable("CurrentWeatherData");
84
85             if ((forecastWeatherData != null) && (currentWeatherData != null)) {
86                 try {
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");
94                 }
95             }
96         }
97
98         this.setHasOptionsMenu(false);
99
100         final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(
101                 this.getActivity(), R.layout.weather_main_entry_list);
102
103
104         this.setEmptyText("Press download to receive weather information");
105
106         this.setListAdapter(adapter);
107         this.setListShown(true);
108         this.setListShownNoAnimation(true);
109     }
110
111     @Override
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) {
116             // handset layout
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);
122         } else {
123             // tablet layout
124             fragment.getWeatherByDay(position);
125         }
126     }
127
128     @Override
129     public void onSaveInstanceState(final Bundle savedInstanceState) {
130
131         // Save state
132         final ForecastWeatherData forecastWeatherData = this.mWeatherServicePersistenceFile
133                 .getForecastWeatherData();
134
135         final CurrentWeatherData currentWeatherData = this.mWeatherServicePersistenceFile
136                 .getCurrentWeatherData();
137
138         if ((forecastWeatherData != null) && (currentWeatherData != null)) {
139             savedInstanceState.putSerializable("ForecastWeatherData", forecastWeatherData);
140             savedInstanceState.putSerializable("CurrentWeatherData", currentWeatherData);
141         }
142
143         super.onSaveInstanceState(savedInstanceState);
144     }
145
146     @Override
147     public void getRemoteWeatherInformation() {
148
149         final GeocodingData geocodingData = this.mWeatherServicePersistenceFile.getGeocodingData();
150
151         if (geocodingData != null) {
152             final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
153             final WeatherServiceParser weatherService = new WeatherServiceParser(
154                     JPOSWeatherParser);
155             final AndroidHttpClient httpClient = AndroidHttpClient
156                     .newInstance("Android Weather Information Agent");
157             final CustomHTTPClient HTTPweatherClient = new CustomHTTPClient(
158                     httpClient);
159
160             final WeatherTask weatherTask = new WeatherTask(HTTPweatherClient, weatherService);
161
162
163             weatherTask.execute(geocodingData);
164         }
165     }
166
167     @Override
168     public void getWeatherByDay(final int chosenDay) {
169         // Nothing to do.
170     }
171
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);
176
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";
184
185         final CurrentWeatherData currentWeatherData = weatherData.getCurrentWeatherData();
186
187         String formatMaxTemp;
188         String formatMinTemp;
189
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;
194         } else {
195             formatMaxTemp = "no data";
196         }
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;
201         } else {
202             formatMinTemp = "no data";
203         }
204
205         entries.add(new WeatherOverviewEntry(dateFormat.format(currentWeatherData.getDate()),
206                 formatMaxTemp, formatMinTemp, picture));
207
208
209         final ForecastWeatherData forecastWeatherData = weatherData.getForecastWeatherData();
210
211         final Calendar calendar = Calendar.getInstance();
212         calendar.setTime(currentWeatherData.getDate());
213
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);
219
220             final de.example.exampletdd.model.forecastweather.List forecast = forecastWeatherData
221                     .getList().get(i);
222
223             if (forecast.getTemp().getMax() != null) {
224                 double maxTemp = (Double) forecast.getTemp().getMax();
225                 maxTemp = maxTemp - tempUnits;
226                 formatMaxTemp = tempFormatter.format(maxTemp) + symbol;
227             } else {
228                 formatMaxTemp = "no data";
229             }
230
231             if (forecast.getTemp().getMin() != null) {
232                 double minTemp = (Double) forecast.getTemp().getMin();
233                 minTemp = minTemp - tempUnits;
234                 formatMinTemp = tempFormatter.format(minTemp) + symbol;
235             } else {
236                 formatMinTemp = "no data";
237             }
238
239             final Date day = calendar.getTime();
240             entries.add(new WeatherOverviewEntry(dateFormat.format(day), formatMaxTemp,
241                     formatMinTemp, picture));
242         }
243
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));
249         }
250
251         this.setListAdapter(null);
252         adapter.addAll(entries);
253         this.setListAdapter(adapter);
254     }
255
256     @Override
257     public void onResume() {
258         super.onResume();
259
260         final SharedPreferences sharedPreferences = PreferenceManager
261                 .getDefaultSharedPreferences(this.getActivity());
262
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;
271         } else {
272             this.mIsFahrenheit = true;
273         }
274
275
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);
284         }
285
286
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();
296         // }
297     }
298
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;
304
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));
313         }
314
315         @Override
316         protected void onPreExecute() {
317             this.newFragment.show(WeatherInformationOverviewFragment.this.getActivity()
318                     .getFragmentManager(), "progressDialog");
319         }
320
321         @Override
322         protected WeatherData doInBackground(final Object... params) {
323             WeatherData weatherData = null;
324
325             try {
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);
338             } finally {
339                 this.weatherHTTPClient.close();
340             }
341
342             return weatherData;
343         }
344
345         @Override
346         protected void onPostExecute(final WeatherData weatherData) {
347             this.weatherHTTPClient.close();
348
349             this.newFragment.dismiss();
350
351             if (weatherData != null) {
352                 try {
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");
359                 }
360             } else {
361                 final DialogFragment newFragment = ErrorDialogFragment
362                         .newInstance(R.string.error_dialog_generic_error);
363                 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
364             }
365         }
366
367         @Override
368         protected void onCancelled(final WeatherData weatherData) {
369             this.weatherHTTPClient.close();
370
371             final DialogFragment newFragment = ErrorDialogFragment
372                     .newInstance(R.string.error_dialog_connection_tiemout);
373             newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
374         }
375
376         private WeatherData doInBackgroundThrowable(final Object... params)
377                 throws ClientProtocolException, MalformedURLException,
378                 URISyntaxException, JsonParseException, IOException {
379             // final SharedPreferences sharedPreferences = PreferenceManager
380             // .getDefaultSharedPreferences(WeatherInformationOverviewFragment.this
381             // .getActivity());
382             //
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, "");
389
390             // 1. Coordinates
391             final GeocodingData geocodingData = (GeocodingData) params[0];
392
393
394             final Calendar now = Calendar.getInstance();
395             final String APIVersion = WeatherInformationOverviewFragment.this.getResources()
396                     .getString(R.string.api_version);
397             // 2. Forecast
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();
409
410                 final Long forecastUNIXDate = (Long) forecast.getDt();
411                 final Calendar forecastCalendar = Calendar.getInstance();
412                 forecastCalendar.setTimeInMillis(forecastUNIXDate * 1000L);
413                 if (now.compareTo(forecastCalendar) == 1) {
414                     iterator.remove();
415                 }
416             }
417
418
419             // 3. Today
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());
428
429             final WeatherData weatherData = new WeatherData(forecastWeatherData, currentWeatherData);
430
431             return weatherData;
432         }
433
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());
440
441             WeatherInformationOverviewFragment.this.updateForecastWeatherData(weatherData);
442         }
443     }
444
445     private class WeatherData {
446         private final ForecastWeatherData forecastWeatherData;
447         private final CurrentWeatherData currentWeatherData;
448
449         private WeatherData(final ForecastWeatherData forecastWeatherData, final CurrentWeatherData currentWeatherData) {
450             this.forecastWeatherData = forecastWeatherData;
451             this.currentWeatherData = currentWeatherData;
452         }
453
454         private ForecastWeatherData getForecastWeatherData() {
455             return this.forecastWeatherData;
456         }
457
458         private CurrentWeatherData getCurrentWeatherData() {
459             return this.currentWeatherData;
460         }
461     }
462 }