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);