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 this.mWeatherServicePersistenceFile = new WeatherServicePersistenceFile(this.getActivity());
56 this.mWeatherServicePersistenceFile.removeCurrentWeatherData();
60 public void onActivityCreated(final Bundle savedInstanceState) {
61 super.onActivityCreated(savedInstanceState);
63 final ListView listWeatherView = this.getListView();
64 listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
66 if (savedInstanceState != null) {
68 final CurrentWeatherData currentWeatherData = (CurrentWeatherData) savedInstanceState
69 .getSerializable("CurrentWeatherData");
71 if (currentWeatherData != null) {
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");
82 this.setHasOptionsMenu(false);
84 this.setEmptyText("No data available");
86 this.setListShownNoAnimation(false);
90 public void onResume() {
93 final SharedPreferences sharedPreferences = PreferenceManager
94 .getDefaultSharedPreferences(this.getActivity());
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;
105 this.mIsFahrenheit = true;
108 // 2. Try to restore old information
109 final CurrentWeatherData currentWeatherData = this.mWeatherServicePersistenceFile
110 .getCurrentWeatherData();
111 if (currentWeatherData != null) {
112 this.updateCurrentWeatherData(currentWeatherData);
114 // 3. Try to update weather data on display with remote
115 this.getRemoteCurrentWeatherInformation();
120 public void onSaveInstanceState(final Bundle savedInstanceState) {
123 final CurrentWeatherData currentWeatherData = this.mWeatherServicePersistenceFile
124 .getCurrentWeatherData();
126 if (currentWeatherData != null) {
127 savedInstanceState.putSerializable("CurrentWeatherData", currentWeatherData);
130 super.onSaveInstanceState(savedInstanceState);
134 public void updateCurrentWeatherData(final CurrentWeatherData currentWeatherData) {
135 final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale
137 tempFormatter.applyPattern("#####.#####");
138 final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss Z",
139 Locale.getDefault());
141 final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
143 final List<WeatherSpecificDataEntry> entries = this.createEmptyEntriesList();
145 final WeatherSpecificDataAdapter adapter = new WeatherSpecificDataAdapter(
146 this.getActivity(), R.layout.weather_data_entry_list);
148 if (currentWeatherData.getWeather().size() > 0) {
150 new WeatherSpecificDataEntry(this.getString(R.string.text_field_description),
151 currentWeatherData.getWeather().get(0).getDescription()));
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)));
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)));
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)));
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);
180 new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_rise),
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));
192 if (currentWeatherData.getClouds().getAll() != null) {
193 final double cloudiness = (Double) currentWeatherData.getClouds().getAll();
195 new WeatherSpecificDataEntry(this.getString(R.string.text_field_cloudiness),
196 tempFormatter.format(cloudiness)));
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);
207 adapter.addAll(entries);
208 this.setListAdapter(adapter);
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;
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));
228 protected void onPreExecute() {
229 this.newFragment.show(WeatherInformationCurrentDataFragment.this.getActivity()
230 .getFragmentManager(), "progressDialog");
234 protected CurrentWeatherData doInBackground(final Object... params) {
235 CurrentWeatherData currentWeatherData = null;
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);
251 this.weatherHTTPClient.close();
254 return currentWeatherData;
258 protected void onPostExecute(final CurrentWeatherData currentWeatherData) {
259 this.weatherHTTPClient.close();
261 this.newFragment.dismiss();
263 if (currentWeatherData != null) {
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);
272 WeatherInformationCurrentDataFragment.this.getFragmentManager(),
276 WeatherInformationCurrentDataFragment.this.setListShown(true);
277 final DialogFragment newFragment = ErrorDialogFragment
278 .newInstance(R.string.error_dialog_generic_error);
279 newFragment.show(WeatherInformationCurrentDataFragment.this.getFragmentManager(),
285 protected void onCancelled(final CurrentWeatherData currentWeatherData) {
286 this.weatherHTTPClient.close();
288 final DialogFragment newFragment = ErrorDialogFragment
289 .newInstance(R.string.error_dialog_connection_tiemout);
290 newFragment.show(WeatherInformationCurrentDataFragment.this.getFragmentManager(),
294 private CurrentWeatherData doInBackgroundThrowable(final Object... params)
295 throws ClientProtocolException, MalformedURLException, URISyntaxException,
296 JsonParseException, IOException {
299 final GeocodingData geocodingData = (GeocodingData) params[0];
301 final String APIVersion = WeatherInformationCurrentDataFragment.this.getResources()
302 .getString(R.string.api_version);
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());
316 return currentWeatherData;
319 private void onPostExecuteThrowable(final CurrentWeatherData currentWeatherData)
320 throws FileNotFoundException, IOException {
322 WeatherInformationCurrentDataFragment.this.mWeatherServicePersistenceFile
323 .storeCurrentWeatherData(currentWeatherData);
325 WeatherInformationCurrentDataFragment.this.updateCurrentWeatherData(currentWeatherData);
329 private void getRemoteCurrentWeatherInformation() {
331 final GeocodingData geocodingData = this.mWeatherServicePersistenceFile.getGeocodingData();
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);
340 final CurrentWeatherTask weatherTask = new CurrentWeatherTask(HTTPweatherClient,
343 weatherTask.execute(geocodingData);
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),
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),
358 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_rain_time),
360 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_rain_amount),
362 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_wind_speed),
364 entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_humidity), null));