1 package de.example.exampletdd.fragment.overview;
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.Collection;
14 import java.util.Date;
15 import java.util.List;
16 import java.util.Locale;
18 import org.apache.http.client.ClientProtocolException;
19 import org.json.JSONException;
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;
48 public class WeatherInformationOverviewFragment extends ListFragment implements GetWeather {
49 private boolean mIsFahrenheit;
50 private String mLanguage;
51 private WeatherServicePersistenceFile mWeatherServicePersistenceFile;
54 public void onCreate(final Bundle savedInstanceState) {
55 super.onCreate(savedInstanceState);
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(
64 this.mWeatherServicePersistenceFile = new WeatherServicePersistenceFile(
66 this.mWeatherServicePersistenceFile.removeWeatherData();
70 public void onActivityCreated(final Bundle savedInstanceState) {
71 super.onActivityCreated(savedInstanceState);
73 final ListView listWeatherView = this.getListView();
75 listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
77 if (savedInstanceState != null) {
79 final WeatherData weatherData = (WeatherData) savedInstanceState
80 .getSerializable("weatherData");
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");
91 this.setHasOptionsMenu(false);
93 final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(
94 this.getActivity(), R.layout.weather_main_entry_list);
96 final Collection<WeatherOverviewEntry> entries = this
97 .createEmptyEntriesList();
99 this.setListAdapter(null);
100 adapter.addAll(entries);
101 this.setListAdapter(adapter);
102 this.setListShown(true);
103 this.setListShownNoAnimation(true);
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) {
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);
118 fragment.getWeather();
123 public void onSaveInstanceState(final Bundle savedInstanceState) {
126 final WeatherData weatherData = this.mWeatherServicePersistenceFile.getWeatherData();
128 if (weatherData != null) {
129 savedInstanceState.putSerializable("weatherData", weatherData);
132 super.onSaveInstanceState(savedInstanceState);
136 public void getWeather() {
138 final GeocodingData geocodingData = this.mWeatherServicePersistenceFile.getGeocodingData();
140 if (geocodingData != null) {
141 final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
142 final WeatherService weatherService = new WeatherService(
144 final AndroidHttpClient httpClient = AndroidHttpClient
145 .newInstance("Android Weather Information Agent");
146 final WeatherHTTPClient HTTPweatherClient = new WeatherHTTPClient(
149 final WeatherTask weatherTask = new WeatherTask(HTTPweatherClient, weatherService);
152 weatherTask.execute(geocodingData);
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);
161 // Bitmap picture = null;
163 // if (weatherData.getWeather().getIcon() != null) {
164 // picture= BitmapFactory.decodeByteArray(
165 // weatherData.getIconData(), 0,
166 // weatherData.getIconData().length);
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;
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);
194 this.setListAdapter(null);
195 adapter.addAll(entries);
196 this.setListAdapter(adapter);
200 public void onResume() {
203 final SharedPreferences sharedPreferences = PreferenceManager
204 .getDefaultSharedPreferences(this.getActivity());
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;
215 this.mIsFahrenheit = true;
219 // 2. Update current data on display.
220 final WeatherData weatherData = this.mWeatherServicePersistenceFile.getWeatherData();
222 if (weatherData != null) {
223 this.updateWeatherData(weatherData);
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(
233 if (!languagePreferenceValue.equals(this.mLanguage)) {
234 this.mLanguage = languagePreferenceValue;
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;
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));
256 protected void onPreExecute() {
257 this.newFragment.show(WeatherInformationOverviewFragment.this.getActivity()
258 .getFragmentManager(), "progressDialog");
262 protected WeatherData doInBackground(final Object... params) {
263 WeatherData weatherData = null;
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);
279 this.weatherHTTPClient.close();
286 protected void onPostExecute(final WeatherData weatherData) {
287 this.weatherHTTPClient.close();
289 this.newFragment.dismiss();
291 if (weatherData != null) {
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");
301 final DialogFragment newFragment = ErrorDialogFragment
302 .newInstance(R.string.error_dialog_generic_error);
303 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
308 protected void onCancelled(final WeatherData weatherData) {
309 this.weatherHTTPClient.close();
311 final DialogFragment newFragment = ErrorDialogFragment
312 .newInstance(R.string.error_dialog_connection_tiemout);
313 newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
316 private WeatherData doInBackgroundThrowable(final Object... params)
317 throws ClientProtocolException, MalformedURLException,
318 URISyntaxException, IOException, JSONException {
319 final SharedPreferences sharedPreferences = PreferenceManager
320 .getDefaultSharedPreferences(WeatherInformationOverviewFragment.this
323 final String keyPreference = WeatherInformationOverviewFragment.this
324 .getActivity().getString(
325 R.string.weather_preferences_language_key);
326 final String languagePreferenceValue = sharedPreferences.getString(keyPreference, "");
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);
337 final String jsonData = this.weatherHTTPClient.retrieveJSONDataFromAPI(new URL(url));
340 final WeatherData weatherData = this.weatherService.retrieveDataFromJPOS(jsonData);
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);
355 private void onPostExecuteThrowable(final WeatherData weatherData)
356 throws FileNotFoundException, IOException {
357 WeatherInformationOverviewFragment.this.mWeatherServicePersistenceFile
358 .storeWeatherData(weatherData);
360 WeatherInformationOverviewFragment.this.updateWeatherData(weatherData);
364 private List<WeatherOverviewEntry> createEmptyEntriesList() {
365 final List<WeatherOverviewEntry> entries = new ArrayList<WeatherOverviewEntry>();
366 final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MMM d", Locale.getDefault());
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);