1 package de.example.exampletdd.fragment.current;
3 import java.io.FileNotFoundException;
4 import java.io.IOException;
5 import java.net.MalformedURLException;
6 import java.net.URISyntaxException;
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;
17 import org.apache.http.client.ClientProtocolException;
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;
32 import com.fasterxml.jackson.core.JsonParseException;
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;
47 public class WeatherInformationCurrentDataFragment extends ListFragment {
48 private boolean mIsFahrenheit;
49 private WeatherServicePersistenceFile mWeatherServicePersistenceFile;
52 public void onCreate(final Bundle savedInstanceState) {
53 super.onCreate(savedInstanceState);
55 // final SharedPreferences sharedPreferences = PreferenceManager
56 // .getDefaultSharedPreferences(this.getActivity());
57 // final String keyPreference = this.getResources().getString(
58 // R.string.weather_preferences_language_key);
59 // this.mLanguage = sharedPreferences.getString(
60 // keyPreference, "");
62 this.mWeatherServicePersistenceFile = new WeatherServicePersistenceFile(this.getActivity());
63 this.mWeatherServicePersistenceFile.removeCurrentWeatherData();
67 public void onActivityCreated(final Bundle savedInstanceState) {
68 super.onActivityCreated(savedInstanceState);
70 final ListView listWeatherView = this.getListView();
71 listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
73 if (savedInstanceState != null) {
75 final CurrentWeatherData currentWeatherData = (CurrentWeatherData) savedInstanceState
76 .getSerializable("CurrentWeatherData");
78 if (currentWeatherData != null) {
80 this.mWeatherServicePersistenceFile.storeCurrentWeatherData(currentWeatherData);
81 } catch (final IOException e) {
82 final DialogFragment newFragment = ErrorDialogFragment
83 .newInstance(R.string.error_dialog_generic_error);
84 newFragment.show(this.getFragmentManager(), "errorDialog");
89 this.setHasOptionsMenu(false);
91 final WeatherSpecificDataAdapter adapter = new WeatherSpecificDataAdapter(
92 this.getActivity(), R.layout.weather_data_entry_list);
95 this.setEmptyText("No data available");
97 this.setListAdapter(adapter);
98 this.setListShown(true);
99 this.setListShownNoAnimation(true);
104 public void onResume() {
107 final SharedPreferences sharedPreferences = PreferenceManager
108 .getDefaultSharedPreferences(this.getActivity());
110 // 1. Update units of measurement.
111 final String keyPreference = this.getResources().getString(
112 R.string.weather_preferences_units_key);
113 final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
114 final String celsius = this.getResources().getString(
115 R.string.weather_preferences_units_celsius);
116 if (unitsPreferenceValue.equals(celsius)) {
117 this.mIsFahrenheit = false;
119 this.mIsFahrenheit = true;
122 // 2. Try to restore old information
123 final CurrentWeatherData currentWeatherData = this.mWeatherServicePersistenceFile
124 .getCurrentWeatherData();
125 if (currentWeatherData != null) {
126 this.updateCurrentWeatherData(currentWeatherData);
128 // 2.1 Empty list by default
129 final WeatherSpecificDataAdapter adapter = new WeatherSpecificDataAdapter(
130 this.getActivity(), R.layout.weather_data_entry_list);
131 this.setListAdapter(adapter);
133 // 2.2. Try to update weather data on display with remote
135 this.getRemoteCurrentWeatherInformation();
140 // 3. If language changed, try to retrieve new data for new language
141 // (new strings with the chosen language)
142 // keyPreference = this.getResources().getString(
143 // R.string.weather_preferences_language_key);
144 // final String languagePreferenceValue = sharedPreferences.getString(
145 // keyPreference, "");
146 // if (!languagePreferenceValue.equals(this.mLanguage)) {
147 // this.mLanguage = languagePreferenceValue;
148 // this.getWeather();
153 public void onSaveInstanceState(final Bundle savedInstanceState) {
156 final CurrentWeatherData currentWeatherData = this.mWeatherServicePersistenceFile
157 .getCurrentWeatherData();
159 if (currentWeatherData != null) {
160 savedInstanceState.putSerializable("CurrentWeatherData", currentWeatherData);
163 super.onSaveInstanceState(savedInstanceState);
167 public void updateCurrentWeatherData(final CurrentWeatherData currentWeatherData) {
168 final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale
170 tempFormatter.applyPattern("#####.#####");
171 final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss Z",
172 Locale.getDefault());
174 final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
176 final List<WeatherSpecificDataEntry> entries = this.createEmptyEntriesList();
178 final WeatherSpecificDataAdapter adapter = new WeatherSpecificDataAdapter(
179 this.getActivity(), R.layout.weather_data_entry_list);
181 if (currentWeatherData.getWeather().size() > 0) {
183 new WeatherSpecificDataEntry(this.getString(R.string.text_field_description),
184 currentWeatherData.getWeather().get(0).getDescription()));
187 if (currentWeatherData.getMain().getTemp() != null) {
188 double conversion = (Double) currentWeatherData.getMain().getTemp();
189 conversion = conversion - tempUnits;
190 entries.set(1, new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem),
191 tempFormatter.format(conversion)));
194 if (currentWeatherData.getMain().getTemp_max() != null) {
195 double conversion = (Double) currentWeatherData.getMain().getTemp_max();
196 conversion = conversion - tempUnits;
197 entries.set(2, new WeatherSpecificDataEntry(
198 this.getString(R.string.text_field_tem_max), tempFormatter.format(conversion)));
201 if (currentWeatherData.getMain().getTemp_max() != null) {
202 double conversion = (Double) currentWeatherData.getMain().getTemp_min();
203 conversion = conversion - tempUnits;
204 entries.set(3, new WeatherSpecificDataEntry(
205 this.getString(R.string.text_field_tem_min), tempFormatter.format(conversion)));
208 if (currentWeatherData.getSys().getSunrise() != null) {
209 final long unixTime = (Long) currentWeatherData.getSys().getSunrise();
210 final Date unixDate = new Date(unixTime * 1000L);
211 final String dateFormatUnix = dateFormat.format(unixDate);
213 new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_rise),
217 if (currentWeatherData.getSys().getSunset() != null) {
218 final long unixTime = (Long) currentWeatherData.getSys().getSunset();
219 final Date unixDate = new Date(unixTime * 1000L);
220 final String dateFormatUnix = dateFormat.format(unixDate);
221 entries.set(5, new WeatherSpecificDataEntry(
222 this.getString(R.string.text_field_sun_set), dateFormatUnix));
225 if (currentWeatherData.getClouds().getAll() != null) {
226 final double cloudiness = (Double) currentWeatherData.getClouds().getAll();
228 new WeatherSpecificDataEntry(this.getString(R.string.text_field_cloudiness),
229 tempFormatter.format(cloudiness)));
232 if (currentWeatherData.getIconData() != null) {
233 final Bitmap icon = BitmapFactory.decodeByteArray(currentWeatherData.getIconData(), 0,
234 currentWeatherData.getIconData().length);
235 final ImageView imageIcon = (ImageView) this.getActivity().findViewById(
236 R.id.weather_picture);
237 imageIcon.setImageBitmap(icon);
240 adapter.addAll(entries);
241 this.setListAdapter(adapter);
244 public class CurrentWeatherTask extends AsyncTask<Object, Void, CurrentWeatherData> {
245 private static final String TAG = "WeatherTask";
246 private final CustomHTTPClient weatherHTTPClient;
247 private final WeatherServiceParser weatherService;
248 private final DialogFragment newFragment;
250 public CurrentWeatherTask(final CustomHTTPClient weatherHTTPClient,
251 final WeatherServiceParser weatherService) {
252 this.weatherHTTPClient = weatherHTTPClient;
253 this.weatherService = weatherService;
254 this.newFragment = ProgressDialogFragment.newInstance(
255 R.string.progress_dialog_get_remote_data,
256 WeatherInformationCurrentDataFragment.this
257 .getString(R.string.progress_dialog_generic_message));
261 protected void onPreExecute() {
262 this.newFragment.show(WeatherInformationCurrentDataFragment.this.getActivity()
263 .getFragmentManager(), "progressDialog");
267 protected CurrentWeatherData doInBackground(final Object... params) {
268 CurrentWeatherData currentWeatherData = null;
271 currentWeatherData = this.doInBackgroundThrowable(params);
272 } catch (final ClientProtocolException e) {
273 Log.e(TAG, "doInBackground exception: ", e);
274 } catch (final MalformedURLException e) {
275 Log.e(TAG, "doInBackground exception: ", e);
276 } catch (final URISyntaxException e) {
277 Log.e(TAG, "doInBackground exception: ", e);
278 } catch (final JsonParseException e) {
279 Log.e(TAG, "doInBackground exception: ", e);
280 } catch (final IOException e) {
281 // logger infrastructure swallows UnknownHostException :/
282 Log.e(TAG, "doInBackground exception: " + e.getMessage(), e);
284 this.weatherHTTPClient.close();
287 return currentWeatherData;
291 protected void onPostExecute(final CurrentWeatherData currentWeatherData) {
292 this.weatherHTTPClient.close();
294 this.newFragment.dismiss();
296 if (currentWeatherData != null) {
298 this.onPostExecuteThrowable(currentWeatherData);
299 } catch (final IOException e) {
300 Log.e(TAG, "WeatherTask onPostExecute exception: ", e);
301 final DialogFragment newFragment = ErrorDialogFragment
302 .newInstance(R.string.error_dialog_generic_error);
304 WeatherInformationCurrentDataFragment.this.getFragmentManager(),
308 final DialogFragment newFragment = ErrorDialogFragment
309 .newInstance(R.string.error_dialog_generic_error);
310 newFragment.show(WeatherInformationCurrentDataFragment.this.getFragmentManager(),
316 protected void onCancelled(final CurrentWeatherData currentWeatherData) {
317 this.weatherHTTPClient.close();
319 final DialogFragment newFragment = ErrorDialogFragment
320 .newInstance(R.string.error_dialog_connection_tiemout);
321 newFragment.show(WeatherInformationCurrentDataFragment.this.getFragmentManager(),
325 private CurrentWeatherData doInBackgroundThrowable(final Object... params)
326 throws ClientProtocolException, MalformedURLException, URISyntaxException,
327 JsonParseException, IOException {
328 // final SharedPreferences sharedPreferences = PreferenceManager
329 // .getDefaultSharedPreferences(WeatherInformationCurrentDataFragment.this
332 // final String keyPreference =
333 // WeatherInformationCurrentDataFragment.this
334 // .getActivity().getString(
335 // R.string.weather_preferences_language_key);
336 // final String languagePreferenceValue =
337 // sharedPreferences.getString(keyPreference, "");
340 final GeocodingData geocodingData = (GeocodingData) params[0];
342 final String APIVersion = WeatherInformationCurrentDataFragment.this.getResources()
343 .getString(R.string.api_version);
346 final String urlAPI = WeatherInformationCurrentDataFragment.this.getResources()
347 .getString(R.string.uri_api_weather_today);
348 final String url = this.weatherService.createURIAPITodayWeather(urlAPI, APIVersion,
349 geocodingData.getLatitude(), geocodingData.getLongitude());
350 final String jsonData = this.weatherHTTPClient.retrieveDataAsString(new URL(url));
351 final CurrentWeatherData currentWeatherData = this.weatherService
352 .retrieveCurrentWeatherDataFromJPOS(jsonData);
353 final Calendar now = Calendar.getInstance();
354 currentWeatherData.setDate(now.getTime());
357 return currentWeatherData;
360 private void onPostExecuteThrowable(final CurrentWeatherData currentWeatherData)
361 throws FileNotFoundException, IOException {
363 WeatherInformationCurrentDataFragment.this.mWeatherServicePersistenceFile
364 .storeCurrentWeatherData(currentWeatherData);
366 WeatherInformationCurrentDataFragment.this.updateCurrentWeatherData(currentWeatherData);
370 private void getRemoteCurrentWeatherInformation() {
372 final GeocodingData geocodingData = this.mWeatherServicePersistenceFile.getGeocodingData();
374 if (geocodingData != null) {
375 final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
376 final WeatherServiceParser weatherService = new WeatherServiceParser(JPOSWeatherParser);
377 final AndroidHttpClient httpClient = AndroidHttpClient
378 .newInstance("Android Weather Information Agent");
379 final CustomHTTPClient HTTPweatherClient = new CustomHTTPClient(httpClient);
381 final CurrentWeatherTask weatherTask = new CurrentWeatherTask(HTTPweatherClient,
384 weatherTask.execute(geocodingData);
388 private List<WeatherSpecificDataEntry> createEmptyEntriesList() {
389 final List<WeatherSpecificDataEntry> entries = new ArrayList<WeatherSpecificDataEntry>();
390 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_description),
392 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem), null));
393 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem_max), null));
394 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem_min), null));
395 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_rise), null));
396 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_set), null));
397 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_cloudiness),
399 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_rain_time),
401 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_rain_amount),
403 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_wind_speed),
405 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_humidity), null));