0fbe1531d4c8c24ad40faf7e9fbc46a198b6c7d4
[JavaForFun] /
1 package de.example.exampletdd.fragment.current;
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.List;
15 import java.util.Locale;
16
17 import org.apache.http.client.ClientProtocolException;
18
19 import android.app.DialogFragment;
20 import android.app.ListFragment;
21 import android.content.SharedPreferences;
22 import android.graphics.Bitmap;
23 import android.graphics.BitmapFactory;
24 import android.net.http.AndroidHttpClient;
25 import android.os.AsyncTask;
26 import android.os.Bundle;
27 import android.preference.PreferenceManager;
28 import android.util.Log;
29 import android.widget.ImageView;
30 import android.widget.ListView;
31
32 import com.fasterxml.jackson.core.JsonParseException;
33
34 import de.example.exampletdd.R;
35 import de.example.exampletdd.fragment.ErrorDialogFragment;
36 import de.example.exampletdd.fragment.ProgressDialogFragment;
37 import de.example.exampletdd.fragment.specific.WeatherSpecificDataAdapter;
38 import de.example.exampletdd.fragment.specific.WeatherSpecificDataEntry;
39 import de.example.exampletdd.httpclient.CustomHTTPClient;
40 import de.example.exampletdd.model.GeocodingData;
41 import de.example.exampletdd.model.currentweather.CurrentWeatherData;
42 import de.example.exampletdd.parser.IJPOSWeatherParser;
43 import de.example.exampletdd.parser.JPOSWeatherParser;
44 import de.example.exampletdd.service.WeatherServiceParser;
45 import de.example.exampletdd.service.WeatherServicePersistenceFile;
46
47 public class WeatherInformationCurrentDataFragment extends ListFragment {
48     private boolean mIsFahrenheit;
49     private WeatherServicePersistenceFile mWeatherServicePersistenceFile;
50
51     @Override
52     public void onCreate(final Bundle savedInstanceState) {
53         super.onCreate(savedInstanceState);
54
55         this.mWeatherServicePersistenceFile = new WeatherServicePersistenceFile(this.getActivity());
56         this.mWeatherServicePersistenceFile.removeCurrentWeatherData();
57     }
58
59     @Override
60     public void onActivityCreated(final Bundle savedInstanceState) {
61         super.onActivityCreated(savedInstanceState);
62
63         final ListView listWeatherView = this.getListView();
64         listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
65
66         if (savedInstanceState != null) {
67             // Restore state
68             final CurrentWeatherData currentWeatherData = (CurrentWeatherData) savedInstanceState
69                     .getSerializable("CurrentWeatherData");
70
71             if (currentWeatherData != null) {
72                 try {
73                     this.mWeatherServicePersistenceFile.storeCurrentWeatherData(currentWeatherData);
74                 } catch (final IOException e) {
75                     final DialogFragment newFragment = ErrorDialogFragment
76                             .newInstance(R.string.error_dialog_generic_error);
77                     newFragment.show(this.getFragmentManager(), "errorDialog");
78                 }
79             }
80         }
81
82         this.setHasOptionsMenu(false);
83
84         this.setEmptyText("No data available");
85
86         this.setListShownNoAnimation(false);
87     }
88
89     @Override
90     public void onResume() {
91         super.onResume();
92
93         final SharedPreferences sharedPreferences = PreferenceManager
94                 .getDefaultSharedPreferences(this.getActivity());
95
96         // 1. Update units of measurement.
97         final String keyPreference = this.getResources().getString(
98                 R.string.weather_preferences_units_key);
99         final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
100         final String celsius = this.getResources().getString(
101                 R.string.weather_preferences_units_celsius);
102         if (unitsPreferenceValue.equals(celsius)) {
103             this.mIsFahrenheit = false;
104         } else {
105             this.mIsFahrenheit = true;
106         }
107
108         // 2. Try to restore old information
109         final CurrentWeatherData currentWeatherData = this.mWeatherServicePersistenceFile
110                 .getCurrentWeatherData();
111         if (currentWeatherData != null) {
112             this.updateCurrentWeatherData(currentWeatherData);
113         } else {
114             // 3. Try to update weather data on display with remote
115             this.getRemoteCurrentWeatherInformation();
116         }
117     }
118
119     @Override
120     public void onSaveInstanceState(final Bundle savedInstanceState) {
121
122         // Save state
123         final CurrentWeatherData currentWeatherData = this.mWeatherServicePersistenceFile
124                 .getCurrentWeatherData();
125
126         if (currentWeatherData != null) {
127             savedInstanceState.putSerializable("CurrentWeatherData", currentWeatherData);
128         }
129
130         super.onSaveInstanceState(savedInstanceState);
131     }
132
133
134     public void updateCurrentWeatherData(final CurrentWeatherData currentWeatherData) {
135         final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale
136                 .getDefault());
137         tempFormatter.applyPattern("#####.#####");
138         final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss Z",
139                 Locale.getDefault());
140
141         final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
142
143         final List<WeatherSpecificDataEntry> entries = this.createEmptyEntriesList();
144
145         final WeatherSpecificDataAdapter adapter = new WeatherSpecificDataAdapter(
146                 this.getActivity(), R.layout.weather_data_entry_list);
147
148         if (currentWeatherData.getWeather().size() > 0) {
149             entries.set(0,
150                     new WeatherSpecificDataEntry(this.getString(R.string.text_field_description),
151                             currentWeatherData.getWeather().get(0).getDescription()));
152         }
153
154         if (currentWeatherData.getMain().getTemp() != null) {
155             double conversion = (Double) currentWeatherData.getMain().getTemp();
156             conversion = conversion - tempUnits;
157             entries.set(1, new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem),
158                     tempFormatter.format(conversion)));
159         }
160
161         if (currentWeatherData.getMain().getTemp_max() != null) {
162             double conversion = (Double) currentWeatherData.getMain().getTemp_max();
163             conversion = conversion - tempUnits;
164             entries.set(2, new WeatherSpecificDataEntry(
165                     this.getString(R.string.text_field_tem_max), tempFormatter.format(conversion)));
166         }
167
168         if (currentWeatherData.getMain().getTemp_max() != null) {
169             double conversion = (Double) currentWeatherData.getMain().getTemp_min();
170             conversion = conversion - tempUnits;
171             entries.set(3, new WeatherSpecificDataEntry(
172                     this.getString(R.string.text_field_tem_min), tempFormatter.format(conversion)));
173         }
174
175         if (currentWeatherData.getSys().getSunrise() != null) {
176             final long unixTime = (Long) currentWeatherData.getSys().getSunrise();
177             final Date unixDate = new Date(unixTime * 1000L);
178             final String dateFormatUnix = dateFormat.format(unixDate);
179             entries.set(4,
180                     new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_rise),
181                             dateFormatUnix));
182         }
183
184         if (currentWeatherData.getSys().getSunset() != null) {
185             final long unixTime = (Long) currentWeatherData.getSys().getSunset();
186             final Date unixDate = new Date(unixTime * 1000L);
187             final String dateFormatUnix = dateFormat.format(unixDate);
188             entries.set(5, new WeatherSpecificDataEntry(
189                     this.getString(R.string.text_field_sun_set), dateFormatUnix));
190         }
191
192         if (currentWeatherData.getClouds().getAll() != null) {
193             final double cloudiness = (Double) currentWeatherData.getClouds().getAll();
194             entries.set(6,
195                     new WeatherSpecificDataEntry(this.getString(R.string.text_field_cloudiness),
196                             tempFormatter.format(cloudiness)));
197         }
198
199         if (currentWeatherData.getIconData() != null) {
200             final Bitmap icon = BitmapFactory.decodeByteArray(currentWeatherData.getIconData(), 0,
201                     currentWeatherData.getIconData().length);
202             final ImageView imageIcon = (ImageView) this.getActivity().findViewById(
203                     R.id.weather_picture);
204             imageIcon.setImageBitmap(icon);
205         }
206
207         adapter.addAll(entries);
208         this.setListAdapter(adapter);
209     }
210
211     public class CurrentWeatherTask extends AsyncTask<Object, Void, CurrentWeatherData> {
212         private static final String TAG = "WeatherTask";
213         private final CustomHTTPClient weatherHTTPClient;
214         private final WeatherServiceParser weatherService;
215         private final DialogFragment newFragment;
216
217         public CurrentWeatherTask(final CustomHTTPClient weatherHTTPClient,
218                 final WeatherServiceParser weatherService) {
219             this.weatherHTTPClient = weatherHTTPClient;
220             this.weatherService = weatherService;
221             this.newFragment = ProgressDialogFragment.newInstance(
222                     R.string.progress_dialog_get_remote_data,
223                     WeatherInformationCurrentDataFragment.this
224                     .getString(R.string.progress_dialog_generic_message));
225         }
226
227         @Override
228         protected void onPreExecute() {
229             this.newFragment.show(WeatherInformationCurrentDataFragment.this.getActivity()
230                     .getFragmentManager(), "progressDialog");
231         }
232
233         @Override
234         protected CurrentWeatherData doInBackground(final Object... params) {
235             CurrentWeatherData currentWeatherData = null;
236
237             try {
238                 currentWeatherData = this.doInBackgroundThrowable(params);
239             } catch (final ClientProtocolException e) {
240                 Log.e(TAG, "doInBackground exception: ", e);
241             } catch (final MalformedURLException e) {
242                 Log.e(TAG, "doInBackground exception: ", e);
243             } catch (final URISyntaxException e) {
244                 Log.e(TAG, "doInBackground exception: ", e);
245             } catch (final JsonParseException e) {
246                 Log.e(TAG, "doInBackground exception: ", e);
247             } catch (final IOException e) {
248                 // logger infrastructure swallows UnknownHostException :/
249                 Log.e(TAG, "doInBackground exception: " + e.getMessage(), e);
250             } finally {
251                 this.weatherHTTPClient.close();
252             }
253
254             return currentWeatherData;
255         }
256
257         @Override
258         protected void onPostExecute(final CurrentWeatherData currentWeatherData) {
259             this.weatherHTTPClient.close();
260
261             this.newFragment.dismiss();
262
263             if (currentWeatherData != null) {
264                 try {
265                     this.onPostExecuteThrowable(currentWeatherData);
266                 } catch (final IOException e) {
267                     WeatherInformationCurrentDataFragment.this.setListShown(true);
268                     Log.e(TAG, "WeatherTask onPostExecute exception: ", e);
269                     final DialogFragment newFragment = ErrorDialogFragment
270                             .newInstance(R.string.error_dialog_generic_error);
271                     newFragment.show(
272                             WeatherInformationCurrentDataFragment.this.getFragmentManager(),
273                             "errorDialog");
274                 }
275             } else {
276                 WeatherInformationCurrentDataFragment.this.setListShown(true);
277                 final DialogFragment newFragment = ErrorDialogFragment
278                         .newInstance(R.string.error_dialog_generic_error);
279                 newFragment.show(WeatherInformationCurrentDataFragment.this.getFragmentManager(),
280                         "errorDialog");
281             }
282         }
283
284         @Override
285         protected void onCancelled(final CurrentWeatherData currentWeatherData) {
286             this.weatherHTTPClient.close();
287
288             final DialogFragment newFragment = ErrorDialogFragment
289                     .newInstance(R.string.error_dialog_connection_tiemout);
290             newFragment.show(WeatherInformationCurrentDataFragment.this.getFragmentManager(),
291                     "errorDialog");
292         }
293
294         private CurrentWeatherData doInBackgroundThrowable(final Object... params)
295                 throws ClientProtocolException, MalformedURLException, URISyntaxException,
296                 JsonParseException, IOException {
297
298             // 1. Coordinates
299             final GeocodingData geocodingData = (GeocodingData) params[0];
300
301             final String APIVersion = WeatherInformationCurrentDataFragment.this.getResources()
302                     .getString(R.string.api_version);
303
304             // 2. Today
305             final String urlAPI = WeatherInformationCurrentDataFragment.this.getResources()
306                     .getString(R.string.uri_api_weather_today);
307             final String url = this.weatherService.createURIAPITodayWeather(urlAPI, APIVersion,
308                     geocodingData.getLatitude(), geocodingData.getLongitude());
309             final String jsonData = this.weatherHTTPClient.retrieveDataAsString(new URL(url));
310             final CurrentWeatherData currentWeatherData = this.weatherService
311                     .retrieveCurrentWeatherDataFromJPOS(jsonData);
312             final Calendar now = Calendar.getInstance();
313             currentWeatherData.setDate(now.getTime());
314
315
316             return currentWeatherData;
317         }
318
319         private void onPostExecuteThrowable(final CurrentWeatherData currentWeatherData)
320                 throws FileNotFoundException, IOException {
321
322             WeatherInformationCurrentDataFragment.this.mWeatherServicePersistenceFile
323             .storeCurrentWeatherData(currentWeatherData);
324
325             WeatherInformationCurrentDataFragment.this.updateCurrentWeatherData(currentWeatherData);
326         }
327     }
328
329     private void getRemoteCurrentWeatherInformation() {
330
331         final GeocodingData geocodingData = this.mWeatherServicePersistenceFile.getGeocodingData();
332
333         if (geocodingData != null) {
334             final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
335             final WeatherServiceParser weatherService = new WeatherServiceParser(JPOSWeatherParser);
336             final AndroidHttpClient httpClient = AndroidHttpClient
337                     .newInstance("Android Weather Information Agent");
338             final CustomHTTPClient HTTPweatherClient = new CustomHTTPClient(httpClient);
339
340             final CurrentWeatherTask weatherTask = new CurrentWeatherTask(HTTPweatherClient,
341                     weatherService);
342
343             weatherTask.execute(geocodingData);
344         }
345     }
346
347     private List<WeatherSpecificDataEntry> createEmptyEntriesList() {
348         final List<WeatherSpecificDataEntry> entries = new ArrayList<WeatherSpecificDataEntry>();
349         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_description),
350                 null));
351         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem), null));
352         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem_max), null));
353         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem_min), null));
354         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_rise), null));
355         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_set), null));
356         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_cloudiness),
357                 null));
358         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_rain_time),
359                 null));
360         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_rain_amount),
361                 null));
362         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_wind_speed),
363                 null));
364         entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_humidity), null));
365
366         return entries;
367     }
368 }