1 package de.example.exampletdd.fragment.overview;
3 import java.io.FileNotFoundException;
4 import java.io.IOException;
5 import java.io.StreamCorruptedException;
6 import java.net.MalformedURLException;
7 import java.net.URISyntaxException;
9 import java.text.DecimalFormat;
10 import java.text.NumberFormat;
11 import java.text.SimpleDateFormat;
12 import java.util.ArrayList;
13 import java.util.Calendar;
14 import java.util.Collection;
15 import java.util.Date;
16 import java.util.List;
17 import java.util.Locale;
19 import org.apache.http.client.ClientProtocolException;
20 import org.json.JSONException;
22 import android.app.DialogFragment;
23 import android.app.ListFragment;
24 import android.content.ComponentName;
25 import android.content.Intent;
26 import android.content.SharedPreferences;
27 import android.graphics.Bitmap;
28 import android.graphics.BitmapFactory;
29 import android.net.http.AndroidHttpClient;
30 import android.os.AsyncTask;
31 import android.os.Bundle;
32 import android.preference.PreferenceManager;
33 import android.util.Log;
34 import android.view.View;
35 import android.widget.ListView;
36 import de.example.exampletdd.R;
37 import de.example.exampletdd.activityinterface.GetWeather;
38 import de.example.exampletdd.fragment.ErrorDialogFragment;
39 import de.example.exampletdd.fragment.ProgressDialogFragment;
40 import de.example.exampletdd.fragment.specific.WeatherInformationSpecificDataFragment;
41 import de.example.exampletdd.httpclient.WeatherHTTPClient;
42 import de.example.exampletdd.model.GeocodingData;
43 import de.example.exampletdd.model.WeatherData;
44 import de.example.exampletdd.parser.IJPOSWeatherParser;
45 import de.example.exampletdd.parser.JPOSWeatherParser;
46 import de.example.exampletdd.service.WeatherService;
47 import de.example.exampletdd.service.WeatherServicePersistenceFile;
49 public class WeatherInformationOverviewFragment extends ListFragment implements GetWeather {
50 private static final String TAG = "WeatherInformationOverviewFragment";
51 private boolean mIsFahrenheit;
52 private String mLanguage;
53 private WeatherServicePersistenceFile mWeatherServicePersistenceFile;
56 public void onCreate(final Bundle savedInstanceState) {
57 super.onCreate(savedInstanceState);
59 final SharedPreferences sharedPreferences = PreferenceManager
60 .getDefaultSharedPreferences(this.getActivity());
61 final String keyPreference = this.getResources().getString(
62 R.string.weather_preferences_language_key);
63 this.mLanguage = sharedPreferences.getString(
66 this.mWeatherServicePersistenceFile = new WeatherServicePersistenceFile(
68 this.mWeatherServicePersistenceFile.removeWeatherData();
72 public void onActivityCreated(final Bundle savedInstanceState) {
73 super.onActivityCreated(savedInstanceState);
75 final ListView listWeatherView = this.getListView();
77 listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
79 if (savedInstanceState != null) {
81 final WeatherData weatherData = (WeatherData) savedInstanceState
82 .getSerializable("weatherData");
84 this.mWeatherServicePersistenceFile
85 .storeWeatherData(weatherData);
86 } catch (final IOException e) {
87 final DialogFragment newFragment = ErrorDialogFragment
88 .newInstance(R.string.error_dialog_generic_error);
89 newFragment.show(this.getFragmentManager(), "errorDialog");
93 this.setHasOptionsMenu(false);
95 final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(
96 this.getActivity(), R.layout.weather_main_entry_list);
98 final Collection<WeatherOverviewEntry> entries = this
99 .createEmptyEntriesList();
101 this.setListAdapter(null);
102 adapter.addAll(entries);
103 this.setListAdapter(adapter);
104 this.setListShown(true);
105 this.setListShownNoAnimation(true);
109 public void onListItemClick(final ListView l, final View v, final int position, final long id) {
110 final WeatherInformationSpecificDataFragment fragment = (WeatherInformationSpecificDataFragment) this.getFragmentManager()
111 .findFragmentById(R.id.weather_specific_data__fragment);
112 if (fragment == null) {
114 final Intent intent = new Intent("de.example.exampletdd.WEATHERINFO").
115 setComponent(new ComponentName("de.example.exampletdd",
116 "de.example.exampletdd.WeatherInformationSpecificDataActivity"));
117 WeatherInformationOverviewFragment.this.getActivity().startActivity(intent);
120 fragment.getWeather();
125 public void onSaveInstanceState(final Bundle savedInstanceState) {
128 WeatherData weatherData = null;
130 weatherData = this.mWeatherServicePersistenceFile.getWeatherData();
131 } catch (final StreamCorruptedException e) {
132 Log.e(TAG, "onResume exception: ", e);
133 } catch (final FileNotFoundException e) {
134 Log.e(TAG, "onResume exception: ", e);
135 } catch (final IOException e) {
136 Log.e(TAG, "onResume exception: ", e);
137 } catch (final ClassNotFoundException e) {
138 Log.e(TAG, "onResume exception: ", e);
141 if (weatherData != null) {
142 savedInstanceState.putSerializable("weatherData", weatherData);
145 super.onSaveInstanceState(savedInstanceState);
149 public void getWeather() {
151 GeocodingData geocodingData = null;
153 geocodingData = this.mWeatherServicePersistenceFile
155 } catch (final StreamCorruptedException e) {
156 Log.e(TAG, "onResume exception: ", e);
157 } catch (final FileNotFoundException e) {
158 Log.e(TAG, "onResume exception: ", e);
159 } catch (final IOException e) {
160 Log.e(TAG, "onResume exception: ", e);
161 } catch (final ClassNotFoundException e) {
162 Log.e(TAG, "onResume exception: ", e);
165 if (geocodingData != null) {
166 final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
167 final WeatherService weatherService = new WeatherService(
169 final AndroidHttpClient httpClient = AndroidHttpClient
170 .newInstance("Android Weather Information Agent");
171 final WeatherHTTPClient HTTPweatherClient = new WeatherHTTPClient(
174 final WeatherTask weatherTask = new WeatherTask(HTTPweatherClient, weatherService);
177 weatherTask.execute(geocodingData);
181 public void updateWeatherData(final WeatherData weatherData) {
182 final List<WeatherOverviewEntry> entries = this.createEmptyEntriesList();
183 final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(this.getActivity(),
184 R.layout.weather_main_entry_list);
186 // Bitmap picture = null;
188 // if (weatherData.getWeather().getIcon() != null) {
189 // picture= BitmapFactory.decodeByteArray(
190 // weatherData.getIconData(), 0,
191 // weatherData.getIconData().length);
194 final Bitmap picture = BitmapFactory.decodeResource(
195 this.getResources(), R.drawable.ic_02d);
196 final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.getDefault());
197 tempFormatter.applyPattern("#####.##");
198 final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MMM d", Locale.getDefault());
199 final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
200 double temp = weatherData.getMain().getTemp();
201 temp = temp - tempUnits;
202 double maxTemp = weatherData.getMain().getMaxTemp();
203 maxTemp = maxTemp - tempUnits;
204 double minTemp = weatherData.getMain().getMinTemp();
205 minTemp = minTemp - tempUnits;
207 final Calendar now = Calendar.getInstance();
208 if (weatherData.getWeather() != null) {
209 for (int i = 0; i<15; i++) {
210 final Date day = now.getTime();
211 entries.set(i, new WeatherOverviewEntry(dateFormat.format(day),
212 tempFormatter.format(temp), tempFormatter
213 .format(maxTemp), tempFormatter
214 .format(minTemp), picture));
215 now.add(Calendar.DAY_OF_MONTH, 1);
219 this.setListAdapter(null);
220 adapter.addAll(entries);
221 this.setListAdapter(adapter);
225 public void onResume() {
228 final SharedPreferences sharedPreferences = PreferenceManager
229 .getDefaultSharedPreferences(this.getActivity());
231 // 1. Update units of measurement.
232 String keyPreference = this.getResources().getString(
233 R.string.weather_preferences_units_key);
234 final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
235 final String celsius = this.getResources().getString(
236 R.string.weather_preferences_units_celsius);
237 if (unitsPreferenceValue.equals(celsius)) {
238 this.mIsFahrenheit = false;
240 this.mIsFahrenheit = true;
244 // 2. Update current data on display.
245 WeatherData weatherData = null;
247 weatherData = this.mWeatherServicePersistenceFile.getWeatherData();
248 } catch (final StreamCorruptedException e) {
249 Log.e(TAG, "onResume exception: ", e);
250 } catch (final FileNotFoundException e) {
251 Log.e(TAG, "onResume exception: ", e);
252 } catch (final IOException e) {
253 Log.e(TAG, "onResume exception: ", e);
254 } catch (final ClassNotFoundException e) {
255 Log.e(TAG, "onResume exception: ", e);
257 if (weatherData != null) {
258 this.updateWeatherData(weatherData);
262 // 3. If language changed, try to retrieve new data for new language
263 // (new strings with the chosen language)
264 keyPreference = this.getResources().getString(
265 R.string.weather_preferences_language_key);
266 final String languagePreferenceValue = sharedPreferences.getString(
268 if (!languagePreferenceValue.equals(this.mLanguage)) {
269 this.mLanguage = languagePreferenceValue;
274 public class WeatherTask extends AsyncTask<Object, Void, WeatherData> {
275 private static final String TAG = "WeatherTask";
276 private final WeatherHTTPClient weatherHTTPClient;
277 private final WeatherService weatherService;
278 private final DialogFragment newFragment;
280 public WeatherTask(final WeatherHTTPClient weatherHTTPClient,
281 final WeatherService weatherService) {
282 this.weatherHTTPClient = weatherHTTPClient;
283 this.weatherService = weatherService;
284 this.newFragment = ProgressDialogFragment.newInstance(
285 R.string.progress_dialog_get_remote_data,
286 WeatherInformationOverviewFragment.this
287 .getString(R.string.progress_dialog_generic_message));
291 protected void onPreExecute() {
292 this.newFragment.show(WeatherInformationOverviewFragment.this.getActivity()
293 .getFragmentManager(), "progressDialog");
297 protected WeatherData doInBackground(final Object... params) {
298 WeatherData weatherData = null;
301 weatherData = this.doInBackgroundThrowable(params);
302 } catch (final ClientProtocolException e) {
303 Log.e(TAG, "doInBackground exception: ", e);
304 } catch (final MalformedURLException e) {
305 Log.e(TAG, "doInBackground exception: ", e);
306 } catch (final URISyntaxException e) {
307 Log.e(TAG, "doInBackground exception: ", e);
308 } catch (final IOException e) {
309 // logger infrastructure swallows UnknownHostException :/
310 Log.e(TAG, "doInBackground exception: " + e.getMessage(), e);
311 } catch (final JSONException e) {
312 Log.e(TAG, "doInBackground exception: ", e);
314 this.weatherHTTPClient.close();
321 protected void onPostExecute(final WeatherData weatherData) {
322 this.weatherHTTPClient.close();
324 this.newFragment.dismiss();
326 if (weatherData != null) {
328 this.onPostExecuteThrowable(weatherData);
329 } catch (final IOException e) {
330 Log.e(TAG, "WeatherTask onPostExecute exception: ", e);
331 final DialogFragment newFragment = ErrorDialogFragment
332 .newInstance(R.string.error_dialog_generic_error);
333 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
336 final DialogFragment newFragment = ErrorDialogFragment
337 .newInstance(R.string.error_dialog_generic_error);
338 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
343 protected void onCancelled(final WeatherData weatherData) {
344 this.weatherHTTPClient.close();
346 final DialogFragment newFragment = ErrorDialogFragment
347 .newInstance(R.string.error_dialog_connection_tiemout);
348 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
351 private WeatherData doInBackgroundThrowable(final Object... params)
352 throws ClientProtocolException, MalformedURLException,
353 URISyntaxException, IOException, JSONException {
354 final SharedPreferences sharedPreferences = PreferenceManager
355 .getDefaultSharedPreferences(WeatherInformationOverviewFragment.this
358 final String keyPreference = WeatherInformationOverviewFragment.this
359 .getActivity().getString(
360 R.string.weather_preferences_language_key);
361 final String languagePreferenceValue = sharedPreferences.getString(keyPreference, "");
363 final GeocodingData geocodingData = (GeocodingData) params[0];
364 final String urlAPICoord = WeatherInformationOverviewFragment.this.getResources()
365 .getString(R.string.uri_api_coord);
366 final String APIVersion = WeatherInformationOverviewFragment.this.getResources()
367 .getString(R.string.api_version);
368 String url = this.weatherService.createURIAPICoord(geocodingData.getLatitude(),
369 geocodingData.getLongitude(), urlAPICoord, APIVersion, languagePreferenceValue);
372 final String jsonData = this.weatherHTTPClient.retrieveJSONDataFromAPI(new URL(url));
375 final WeatherData weatherData = this.weatherService.retrieveDataFromJPOS(jsonData);
378 final String icon = weatherData.getWeather().getIcon();
379 final String urlAPIicon = WeatherInformationOverviewFragment.this
380 .getResources().getString(R.string.uri_api_icon);
381 url = this.weatherService.createURIAPIicon(icon, urlAPIicon);
382 final byte[] iconData = this.weatherHTTPClient
383 .retrieveDataFromAPI(new URL(url)).toByteArray();
384 weatherData.setIconData(iconData);
390 private void onPostExecuteThrowable(final WeatherData weatherData)
391 throws FileNotFoundException, IOException {
392 WeatherInformationOverviewFragment.this.mWeatherServicePersistenceFile
393 .storeWeatherData(weatherData);
395 WeatherInformationOverviewFragment.this.updateWeatherData(weatherData);
399 private List<WeatherOverviewEntry> createEmptyEntriesList() {
400 final List<WeatherOverviewEntry> entries = new ArrayList<WeatherOverviewEntry>();
401 final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MMM d", Locale.getDefault());
403 final Calendar now = Calendar.getInstance();
404 for (int i = 0; i<15; i++) {
405 final Date day = now.getTime();
406 entries.add(i, new WeatherOverviewEntry(dateFormat.format(day),
407 null, null, null, null));
408 now.add(Calendar.DAY_OF_MONTH, 1);