5061dd5808fd1f709b196fc936e3ab3e7e594b33
[JavaForFun] /
1 package de.example.exampletdd.fragment.overview;
2
3 import java.io.FileNotFoundException;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.ObjectInputStream;
7 import java.io.ObjectOutputStream;
8 import java.io.OutputStream;
9 import java.io.StreamCorruptedException;
10 import java.net.MalformedURLException;
11 import java.net.URISyntaxException;
12 import java.net.URL;
13 import java.text.DecimalFormat;
14 import java.text.NumberFormat;
15 import java.text.SimpleDateFormat;
16 import java.util.ArrayList;
17 import java.util.Calendar;
18 import java.util.Collection;
19 import java.util.Date;
20 import java.util.List;
21 import java.util.Locale;
22
23 import org.apache.http.client.ClientProtocolException;
24 import org.json.JSONException;
25
26 import android.app.DialogFragment;
27 import android.app.ListFragment;
28 import android.content.ComponentName;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.content.SharedPreferences;
32 import android.graphics.Bitmap;
33 import android.graphics.BitmapFactory;
34 import android.net.http.AndroidHttpClient;
35 import android.os.AsyncTask;
36 import android.os.Bundle;
37 import android.preference.PreferenceManager;
38 import android.util.Log;
39 import android.view.View;
40 import android.widget.ListView;
41 import de.example.exampletdd.R;
42 import de.example.exampletdd.activityinterface.GetWeather;
43 import de.example.exampletdd.fragment.ErrorDialogFragment;
44 import de.example.exampletdd.fragment.ProgressDialogFragment;
45 import de.example.exampletdd.fragment.specific.WeatherInformationSpecificDataFragment;
46 import de.example.exampletdd.httpclient.WeatherHTTPClient;
47 import de.example.exampletdd.model.GeocodingData;
48 import de.example.exampletdd.model.WeatherData;
49 import de.example.exampletdd.parser.IJPOSWeatherParser;
50 import de.example.exampletdd.parser.JPOSWeatherParser;
51 import de.example.exampletdd.service.WeatherService;
52
53 public class WeatherInformationOverviewFragment extends ListFragment implements
54 GetWeather {
55     private static final String WEATHER_DATA_FILE = "weatherdata.file";
56     private static final String WEATHER_GEOCODING_FILE = "weathergeocoding.file";
57     private static final String TAG = "WeatherInformationOverviewFragment";
58     private boolean mIsFahrenheit;
59     private String mLanguage;
60
61     @Override
62     public void onCreate(final Bundle savedInstanceState) {
63         super.onCreate(savedInstanceState);
64
65         this.getActivity().deleteFile(WEATHER_DATA_FILE);
66
67         final SharedPreferences sharedPreferences = PreferenceManager
68                 .getDefaultSharedPreferences(this.getActivity());
69         final String keyPreference = this.getResources().getString(
70                 R.string.weather_preferences_language_key);
71         this.mLanguage = sharedPreferences.getString(
72                 keyPreference, "");
73     }
74
75     @Override
76     public void onActivityCreated(final Bundle savedInstanceState) {
77         super.onActivityCreated(savedInstanceState);
78
79         final ListView listWeatherView = this.getListView();
80
81         listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
82
83         if (savedInstanceState != null) {
84             // Restore state
85             final WeatherData weatherData = (WeatherData) savedInstanceState
86                     .getSerializable("weatherData");
87             try {
88                 this.storeWeatherDataToFile(weatherData);
89             } catch (final IOException e) {
90                 final DialogFragment newFragment = ErrorDialogFragment
91                         .newInstance(R.string.error_dialog_generic_error);
92                 newFragment.show(this.getFragmentManager(), "errorDialog");
93             }
94         }
95
96         this.setHasOptionsMenu(false);
97
98         final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(
99                 this.getActivity(), R.layout.weather_main_entry_list);
100
101         final Collection<WeatherOverviewEntry> entries = this
102                 .createEmptyEntriesList();
103
104         this.setListAdapter(null);
105         adapter.addAll(entries);
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) 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.specific.WeatherInformationSpecificDataActivity"));
120             WeatherInformationOverviewFragment.this.getActivity().startActivity(intent);
121         } else {
122             // tablet layout
123             fragment.getWeather();
124         }
125     }
126
127     @Override
128     public void onSaveInstanceState(final Bundle savedInstanceState) {
129
130         // Save state
131         WeatherData weatherData = null;
132         try {
133             weatherData = this.restoreWeatherDataFromFile();
134         } catch (final StreamCorruptedException e) {
135             Log.e(TAG, "onResume exception: ", e);
136         } catch (final FileNotFoundException e) {
137             Log.e(TAG, "onResume exception: ", e);
138         } catch (final IOException e) {
139             Log.e(TAG, "onResume exception: ", e);
140         } catch (final ClassNotFoundException e) {
141             Log.e(TAG, "onResume exception: ", e);
142         }
143
144         if (weatherData != null) {
145             savedInstanceState.putSerializable("weatherData", weatherData);
146         }
147
148         super.onSaveInstanceState(savedInstanceState);
149     }
150
151     @Override
152     public void getWeather() {
153
154         GeocodingData geocodingData = null;
155         try {
156             geocodingData = this.restoreGeocodingDataFromFile();
157         } catch (final StreamCorruptedException e) {
158             Log.e(TAG, "onResume exception: ", e);
159         } catch (final FileNotFoundException e) {
160             Log.e(TAG, "onResume exception: ", e);
161         } catch (final IOException e) {
162             Log.e(TAG, "onResume exception: ", e);
163         } catch (final ClassNotFoundException e) {
164             Log.e(TAG, "onResume exception: ", e);
165         }
166
167         if (geocodingData != null) {
168             final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
169             final WeatherService weatherService = new WeatherService(
170                     JPOSWeatherParser);
171             final AndroidHttpClient httpClient = AndroidHttpClient
172                     .newInstance("Android Weather Information Agent");
173             final WeatherHTTPClient HTTPweatherClient = new WeatherHTTPClient(
174                     httpClient);
175
176             final WeatherTask weatherTask = new WeatherTask(HTTPweatherClient, weatherService);
177
178
179             weatherTask.execute(geocodingData);
180         }
181     }
182
183     public void updateWeatherData(final WeatherData weatherData) {
184         final List<WeatherOverviewEntry> entries = this.createEmptyEntriesList();
185         final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(this.getActivity(),
186                 R.layout.weather_main_entry_list);
187
188         // Bitmap picture = null;
189         //
190         // if (weatherData.getWeather().getIcon() != null) {
191         // picture= BitmapFactory.decodeByteArray(
192         // weatherData.getIconData(), 0,
193         // weatherData.getIconData().length);
194         // }
195
196         final Bitmap picture = BitmapFactory.decodeResource(
197                 this.getResources(), R.drawable.ic_02d);
198         final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.getDefault());
199         tempFormatter.applyPattern("#####.##");
200         final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MMM d", Locale.getDefault());
201         final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
202         double temp = weatherData.getMain().getTemp();
203         temp = temp - tempUnits;
204         double maxTemp = weatherData.getMain().getMaxTemp();
205         maxTemp = maxTemp - tempUnits;
206         double minTemp = weatherData.getMain().getMinTemp();
207         minTemp = minTemp - tempUnits;
208
209         final Calendar now = Calendar.getInstance();
210         if (weatherData.getWeather() != null) {
211             for (int i = 0; i<15; i++) {
212                 final Date day = now.getTime();
213                 entries.set(i, new WeatherOverviewEntry(dateFormat.format(day),
214                         tempFormatter.format(temp), tempFormatter
215                         .format(maxTemp), tempFormatter
216                         .format(minTemp), picture));
217                 now.add(Calendar.DAY_OF_MONTH, 1);
218             }
219         }
220
221         this.setListAdapter(null);
222         adapter.addAll(entries);
223         this.setListAdapter(adapter);
224     }
225
226     @Override
227     public void onResume() {
228         super.onResume();
229
230         final SharedPreferences sharedPreferences = PreferenceManager
231                 .getDefaultSharedPreferences(this.getActivity());
232
233         // 1. Update units of measurement.
234         String keyPreference = this.getResources().getString(
235                 R.string.weather_preferences_units_key);
236         final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
237         final String celsius = this.getResources().getString(
238                 R.string.weather_preferences_units_celsius);
239         if (unitsPreferenceValue.equals(celsius)) {
240             this.mIsFahrenheit = false;
241         } else {
242             this.mIsFahrenheit = true;
243         }
244
245
246         // 2. Update current data on display.
247         WeatherData weatherData = null;
248         try {
249             weatherData = this.restoreWeatherDataFromFile();
250         } catch (final StreamCorruptedException e) {
251             Log.e(TAG, "onResume exception: ", e);
252         } catch (final FileNotFoundException e) {
253             Log.e(TAG, "onResume exception: ", e);
254         } catch (final IOException e) {
255             Log.e(TAG, "onResume exception: ", e);
256         } catch (final ClassNotFoundException e) {
257             Log.e(TAG, "onResume exception: ", e);
258         }
259         if (weatherData != null) {
260             this.updateWeatherData(weatherData);
261         }
262
263
264         // 3. If language changed, try to retrieve new data for new language
265         // (new strings with the chosen language)
266         keyPreference = this.getResources().getString(
267                 R.string.weather_preferences_language_key);
268         final String languagePreferenceValue = sharedPreferences.getString(
269                 keyPreference, "");
270         if (!languagePreferenceValue.equals(this.mLanguage)) {
271             this.mLanguage = languagePreferenceValue;
272             this.getWeather();
273         }
274     }
275
276     public class WeatherTask extends AsyncTask<Object, Void, WeatherData> {
277         private static final String TAG = "WeatherTask";
278         private final WeatherHTTPClient weatherHTTPClient;
279         private final WeatherService weatherService;
280         private final DialogFragment newFragment;
281
282         public WeatherTask(final WeatherHTTPClient weatherHTTPClient,
283                 final WeatherService weatherService) {
284             this.weatherHTTPClient = weatherHTTPClient;
285             this.weatherService = weatherService;
286             this.newFragment = ProgressDialogFragment.newInstance(
287                     R.string.progress_dialog_get_remote_data,
288                     WeatherInformationOverviewFragment.this
289                     .getString(R.string.progress_dialog_generic_message));
290         }
291
292         @Override
293         protected void onPreExecute() {
294             this.newFragment.show(WeatherInformationOverviewFragment.this.getActivity()
295                     .getFragmentManager(), "progressDialog");
296         }
297
298         @Override
299         protected WeatherData doInBackground(final Object... params) {
300             WeatherData weatherData = null;
301
302             try {
303                 weatherData = this.doInBackgroundThrowable(params);
304             } catch (final ClientProtocolException e) {
305                 Log.e(TAG, "doInBackground exception: ", e);
306             } catch (final MalformedURLException e) {
307                 Log.e(TAG, "doInBackground exception: ", e);
308             } catch (final URISyntaxException e) {
309                 Log.e(TAG, "doInBackground exception: ", e);
310             } catch (final IOException e) {
311                 // logger infrastructure swallows UnknownHostException :/
312                 Log.e(TAG, "doInBackground exception: " + e.getMessage(), e);
313             } catch (final JSONException e) {
314                 Log.e(TAG, "doInBackground exception: ", e);
315             } finally {
316                 this.weatherHTTPClient.close();
317             }
318
319             return weatherData;
320         }
321
322         @Override
323         protected void onPostExecute(final WeatherData weatherData) {
324             this.weatherHTTPClient.close();
325
326             this.newFragment.dismiss();
327
328             if (weatherData != null) {
329                 try {
330                     this.onPostExecuteThrowable(weatherData);
331                 } catch (final IOException e) {
332                     Log.e(TAG, "WeatherTask onPostExecute exception: ", e);
333                     final DialogFragment newFragment = ErrorDialogFragment
334                             .newInstance(R.string.error_dialog_generic_error);
335                     newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
336                 }
337             } else {
338                 final DialogFragment newFragment = ErrorDialogFragment
339                         .newInstance(R.string.error_dialog_generic_error);
340                 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
341             }
342         }
343
344         @Override
345         protected void onCancelled(final WeatherData weatherData) {
346             this.weatherHTTPClient.close();
347
348             final DialogFragment newFragment = ErrorDialogFragment
349                     .newInstance(R.string.error_dialog_connection_tiemout);
350             newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
351         }
352
353         private WeatherData doInBackgroundThrowable(final Object... params)
354                 throws ClientProtocolException, MalformedURLException,
355                 URISyntaxException, IOException, JSONException {
356             final SharedPreferences sharedPreferences = PreferenceManager
357                     .getDefaultSharedPreferences(WeatherInformationOverviewFragment.this
358                             .getActivity());
359
360             final String keyPreference = WeatherInformationOverviewFragment.this
361                     .getActivity().getString(
362                             R.string.weather_preferences_language_key);
363             final String languagePreferenceValue = sharedPreferences.getString(keyPreference, "");
364
365             final GeocodingData geocodingData = (GeocodingData) params[0];
366             final String urlAPICoord = WeatherInformationOverviewFragment.this.getResources()
367                     .getString(R.string.uri_api_coord);
368             final String APIVersion = WeatherInformationOverviewFragment.this.getResources()
369                     .getString(R.string.api_version);
370             String url = this.weatherService.createURIAPICoord(geocodingData.getLatitude(),
371                     geocodingData.getLongitude(), urlAPICoord, APIVersion, languagePreferenceValue);
372
373
374             final String jsonData = this.weatherHTTPClient.retrieveJSONDataFromAPI(new URL(url));
375
376
377             final WeatherData weatherData = this.weatherService.retrieveDataFromJPOS(jsonData);
378
379
380             final String icon = weatherData.getWeather().getIcon();
381             final String urlAPIicon = WeatherInformationOverviewFragment.this
382                     .getResources().getString(R.string.uri_api_icon);
383             url = this.weatherService.createURIAPIicon(icon, urlAPIicon);
384             final byte[] iconData = this.weatherHTTPClient
385                     .retrieveDataFromAPI(new URL(url)).toByteArray();
386             weatherData.setIconData(iconData);
387
388
389             return weatherData;
390         }
391
392         private void onPostExecuteThrowable(final WeatherData weatherData)
393                 throws FileNotFoundException, IOException {
394             WeatherInformationOverviewFragment.this.storeWeatherDataToFile(weatherData);
395
396             WeatherInformationOverviewFragment.this.updateWeatherData(weatherData);
397         }
398     }
399
400     private List<WeatherOverviewEntry> createEmptyEntriesList() {
401         final List<WeatherOverviewEntry> entries = new ArrayList<WeatherOverviewEntry>();
402         final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MMM d", Locale.getDefault());
403
404         final Calendar now = Calendar.getInstance();
405         for (int i = 0; i<15; i++) {
406             final Date day = now.getTime();
407             entries.add(i, new WeatherOverviewEntry(dateFormat.format(day),
408                     null, null, null, null));
409             now.add(Calendar.DAY_OF_MONTH, 1);
410         }
411
412         return entries;
413     }
414
415     private void storeWeatherDataToFile(final WeatherData weatherData)
416             throws FileNotFoundException, IOException {
417         final OutputStream persistenceFile = this.getActivity().openFileOutput(
418                 WEATHER_DATA_FILE, Context.MODE_PRIVATE);
419
420         ObjectOutputStream oos = null;
421         try {
422             oos = new ObjectOutputStream(persistenceFile);
423
424             oos.writeObject(weatherData);
425         } finally {
426             if (oos != null) {
427                 oos.close();
428             }
429         }
430     }
431
432     private WeatherData restoreWeatherDataFromFile() throws StreamCorruptedException,
433     FileNotFoundException, IOException, ClassNotFoundException {
434         final InputStream persistenceFile = this.getActivity().openFileInput(
435                 WEATHER_DATA_FILE);
436
437         ObjectInputStream ois = null;
438         try {
439             ois = new ObjectInputStream(persistenceFile);
440
441             return (WeatherData) ois.readObject();
442         } finally {
443             if (ois != null) {
444                 ois.close();
445             }
446         }
447     }
448
449     private GeocodingData restoreGeocodingDataFromFile()
450             throws StreamCorruptedException, FileNotFoundException,
451             IOException, ClassNotFoundException {
452         final InputStream persistenceFile = this.getActivity()
453                 .openFileInput(WEATHER_GEOCODING_FILE);
454
455         ObjectInputStream ois = null;
456         try {
457             ois = new ObjectInputStream(persistenceFile);
458
459             return (GeocodingData) ois.readObject();
460         } finally {
461             if (ois != null) {
462                 ois.close();
463             }
464         }
465     }
466 }