05a10a9b89dd1355f15141fac2bc9777e6fb094d
[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.Collection;
14 import java.util.Date;
15 import java.util.List;
16 import java.util.Locale;
17
18 import org.apache.http.client.ClientProtocolException;
19 import org.json.JSONException;
20
21 import android.app.DialogFragment;
22 import android.app.ListFragment;
23 import android.content.ComponentName;
24 import android.content.Intent;
25 import android.content.SharedPreferences;
26 import android.graphics.Bitmap;
27 import android.graphics.BitmapFactory;
28 import android.net.http.AndroidHttpClient;
29 import android.os.AsyncTask;
30 import android.os.Bundle;
31 import android.preference.PreferenceManager;
32 import android.util.Log;
33 import android.view.View;
34 import android.widget.ListView;
35 import de.example.exampletdd.R;
36 import de.example.exampletdd.activityinterface.GetWeather;
37 import de.example.exampletdd.fragment.ErrorDialogFragment;
38 import de.example.exampletdd.fragment.ProgressDialogFragment;
39 import de.example.exampletdd.fragment.specific.WeatherInformationSpecificDataFragment;
40 import de.example.exampletdd.httpclient.WeatherHTTPClient;
41 import de.example.exampletdd.model.GeocodingData;
42 import de.example.exampletdd.model.WeatherData;
43 import de.example.exampletdd.parser.IJPOSWeatherParser;
44 import de.example.exampletdd.parser.JPOSWeatherParser;
45 import de.example.exampletdd.service.WeatherService;
46 import de.example.exampletdd.service.WeatherServicePersistenceFile;
47
48 public class WeatherInformationOverviewFragment extends ListFragment implements GetWeather {
49     private boolean mIsFahrenheit;
50     private String mLanguage;
51     private WeatherServicePersistenceFile mWeatherServicePersistenceFile;
52
53     @Override
54     public void onCreate(final Bundle savedInstanceState) {
55         super.onCreate(savedInstanceState);
56
57         final SharedPreferences sharedPreferences = PreferenceManager
58                 .getDefaultSharedPreferences(this.getActivity());
59         final String keyPreference = this.getResources().getString(
60                 R.string.weather_preferences_language_key);
61         this.mLanguage = sharedPreferences.getString(
62                 keyPreference, "");
63
64         this.mWeatherServicePersistenceFile = new WeatherServicePersistenceFile(
65                 this.getActivity());
66         this.mWeatherServicePersistenceFile.removeWeatherData();
67     }
68
69     @Override
70     public void onActivityCreated(final Bundle savedInstanceState) {
71         super.onActivityCreated(savedInstanceState);
72
73         final ListView listWeatherView = this.getListView();
74
75         listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
76
77         if (savedInstanceState != null) {
78             // Restore state
79             final WeatherData weatherData = (WeatherData) savedInstanceState
80                     .getSerializable("weatherData");
81             try {
82                 this.mWeatherServicePersistenceFile
83                 .storeWeatherData(weatherData);
84             } catch (final IOException e) {
85                 final DialogFragment newFragment = ErrorDialogFragment
86                         .newInstance(R.string.error_dialog_generic_error);
87                 newFragment.show(this.getFragmentManager(), "errorDialog");
88             }
89         }
90
91         this.setHasOptionsMenu(false);
92
93         final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(
94                 this.getActivity(), R.layout.weather_main_entry_list);
95
96         final Collection<WeatherOverviewEntry> entries = this
97                 .createEmptyEntriesList();
98
99         this.setListAdapter(null);
100         adapter.addAll(entries);
101         this.setListAdapter(adapter);
102         this.setListShown(true);
103         this.setListShownNoAnimation(true);
104     }
105
106     @Override
107     public void onListItemClick(final ListView l, final View v, final int position, final long id) {
108         final WeatherInformationSpecificDataFragment fragment = (WeatherInformationSpecificDataFragment) this.getFragmentManager()
109                 .findFragmentById(R.id.weather_specific_data__fragment);
110         if (fragment == null) {
111             // handset layout
112             final Intent intent = new Intent("de.example.exampletdd.WEATHERINFO").
113                     setComponent(new ComponentName("de.example.exampletdd",
114                             "de.example.exampletdd.WeatherInformationSpecificDataActivity"));
115             WeatherInformationOverviewFragment.this.getActivity().startActivity(intent);
116         } else {
117             // tablet layout
118             fragment.getWeather();
119         }
120     }
121
122     @Override
123     public void onSaveInstanceState(final Bundle savedInstanceState) {
124
125         // Save state
126         final WeatherData weatherData = this.mWeatherServicePersistenceFile.getWeatherData();
127
128         if (weatherData != null) {
129             savedInstanceState.putSerializable("weatherData", weatherData);
130         }
131
132         super.onSaveInstanceState(savedInstanceState);
133     }
134
135     @Override
136     public void getWeather() {
137
138         final GeocodingData geocodingData = this.mWeatherServicePersistenceFile.getGeocodingData();
139
140         if (geocodingData != null) {
141             final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
142             final WeatherService weatherService = new WeatherService(
143                     JPOSWeatherParser);
144             final AndroidHttpClient httpClient = AndroidHttpClient
145                     .newInstance("Android Weather Information Agent");
146             final WeatherHTTPClient HTTPweatherClient = new WeatherHTTPClient(
147                     httpClient);
148
149             final WeatherTask weatherTask = new WeatherTask(HTTPweatherClient, weatherService);
150
151
152             weatherTask.execute(geocodingData);
153         }
154     }
155
156     public void updateWeatherData(final WeatherData weatherData) {
157         final List<WeatherOverviewEntry> entries = this.createEmptyEntriesList();
158         final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(this.getActivity(),
159                 R.layout.weather_main_entry_list);
160
161         // Bitmap picture = null;
162         //
163         // if (weatherData.getWeather().getIcon() != null) {
164         // picture= BitmapFactory.decodeByteArray(
165         // weatherData.getIconData(), 0,
166         // weatherData.getIconData().length);
167         // }
168
169         final Bitmap picture = BitmapFactory.decodeResource(
170                 this.getResources(), R.drawable.ic_02d);
171         final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.getDefault());
172         tempFormatter.applyPattern("#####.##");
173         final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MMM d", Locale.getDefault());
174         final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
175         double temp = weatherData.getMain().getTemp();
176         temp = temp - tempUnits;
177         double maxTemp = weatherData.getMain().getMaxTemp();
178         maxTemp = maxTemp - tempUnits;
179         double minTemp = weatherData.getMain().getMinTemp();
180         minTemp = minTemp - tempUnits;
181
182         final Calendar now = Calendar.getInstance();
183         if (weatherData.getWeather() != null) {
184             for (int i = 0; i<15; i++) {
185                 final Date day = now.getTime();
186                 entries.set(i, new WeatherOverviewEntry(dateFormat.format(day),
187                         tempFormatter.format(temp), tempFormatter
188                         .format(maxTemp), tempFormatter
189                         .format(minTemp), picture));
190                 now.add(Calendar.DAY_OF_MONTH, 1);
191             }
192         }
193
194         this.setListAdapter(null);
195         adapter.addAll(entries);
196         this.setListAdapter(adapter);
197     }
198
199     @Override
200     public void onResume() {
201         super.onResume();
202
203         final SharedPreferences sharedPreferences = PreferenceManager
204                 .getDefaultSharedPreferences(this.getActivity());
205
206         // 1. Update units of measurement.
207         String keyPreference = this.getResources().getString(
208                 R.string.weather_preferences_units_key);
209         final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
210         final String celsius = this.getResources().getString(
211                 R.string.weather_preferences_units_celsius);
212         if (unitsPreferenceValue.equals(celsius)) {
213             this.mIsFahrenheit = false;
214         } else {
215             this.mIsFahrenheit = true;
216         }
217
218
219         // 2. Update current data on display.
220         final WeatherData weatherData = this.mWeatherServicePersistenceFile.getWeatherData();
221
222         if (weatherData != null) {
223             this.updateWeatherData(weatherData);
224         }
225
226
227         // 3. If language changed, try to retrieve new data for new language
228         // (new strings with the chosen language)
229         keyPreference = this.getResources().getString(
230                 R.string.weather_preferences_language_key);
231         final String languagePreferenceValue = sharedPreferences.getString(
232                 keyPreference, "");
233         if (!languagePreferenceValue.equals(this.mLanguage)) {
234             this.mLanguage = languagePreferenceValue;
235             this.getWeather();
236         }
237     }
238
239     public class WeatherTask extends AsyncTask<Object, Void, WeatherData> {
240         private static final String TAG = "WeatherTask";
241         private final WeatherHTTPClient weatherHTTPClient;
242         private final WeatherService weatherService;
243         private final DialogFragment newFragment;
244
245         public WeatherTask(final WeatherHTTPClient weatherHTTPClient,
246                 final WeatherService weatherService) {
247             this.weatherHTTPClient = weatherHTTPClient;
248             this.weatherService = weatherService;
249             this.newFragment = ProgressDialogFragment.newInstance(
250                     R.string.progress_dialog_get_remote_data,
251                     WeatherInformationOverviewFragment.this
252                     .getString(R.string.progress_dialog_generic_message));
253         }
254
255         @Override
256         protected void onPreExecute() {
257             this.newFragment.show(WeatherInformationOverviewFragment.this.getActivity()
258                     .getFragmentManager(), "progressDialog");
259         }
260
261         @Override
262         protected WeatherData doInBackground(final Object... params) {
263             WeatherData weatherData = null;
264
265             try {
266                 weatherData = this.doInBackgroundThrowable(params);
267             } catch (final ClientProtocolException e) {
268                 Log.e(TAG, "doInBackground exception: ", e);
269             } catch (final MalformedURLException e) {
270                 Log.e(TAG, "doInBackground exception: ", e);
271             } catch (final URISyntaxException e) {
272                 Log.e(TAG, "doInBackground exception: ", e);
273             } catch (final IOException e) {
274                 // logger infrastructure swallows UnknownHostException :/
275                 Log.e(TAG, "doInBackground exception: " + e.getMessage(), e);
276             } catch (final JSONException e) {
277                 Log.e(TAG, "doInBackground exception: ", e);
278             } finally {
279                 this.weatherHTTPClient.close();
280             }
281
282             return weatherData;
283         }
284
285         @Override
286         protected void onPostExecute(final WeatherData weatherData) {
287             this.weatherHTTPClient.close();
288
289             this.newFragment.dismiss();
290
291             if (weatherData != null) {
292                 try {
293                     this.onPostExecuteThrowable(weatherData);
294                 } catch (final IOException e) {
295                     Log.e(TAG, "WeatherTask onPostExecute exception: ", e);
296                     final DialogFragment newFragment = ErrorDialogFragment
297                             .newInstance(R.string.error_dialog_generic_error);
298                     newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
299                 }
300             } else {
301                 final DialogFragment newFragment = ErrorDialogFragment
302                         .newInstance(R.string.error_dialog_generic_error);
303                 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
304             }
305         }
306
307         @Override
308         protected void onCancelled(final WeatherData weatherData) {
309             this.weatherHTTPClient.close();
310
311             final DialogFragment newFragment = ErrorDialogFragment
312                     .newInstance(R.string.error_dialog_connection_tiemout);
313             newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
314         }
315
316         private WeatherData doInBackgroundThrowable(final Object... params)
317                 throws ClientProtocolException, MalformedURLException,
318                 URISyntaxException, IOException, JSONException {
319             final SharedPreferences sharedPreferences = PreferenceManager
320                     .getDefaultSharedPreferences(WeatherInformationOverviewFragment.this
321                             .getActivity());
322
323             final String keyPreference = WeatherInformationOverviewFragment.this
324                     .getActivity().getString(
325                             R.string.weather_preferences_language_key);
326             final String languagePreferenceValue = sharedPreferences.getString(keyPreference, "");
327
328             final GeocodingData geocodingData = (GeocodingData) params[0];
329             final String urlAPICoord = WeatherInformationOverviewFragment.this.getResources()
330                     .getString(R.string.uri_api_coord);
331             final String APIVersion = WeatherInformationOverviewFragment.this.getResources()
332                     .getString(R.string.api_version);
333             String url = this.weatherService.createURIAPICoord(geocodingData.getLatitude(),
334                     geocodingData.getLongitude(), urlAPICoord, APIVersion, languagePreferenceValue);
335
336
337             final String jsonData = this.weatherHTTPClient.retrieveJSONDataFromAPI(new URL(url));
338
339
340             final WeatherData weatherData = this.weatherService.retrieveDataFromJPOS(jsonData);
341
342
343             final String icon = weatherData.getWeather().getIcon();
344             final String urlAPIicon = WeatherInformationOverviewFragment.this
345                     .getResources().getString(R.string.uri_api_icon);
346             url = this.weatherService.createURIAPIicon(icon, urlAPIicon);
347             final byte[] iconData = this.weatherHTTPClient
348                     .retrieveDataFromAPI(new URL(url)).toByteArray();
349             weatherData.setIconData(iconData);
350
351
352             return weatherData;
353         }
354
355         private void onPostExecuteThrowable(final WeatherData weatherData)
356                 throws FileNotFoundException, IOException {
357             WeatherInformationOverviewFragment.this.mWeatherServicePersistenceFile
358             .storeWeatherData(weatherData);
359
360             WeatherInformationOverviewFragment.this.updateWeatherData(weatherData);
361         }
362     }
363
364     private List<WeatherOverviewEntry> createEmptyEntriesList() {
365         final List<WeatherOverviewEntry> entries = new ArrayList<WeatherOverviewEntry>();
366         final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MMM d", Locale.getDefault());
367
368         final Calendar now = Calendar.getInstance();
369         for (int i = 0; i<15; i++) {
370             final Date day = now.getTime();
371             entries.add(i, new WeatherOverviewEntry(dateFormat.format(day),
372                     null, null, null, null));
373             now.add(Calendar.DAY_OF_MONTH, 1);
374         }
375
376         return entries;
377     }
378 }