a9c2e7725e65f20e43e3fa0c6e2f2a40c8e30a74
[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.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.ComponentName;
22 import android.content.Intent;
23 import android.content.SharedPreferences;
24 import android.graphics.Bitmap;
25 import android.graphics.BitmapFactory;
26 import android.net.http.AndroidHttpClient;
27 import android.os.AsyncTask;
28 import android.os.Bundle;
29 import android.os.Parcelable;
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.forecastweather.ForecastWeatherData;
45 import de.example.exampletdd.parser.IJPOSWeatherParser;
46 import de.example.exampletdd.parser.JPOSWeatherParser;
47 import de.example.exampletdd.service.WeatherServiceParser;
48 import de.example.exampletdd.service.WeatherServicePersistenceFile;
49
50 public class WeatherInformationOverviewFragment extends ListFragment implements GetWeather {
51     private boolean mIsFahrenheit;
52     private String mDayForecast;
53     private WeatherServicePersistenceFile mWeatherServicePersistenceFile;
54     private Parcelable mListState;
55
56     @Override
57     public void onCreate(final Bundle savedInstanceState) {
58         super.onCreate(savedInstanceState);
59
60         final SharedPreferences sharedPreferences = PreferenceManager
61                 .getDefaultSharedPreferences(this.getActivity());
62         final String keyPreference = this.getResources().getString(
63                 R.string.weather_preferences_day_forecast_key);
64         this.mDayForecast = sharedPreferences.getString(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         listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
76
77         if (savedInstanceState != null) {
78             // Restore state
79             final ForecastWeatherData forecastWeatherData = (ForecastWeatherData) savedInstanceState
80                     .getSerializable("ForecastWeatherData");
81
82             if (forecastWeatherData != null) {
83                 try {
84                     this.mWeatherServicePersistenceFile
85                     .storeForecastWeatherData(forecastWeatherData);
86                 } catch (final IOException e) {
87                     final DialogFragment newFragment = ErrorDialogFragment
88                             .newInstance(R.string.error_dialog_generic_error);
89                     newFragment.show(this.getFragmentManager(), "errorDialog");
90                 }
91             }
92
93             this.mListState = savedInstanceState.getParcelable("ListState");
94         }
95
96         this.setHasOptionsMenu(false);
97
98         final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(
99                 this.getActivity(), R.layout.weather_main_entry_list);
100
101
102         this.setEmptyText("Press download to receive weather information");
103
104         this.setListAdapter(adapter);
105         this.setListShown(true);
106         this.setListShownNoAnimation(true);
107     }
108
109     @Override
110     public void onListItemClick(final ListView l, final View v, final int position, final long id) {
111         final WeatherInformationSpecificDataFragment fragment = (WeatherInformationSpecificDataFragment) this.getFragmentManager()
112                 .findFragmentById(R.id.weather_specific_data__fragment);
113         if (fragment == null) {
114             // handset layout
115             final Intent intent = new Intent("de.example.exampletdd.WEATHERINFO").
116                     setComponent(new ComponentName("de.example.exampletdd",
117                             "de.example.exampletdd.WeatherInformationSpecificDataActivity"));
118             intent.putExtra("CHOSEN_DAY", (int) id);
119             WeatherInformationOverviewFragment.this.getActivity().startActivity(intent);
120         } else {
121             // tablet layout
122             fragment.getWeatherByDay((int) id);
123         }
124     }
125
126     @Override
127     public void onSaveInstanceState(final Bundle savedInstanceState) {
128
129         // Save state
130         final ForecastWeatherData forecastWeatherData = this.mWeatherServicePersistenceFile
131                 .getForecastWeatherData();
132
133         if (forecastWeatherData != null) {
134             savedInstanceState.putSerializable("ForecastWeatherData", forecastWeatherData);
135         }
136
137         this.mListState = this.getListView().onSaveInstanceState();
138         savedInstanceState.putParcelable("ListState", this.mListState);
139
140         super.onSaveInstanceState(savedInstanceState);
141     }
142
143     @Override
144     public void getRemoteWeatherInformation() {
145
146         final GeocodingData geocodingData = this.mWeatherServicePersistenceFile.getGeocodingData();
147
148         if (geocodingData != null) {
149             final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
150             final WeatherServiceParser weatherService = new WeatherServiceParser(
151                     JPOSWeatherParser);
152             final AndroidHttpClient httpClient = AndroidHttpClient
153                     .newInstance("Android Weather Information Agent");
154             final CustomHTTPClient HTTPweatherClient = new CustomHTTPClient(
155                     httpClient);
156
157             final ForecastWeatherTask weatherTask = new ForecastWeatherTask(HTTPweatherClient,
158                     weatherService);
159
160
161             weatherTask.execute(geocodingData);
162         }
163     }
164
165     @Override
166     public void getWeatherByDay(final int chosenDay) {
167         // Nothing to do.
168     }
169
170     public void updateForecastWeatherData(final ForecastWeatherData forecastWeatherData) {
171         final List<WeatherOverviewEntry> entries = new ArrayList<WeatherOverviewEntry>();
172         final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(this.getActivity(),
173                 R.layout.weather_main_entry_list);
174
175
176         final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.getDefault());
177         tempFormatter.applyPattern("#####.##");
178         final SimpleDateFormat dayNameFormatter = new SimpleDateFormat("EEE", Locale.getDefault());
179         final SimpleDateFormat monthAndDayNumberormatter = new SimpleDateFormat("MMM d",
180                 Locale.getDefault());
181         final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
182         final String symbol = this.mIsFahrenheit ? "ºF" : "ºC";
183
184
185         final Calendar calendar = Calendar.getInstance();
186         for (final de.example.exampletdd.model.forecastweather.List forecast : forecastWeatherData
187                 .getList()) {
188
189             Bitmap picture;
190
191             if ((forecast.getWeather().size() > 0) &&
192                     (forecast.getWeather().get(0).getIcon() != null) &&
193                     (IconsList.getIcon(forecast.getWeather().get(0).getIcon()) != null)) {
194                 final String icon = forecast.getWeather().get(0).getIcon();
195                 picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon)
196                         .getResourceDrawable());
197             } else {
198                 picture = BitmapFactory.decodeResource(this.getResources(),
199                         R.drawable.weather_severe_alert);
200             }
201
202             final Long forecastUNIXDate = (Long) forecast.getDt();
203             calendar.setTimeInMillis(forecastUNIXDate * 1000L);
204             final Date dayTime = calendar.getTime();
205             final String dayTextName = dayNameFormatter.format(dayTime);
206             final String monthAndDayNumberText = monthAndDayNumberormatter.format(dayTime);
207
208             Double maxTemp = null;
209             if (forecast.getTemp().getMax() != null) {
210                 maxTemp = (Double) forecast.getTemp().getMax();
211                 maxTemp = maxTemp - tempUnits;
212             }
213
214             Double minTemp = null;
215             if (forecast.getTemp().getMin() != null) {
216                 minTemp = (Double) forecast.getTemp().getMin();
217                 minTemp = minTemp - tempUnits;
218             }
219
220             if ((maxTemp != null) && (minTemp != null)) {
221                 entries.add(new WeatherOverviewEntry(dayTextName, monthAndDayNumberText,
222                         tempFormatter.format(maxTemp) + symbol, tempFormatter.format(minTemp) + symbol,
223                         picture));
224             }
225         }
226
227         this.setListAdapter(null);
228         adapter.addAll(entries);
229         this.setListAdapter(adapter);
230     }
231
232     @Override
233     public void onResume() {
234         super.onResume();
235
236         final SharedPreferences sharedPreferences = PreferenceManager
237                 .getDefaultSharedPreferences(this.getActivity());
238
239         // 1. Update units of measurement.
240         String keyPreference = this.getResources().getString(
241                 R.string.weather_preferences_units_key);
242         final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
243         final String celsius = this.getResources().getString(
244                 R.string.weather_preferences_units_celsius);
245         if (unitsPreferenceValue.equals(celsius)) {
246             this.mIsFahrenheit = false;
247         } else {
248             this.mIsFahrenheit = true;
249         }
250
251         // 2. Update number day forecast.
252         keyPreference = this.getResources().getString(
253                 R.string.weather_preferences_day_forecast_key);
254         this.mDayForecast = sharedPreferences.getString(keyPreference, "");
255
256
257         // 3. Update forecast weather data on display.
258         final ForecastWeatherData forecastWeatherData = this.mWeatherServicePersistenceFile
259                 .getForecastWeatherData();
260         if ((this.mListState != null) && (forecastWeatherData != null)) {
261             this.updateForecastWeatherData(forecastWeatherData);
262             this.getListView().onRestoreInstanceState(this.mListState);
263         } else if (forecastWeatherData != null) {
264             this.updateForecastWeatherData(forecastWeatherData);
265         }
266
267     }
268
269     public class ForecastWeatherTask extends AsyncTask<Object, Void, ForecastWeatherData> {
270         private static final String TAG = "ForecastWeatherTask";
271         private final CustomHTTPClient weatherHTTPClient;
272         private final WeatherServiceParser weatherService;
273         private final DialogFragment newFragment;
274
275         public ForecastWeatherTask(final CustomHTTPClient weatherHTTPClient,
276                 final WeatherServiceParser weatherService) {
277             this.weatherHTTPClient = weatherHTTPClient;
278             this.weatherService = weatherService;
279             this.newFragment = ProgressDialogFragment.newInstance(
280                     R.string.progress_dialog_get_remote_data,
281                     WeatherInformationOverviewFragment.this
282                     .getString(R.string.progress_dialog_generic_message));
283         }
284
285         @Override
286         protected void onPreExecute() {
287             this.newFragment.show(WeatherInformationOverviewFragment.this.getActivity()
288                     .getFragmentManager(), "progressDialog");
289         }
290
291         @Override
292         protected ForecastWeatherData doInBackground(final Object... params) {
293             ForecastWeatherData forecastWeatherData = null;
294
295             try {
296                 forecastWeatherData = this.doInBackgroundThrowable(params);
297             } catch (final ClientProtocolException e) {
298                 Log.e(TAG, "doInBackground exception: ", e);
299             } catch (final MalformedURLException e) {
300                 Log.e(TAG, "doInBackground exception: ", e);
301             } catch (final URISyntaxException e) {
302                 Log.e(TAG, "doInBackground exception: ", e);
303             } catch (final JsonParseException e) {
304                 Log.e(TAG, "doInBackground exception: ", e);
305             } catch (final IOException e) {
306                 // logger infrastructure swallows UnknownHostException :/
307                 Log.e(TAG, "doInBackground exception: " + e.getMessage(), e);
308             } finally {
309                 this.weatherHTTPClient.close();
310             }
311
312             return forecastWeatherData;
313         }
314
315         @Override
316         protected void onPostExecute(final ForecastWeatherData weatherData) {
317             this.weatherHTTPClient.close();
318
319             this.newFragment.dismiss();
320
321             if (weatherData != null) {
322                 try {
323                     this.onPostExecuteThrowable(weatherData);
324                 } catch (final IOException e) {
325                     Log.e(TAG, "WeatherTask onPostExecute exception: ", e);
326                     final DialogFragment newFragment = ErrorDialogFragment
327                             .newInstance(R.string.error_dialog_generic_error);
328                     newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
329                 }
330             } else {
331                 final DialogFragment newFragment = ErrorDialogFragment
332                         .newInstance(R.string.error_dialog_generic_error);
333                 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
334             }
335         }
336
337         @Override
338         protected void onCancelled(final ForecastWeatherData weatherData) {
339             this.weatherHTTPClient.close();
340
341             final DialogFragment newFragment = ErrorDialogFragment
342                     .newInstance(R.string.error_dialog_connection_tiemout);
343             newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
344         }
345
346         private ForecastWeatherData doInBackgroundThrowable(final Object... params)
347                 throws ClientProtocolException, MalformedURLException,
348                 URISyntaxException, JsonParseException, IOException {
349
350             // 1. Coordinates
351             final GeocodingData geocodingData = (GeocodingData) params[0];
352
353
354             final String APIVersion = WeatherInformationOverviewFragment.this.getResources()
355                     .getString(R.string.api_version);
356             // 2. Forecast
357             final String urlAPI = WeatherInformationOverviewFragment.this.getResources()
358                     .getString(R.string.uri_api_weather_forecast);
359             final String url = this.weatherService.createURIAPIForecastWeather(urlAPI, APIVersion,
360                     geocodingData.getLatitude(), geocodingData.getLongitude(), WeatherInformationOverviewFragment.this.mDayForecast);
361             final String jsonData = this.weatherHTTPClient.retrieveDataAsString(new URL(url));
362             final ForecastWeatherData forecastWeatherData = this.weatherService
363                     .retrieveForecastWeatherDataFromJPOS(jsonData);
364
365             return forecastWeatherData;
366         }
367
368         private void onPostExecuteThrowable(final ForecastWeatherData forecastWeatherData)
369                 throws FileNotFoundException, IOException {
370             WeatherInformationOverviewFragment.this.mWeatherServicePersistenceFile
371             .storeForecastWeatherData(forecastWeatherData);
372
373             WeatherInformationOverviewFragment.this.updateForecastWeatherData(forecastWeatherData);
374         }
375     }
376 }