Android app weather info. Preferences, WIP.
authorgu.martinm@gmail.com <gu.martinm@gmail.com>
Tue, 1 Apr 2014 02:41:05 +0000 (04:41 +0200)
committergu.martinm@gmail.com <gu.martinm@gmail.com>
Tue, 1 Apr 2014 02:41:05 +0000 (04:41 +0200)
12 files changed:
Android/WeatherInformation/AndroidManifest.xml
Android/WeatherInformation/res/layout/activity_main.xml
Android/WeatherInformation/res/layout/fragment_main.xml
Android/WeatherInformation/res/menu/weather_main_menu.xml
Android/WeatherInformation/res/values/arrays.xml [new file with mode: 0644]
Android/WeatherInformation/res/values/strings.xml
Android/WeatherInformation/res/xml/weather_preferences.xml [new file with mode: 0644]
Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationActivity.java
Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationPreferencesActivity.java [new file with mode: 0644]
Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherDataFragment.java [deleted file]
Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationDataFragment.java [new file with mode: 0644]
Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationPreferencesFragment.java [new file with mode: 0644]

index 2a24350..a0f5d7b 100644 (file)
@@ -19,7 +19,6 @@
         android:theme="@style/AppTheme" >
         <activity
             android:name="de.example.exampletdd.WeatherInformationActivity"
-            android:uiOptions="splitActionBarWhenNarrow"
             android:label="@string/app_name"
             android:hardwareAccelerated="false">
             <intent-filter>
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        
+        <activity
+            android:label="@string/app_name"
+            android:name=".WeatherInformationPreferencesActivity" 
+            android:theme="@android:style/Theme.Holo">
+            <intent-filter >
+                <action android:name="android.intent.action.WEATHERINFORMATIONSETTINGS" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
     </application>
 
 </manifest>
index f6e05a5..e872532 100644 (file)
@@ -10,7 +10,7 @@
         android:id="@+id/weather_data_frag"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        class="de.example.exampletdd.fragment.WeatherDataFragment"
+        class="de.example.exampletdd.fragment.WeatherInformationDataFragment"
         tools:layout="@layout/fragment_main" />
 
 </FrameLayout>
index 879d382..b110cec 100644 (file)
@@ -6,7 +6,7 @@
     android:paddingLeft="@dimen/activity_horizontal_margin"
     android:paddingRight="@dimen/activity_horizontal_margin"
     android:paddingTop="@dimen/activity_vertical_margin"
-    tools:context="de.example.exampletdd.fragment.WeatherDataFragment" >
+    tools:context="de.example.exampletdd.fragment.WeatherInformationDataFragment" >
 
     <EditText
         android:id="@+id/editTextCity"
index de8a451..72e7142 100644 (file)
@@ -9,8 +9,7 @@
         android:visible="true"
         android:checkable="false"
         android:enabled="true"
-        android:onClick="onMenuSettings"
-        android:showAsAction="ifRoom|withText">
+        android:showAsAction="collapseActionView">
     </item>
     
 
diff --git a/Android/WeatherInformation/res/values/arrays.xml b/Android/WeatherInformation/res/values/arrays.xml
new file mode 100644 (file)
index 0000000..e38881b
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string-array name="weather_preferences_units_value">
+        <item>Celsius</item>
+        <item>Fahrenheit</item>
+    </string-array>
+    <string-array name="weather_preferences_units_human_value">
+        <item>Celsius</item>
+        <item>Fahrenheit</item>
+    </string-array>
+</resources>
index 27fe592..5445332 100644 (file)
@@ -23,5 +23,9 @@
     <string name="error_dialog_generic_error">Impossible to receive weather data.</string>
     <string name="icon_weather_description">Icon weather</string>
     <string name="header_action_bar">Weather Information</string>
+    <string name="weather_preferences_units_key">weather_preferences_units</string>
+    <string name="weather_preferences_units_fahrenheit">Fahrenheit</string>
+    <string name="weather_preferences_units_celsius">Celsius</string>
+    <string name="weather_preferences_units">Units of measurement</string>
 
 </resources>
diff --git a/Android/WeatherInformation/res/xml/weather_preferences.xml b/Android/WeatherInformation/res/xml/weather_preferences.xml
new file mode 100644 (file)
index 0000000..3e2cbe0
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+    <ListPreference
+        android:key="@string/weather_preferences_units_key"
+        android:title="@string/weather_preferences_units"
+        android:summary="@string/weather_preferences_units_celsius"
+        android:entries="@array/weather_preferences_units_human_value"
+        android:entryValues="@array/weather_preferences_units_value"
+        android:selectable="true"
+        android:persistent="true"
+        android:defaultValue="Celsius" />
+
+</PreferenceScreen>
index 569c903..e3c53c4 100644 (file)
@@ -6,13 +6,14 @@ import android.app.DialogFragment;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Bundle;
+import android.preference.PreferenceManager;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import de.example.exampletdd.activityinterface.ErrorMessage;
 import de.example.exampletdd.activityinterface.OnClickButtons;
 import de.example.exampletdd.fragment.ErrorDialogFragment;
-import de.example.exampletdd.fragment.WeatherDataFragment;
+import de.example.exampletdd.fragment.WeatherInformationDataFragment;
 
 public class WeatherInformationActivity extends Activity implements ErrorMessage {
     private OnClickButtons onclickButtons;
@@ -21,32 +22,36 @@ public class WeatherInformationActivity extends Activity implements ErrorMessage
     protected void onCreate(final Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         this.setContentView(R.layout.activity_main);
-        
-        final ActionBar actionBar = getActionBar();
+
+        PreferenceManager.setDefaultValues(this, R.xml.weather_preferences,
+                false);
+
+        final ActionBar actionBar = this.getActionBar();
 
         actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
         actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE);
-        actionBar.setTitle(getResources().getString(R.string.header_action_bar));
+        actionBar.setTitle(this.getResources().getString(R.string.header_action_bar));
 
-        // Better using xml files.
+        // Better using xml files? How to deal with savedInstanceState with xml files?
         // final WeatherDataFragment weatherDataFragment = new WeatherDataFragment();
         //
         // if (savedInstanceState == null) {
         //      this.getFragmentManager().beginTransaction()
         //      .add(R.id.container, weatherDataFragment).commit();
         // }
-        final WeatherDataFragment weatherDataFragment = (WeatherDataFragment) this
+        final WeatherInformationDataFragment weatherDataFragment = (WeatherInformationDataFragment) this
                 .getFragmentManager().findFragmentById(R.id.weather_data_frag);
 
         this.onclickButtons = weatherDataFragment;
+
     }
 
     @Override
     public boolean onCreateOptionsMenu(final Menu menu) {
 
-        // Inflate the menu; this adds items to the action bar if it is present.
-        this.getMenuInflater().inflate(R.menu.main, menu);
-        return true;
+        this.getMenuInflater().inflate(R.menu.weather_main_menu, menu);
+
+        return super.onCreateOptionsMenu(menu);
     }
 
     @Override
@@ -56,14 +61,14 @@ public class WeatherInformationActivity extends Activity implements ErrorMessage
         // as you specify a parent activity in AndroidManifest.xml.
         super.onOptionsItemSelected(item);
         switch (item.getItemId()) {
-            case R.id.weather_menu_settings:
-                final Intent intent = new Intent("de.example.exampletdd.WEATHERINFO").
-                setComponent(new ComponentName("de.example.exampletdd",
-                        "de.example.exampletdd.WeatherInformationSettings"));
-                this.startActivity(intent);
-                return true;
-            default:
-                break;
+        case R.id.weather_menu_settings:
+            final Intent intent = new Intent("de.example.exampletdd.WEATHERINFO").
+            setComponent(new ComponentName("de.example.exampletdd",
+                    "de.example.exampletdd.WeatherInformationPreferencesActivity"));
+            this.startActivity(intent);
+            return true;
+        default:
+            break;
         }
 
         return super.onOptionsItemSelected(item);
@@ -79,4 +84,5 @@ public class WeatherInformationActivity extends Activity implements ErrorMessage
     public void onClickGetWeather(final View v) {
         this.onclickButtons.onClickGetWeather(v);
     }
+
 }
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationPreferencesActivity.java b/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationPreferencesActivity.java
new file mode 100644 (file)
index 0000000..3fe6e9a
--- /dev/null
@@ -0,0 +1,19 @@
+package de.example.exampletdd;
+
+import android.app.Activity;
+import android.os.Bundle;
+import de.example.exampletdd.fragment.WeatherInformationPreferencesFragment;
+
+public class WeatherInformationPreferencesActivity extends Activity {
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        this.getFragmentManager()
+        .beginTransaction()
+        .replace(android.R.id.content,
+                new WeatherInformationPreferencesFragment()).commit();
+    }
+
+}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherDataFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherDataFragment.java
deleted file mode 100644 (file)
index 1efe3fb..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-package de.example.exampletdd.fragment;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.text.DecimalFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import org.apache.http.client.ClientProtocolException;
-import org.json.JSONException;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.http.AndroidHttpClient;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.EditText;
-import android.widget.ImageView;
-import de.example.exampletdd.R;
-import de.example.exampletdd.activityinterface.ErrorMessage;
-import de.example.exampletdd.activityinterface.OnClickButtons;
-import de.example.exampletdd.httpclient.WeatherHTTPClient;
-import de.example.exampletdd.model.WeatherData;
-import de.example.exampletdd.parser.IJPOSWeatherParser;
-import de.example.exampletdd.parser.JPOSWeatherParser;
-import de.example.exampletdd.service.WeatherService;
-
-public class WeatherDataFragment extends Fragment implements OnClickButtons {
-    private Activity currentActivity;
-    EditText weatherDescription;
-    EditText temperature;
-    EditText maxTemperature;
-    EditText minTemperature;
-    EditText sunRise;
-    EditText sunSet;
-    ImageView imageIcon;
-
-
-    @Override
-    public View onCreateView(final LayoutInflater inflater,
-            final ViewGroup container, final Bundle savedInstanceState) {
-        final View rootView = inflater.inflate(R.layout.fragment_main,
-                container, false);
-
-        this.currentActivity = this.getActivity();
-
-        this.weatherDescription = (EditText) rootView.findViewById(R.id.editTextWeatherDescription);
-        this.temperature = (EditText) rootView.findViewById(R.id.editTextTemperature);
-        this.maxTemperature = (EditText) rootView.findViewById(R.id.editTextMaxTemperature);
-        this.minTemperature = (EditText) rootView.findViewById(R.id.editTextMinTemperature);
-        this.sunRise = (EditText) rootView.findViewById(R.id.editTextSunRise);
-        this.sunSet = (EditText) rootView.findViewById(R.id.editTextSunSet);
-        this.imageIcon = (ImageView) rootView.findViewById(R.id.imageIcon);
-
-        return rootView;
-    }
-
-    @Override
-    public void onClickGetWeather(final View v) {
-
-        final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
-        final WeatherService weatherService = new WeatherService(
-                JPOSWeatherParser);
-        final AndroidHttpClient httpClient = AndroidHttpClient
-                .newInstance("Android Weather Information Agent");
-        final WeatherHTTPClient HTTPweatherClient = new WeatherHTTPClient(
-                httpClient);
-
-        final WeatherTask weatherTask = new WeatherTask(HTTPweatherClient, weatherService);
-
-        final EditText cityCountry = (EditText) this.getActivity()
-                .findViewById(R.id.editTextCity);
-
-        weatherTask.execute(cityCountry.getText().toString());
-    }
-
-    public void updateWeatherData(final WeatherData weatherData) {
-        final DecimalFormat tempFormatter = new DecimalFormat("#####.#####");
-        final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss Z");
-
-        if (weatherData.getWeather() != null) {
-            this.weatherDescription.setText(weatherData.getWeather()
-                    .getDescription());
-            double conversion = weatherData.getMain().getTemp();
-            conversion = conversion - 273.15;
-            this.temperature.setText(tempFormatter.format(conversion));
-            conversion = weatherData.getMain().getMaxTemp();
-            conversion = conversion - 273.15;
-            this.maxTemperature.setText(tempFormatter.format(conversion));
-            conversion = weatherData.getMain().getMinTemp();
-            conversion = conversion - 273.15;
-            this.minTemperature.setText(tempFormatter.format(conversion));
-        }
-
-        if (weatherData.getSystem() != null) {
-            long unixTime = weatherData.getSystem().getSunRiseTime();
-            Date unixDate = new Date(unixTime * 1000L);
-            String dateFormatUnix = dateFormat.format(unixDate);
-            this.sunRise.setText(dateFormatUnix);
-
-            unixTime = weatherData.getSystem().getSunSetTime();
-            unixDate = new Date(unixTime * 1000L);
-            dateFormatUnix = dateFormat.format(unixDate);
-            this.sunSet.setText(dateFormatUnix);
-        }
-
-        if (weatherData.getIconData() != null) {
-            final Bitmap icon = BitmapFactory.decodeByteArray(
-                    weatherData.getIconData(), 0,
-                    weatherData.getIconData().length);
-            this.imageIcon.setImageBitmap(icon);
-        }
-    }
-
-    public class WeatherTask extends AsyncTask<Object, Void, WeatherData> {
-        private static final String TAG = "JSONWeatherTask";
-        private final WeatherHTTPClient weatherHTTPClient;
-        private final WeatherService weatherService;
-
-        public WeatherTask(final WeatherHTTPClient weatherHTTPClient,
-                final WeatherService weatherService) {
-            this.weatherHTTPClient = weatherHTTPClient;
-            this.weatherService = weatherService;
-        }
-
-        @Override
-        protected WeatherData doInBackground(final Object... params) {
-            WeatherData weatherData = null;
-
-            try {
-                weatherData = this.doInBackgroundThrowable(params);
-            } catch (final ClientProtocolException e) {
-                Log.e(TAG, "WeatherHTTPClient exception: ", e);
-            } catch (final MalformedURLException e) {
-                Log.e(TAG, "Syntax URL exception: ", e);
-            } catch (final URISyntaxException e) {
-                Log.e(TAG, "WeatherHTTPClient exception: ", e);
-            } catch (final IOException e) {
-                Log.e(TAG, "WeatherHTTPClient exception: ", e);
-            } catch (final JSONException e) {
-                Log.e(TAG, "WeatherService exception: ", e);
-            } finally {
-                this.weatherHTTPClient.close();
-            }
-
-            return weatherData;
-        }
-
-        @Override
-        protected void onPostExecute(final WeatherData weatherData) {
-            if (weatherData != null) {
-                WeatherDataFragment.this.updateWeatherData(weatherData);
-            } else {
-                ((ErrorMessage) WeatherDataFragment.this.currentActivity)
-                .createErrorDialog(R.string.error_dialog_generic_error);
-            }
-
-            this.weatherHTTPClient.close();
-        }
-
-        @Override
-        protected void onCancelled(final WeatherData weatherData) {
-            this.onCancelled();
-            ((ErrorMessage) WeatherDataFragment.this.currentActivity)
-            .createErrorDialog(R.string.error_dialog_connection_tiemout);
-
-            this.weatherHTTPClient.close();
-        }
-
-        private WeatherData doInBackgroundThrowable(final Object... params)
-                throws ClientProtocolException, MalformedURLException,
-                URISyntaxException, IOException, JSONException {
-            final String cityCountry = (String) params[0];
-            final String urlAPICity = WeatherDataFragment.this.getResources()
-                    .getString(R.string.uri_api_city);
-            final String APIVersion = WeatherDataFragment.this.getResources()
-                    .getString(R.string.api_version);
-            String url = this.weatherService.createURIAPICityCountry(
-                    cityCountry, urlAPICity, APIVersion);
-
-
-            final String jsonData = this.weatherHTTPClient.retrieveJSONDataFromAPI(new URL(url));
-
-
-            final WeatherData weatherData = this.weatherService.retrieveWeather(jsonData);
-
-
-            final String icon = weatherData.getWeather().getIcon();
-            final String urlAPIicon = WeatherDataFragment.this
-                    .getResources().getString(R.string.uri_api_icon);
-            url = this.weatherService.createURIAPIicon(icon, urlAPIicon);
-            final byte[] iconData = this.weatherHTTPClient
-                    .retrieveDataFromAPI(new URL(url)).toByteArray();
-            weatherData.setIconData(iconData);
-
-
-            return weatherData;
-        }
-    }
-}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationDataFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationDataFragment.java
new file mode 100644 (file)
index 0000000..9e47ce1
--- /dev/null
@@ -0,0 +1,228 @@
+package de.example.exampletdd.fragment;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.http.client.ClientProtocolException;
+import org.json.JSONException;
+
+import android.app.Fragment;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.http.AndroidHttpClient;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.ImageView;
+import de.example.exampletdd.R;
+import de.example.exampletdd.activityinterface.ErrorMessage;
+import de.example.exampletdd.activityinterface.OnClickButtons;
+import de.example.exampletdd.httpclient.WeatherHTTPClient;
+import de.example.exampletdd.model.WeatherData;
+import de.example.exampletdd.parser.IJPOSWeatherParser;
+import de.example.exampletdd.parser.JPOSWeatherParser;
+import de.example.exampletdd.service.WeatherService;
+
+public class WeatherInformationDataFragment extends Fragment implements OnClickButtons {
+    private boolean isFahrenheit;
+    private EditText weatherDescription;
+    private EditText temperature;
+    private EditText maxTemperature;
+    private EditText minTemperature;
+    private EditText sunRise;
+    private EditText sunSet;
+    private ImageView imageIcon;
+
+
+    @Override
+    public View onCreateView(final LayoutInflater inflater,
+            final ViewGroup container, final Bundle savedInstanceState) {
+        final View rootView = inflater.inflate(R.layout.fragment_main,
+                container, false);
+
+
+        this.weatherDescription = (EditText) rootView.findViewById(R.id.editTextWeatherDescription);
+        this.temperature = (EditText) rootView.findViewById(R.id.editTextTemperature);
+        this.maxTemperature = (EditText) rootView.findViewById(R.id.editTextMaxTemperature);
+        this.minTemperature = (EditText) rootView.findViewById(R.id.editTextMinTemperature);
+        this.sunRise = (EditText) rootView.findViewById(R.id.editTextSunRise);
+        this.sunSet = (EditText) rootView.findViewById(R.id.editTextSunSet);
+        this.imageIcon = (ImageView) rootView.findViewById(R.id.imageIcon);
+
+        return rootView;
+    }
+
+    @Override
+    public void onClickGetWeather(final View v) {
+
+        final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser();
+        final WeatherService weatherService = new WeatherService(
+                JPOSWeatherParser);
+        final AndroidHttpClient httpClient = AndroidHttpClient
+                .newInstance("Android Weather Information Agent");
+        final WeatherHTTPClient HTTPweatherClient = new WeatherHTTPClient(
+                httpClient);
+
+        final WeatherTask weatherTask = new WeatherTask(HTTPweatherClient, weatherService);
+
+        final EditText cityCountry = (EditText) this.getActivity()
+                .findViewById(R.id.editTextCity);
+
+        weatherTask.execute(cityCountry.getText().toString());
+    }
+
+    public void updateWeatherData(final WeatherData weatherData) {
+        final DecimalFormat tempFormatter = new DecimalFormat("#####.#####");
+        final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss Z");
+        final double tempUnits = this.isFahrenheit ? 0 : 273.15;
+
+        if (weatherData.getWeather() != null) {
+            this.weatherDescription.setText(weatherData.getWeather()
+                    .getDescription());
+            double conversion = weatherData.getMain().getTemp();
+            conversion = conversion - tempUnits;
+            this.temperature.setText(tempFormatter.format(conversion));
+            conversion = weatherData.getMain().getMaxTemp();
+            conversion = conversion - tempUnits;
+            this.maxTemperature.setText(tempFormatter.format(conversion));
+            conversion = weatherData.getMain().getMinTemp();
+            conversion = conversion - tempUnits;
+            this.minTemperature.setText(tempFormatter.format(conversion));
+        }
+
+        if (weatherData.getSystem() != null) {
+            long unixTime = weatherData.getSystem().getSunRiseTime();
+            Date unixDate = new Date(unixTime * 1000L);
+            String dateFormatUnix = dateFormat.format(unixDate);
+            this.sunRise.setText(dateFormatUnix);
+
+            unixTime = weatherData.getSystem().getSunSetTime();
+            unixDate = new Date(unixTime * 1000L);
+            dateFormatUnix = dateFormat.format(unixDate);
+            this.sunSet.setText(dateFormatUnix);
+        }
+
+        if (weatherData.getIconData() != null) {
+            final Bitmap icon = BitmapFactory.decodeByteArray(
+                    weatherData.getIconData(), 0,
+                    weatherData.getIconData().length);
+            this.imageIcon.setImageBitmap(icon);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        final SharedPreferences sharedPreferences = PreferenceManager
+                .getDefaultSharedPreferences(this.getActivity());
+
+        final String unitsKey = this.getResources().getString(
+                R.string.weather_preferences_units_key);
+        final String units = sharedPreferences.getString(unitsKey, "");
+        final String celsius = this.getResources().getString(
+                R.string.weather_preferences_units_celsius);
+        if (units.equals(celsius)) {
+            this.isFahrenheit = false;
+        } else {
+            this.isFahrenheit = true;
+        }
+    }
+
+    public class WeatherTask extends AsyncTask<Object, Void, WeatherData> {
+        private static final String TAG = "JSONWeatherTask";
+        private final WeatherHTTPClient weatherHTTPClient;
+        private final WeatherService weatherService;
+
+        public WeatherTask(final WeatherHTTPClient weatherHTTPClient,
+                final WeatherService weatherService) {
+            this.weatherHTTPClient = weatherHTTPClient;
+            this.weatherService = weatherService;
+        }
+
+        @Override
+        protected WeatherData doInBackground(final Object... params) {
+            WeatherData weatherData = null;
+
+            try {
+                weatherData = this.doInBackgroundThrowable(params);
+            } catch (final ClientProtocolException e) {
+                Log.e(TAG, "WeatherHTTPClient exception: ", e);
+            } catch (final MalformedURLException e) {
+                Log.e(TAG, "Syntax URL exception: ", e);
+            } catch (final URISyntaxException e) {
+                Log.e(TAG, "WeatherHTTPClient exception: ", e);
+            } catch (final IOException e) {
+                Log.e(TAG, "WeatherHTTPClient exception: ", e);
+            } catch (final JSONException e) {
+                Log.e(TAG, "WeatherService exception: ", e);
+            } finally {
+                this.weatherHTTPClient.close();
+            }
+
+            return weatherData;
+        }
+
+        @Override
+        protected void onPostExecute(final WeatherData weatherData) {
+            if (weatherData != null) {
+                WeatherInformationDataFragment.this.updateWeatherData(weatherData);
+            } else {
+                ((ErrorMessage) WeatherInformationDataFragment.this.getActivity())
+                .createErrorDialog(R.string.error_dialog_generic_error);
+            }
+
+            this.weatherHTTPClient.close();
+        }
+
+        @Override
+        protected void onCancelled(final WeatherData weatherData) {
+            this.onCancelled();
+            ((ErrorMessage) WeatherInformationDataFragment.this.getActivity())
+            .createErrorDialog(R.string.error_dialog_connection_tiemout);
+
+            this.weatherHTTPClient.close();
+        }
+
+        private WeatherData doInBackgroundThrowable(final Object... params)
+                throws ClientProtocolException, MalformedURLException,
+                URISyntaxException, IOException, JSONException {
+            final String cityCountry = (String) params[0];
+            final String urlAPICity = WeatherInformationDataFragment.this.getResources()
+                    .getString(R.string.uri_api_city);
+            final String APIVersion = WeatherInformationDataFragment.this.getResources()
+                    .getString(R.string.api_version);
+            String url = this.weatherService.createURIAPICityCountry(
+                    cityCountry, urlAPICity, APIVersion);
+
+
+            final String jsonData = this.weatherHTTPClient.retrieveJSONDataFromAPI(new URL(url));
+
+
+            final WeatherData weatherData = this.weatherService.retrieveWeather(jsonData);
+
+
+            final String icon = weatherData.getWeather().getIcon();
+            final String urlAPIicon = WeatherInformationDataFragment.this
+                    .getResources().getString(R.string.uri_api_icon);
+            url = this.weatherService.createURIAPIicon(icon, urlAPIicon);
+            final byte[] iconData = this.weatherHTTPClient
+                    .retrieveDataFromAPI(new URL(url)).toByteArray();
+            weatherData.setIconData(iconData);
+
+
+            return weatherData;
+        }
+    }
+}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationPreferencesFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationPreferencesFragment.java
new file mode 100644 (file)
index 0000000..d48747c
--- /dev/null
@@ -0,0 +1,57 @@
+package de.example.exampletdd.fragment;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import de.example.exampletdd.R;
+
+public class WeatherInformationPreferencesFragment extends PreferenceFragment
+implements OnSharedPreferenceChangeListener {
+
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Load the preferences from an XML resource
+        this.addPreferencesFromResource(R.xml.weather_preferences);
+
+        final String unitsKey = this.getResources().getString(
+                R.string.weather_preferences_units_key);
+        final Preference connectionPref = this.findPreference(unitsKey);
+        this.getPreferenceManager().getSharedPreferences()
+                .getString(unitsKey, "");
+        connectionPref.setSummary(this.getPreferenceManager()
+                .getSharedPreferences().getString(unitsKey, ""));
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        this.getPreferenceManager().getSharedPreferences()
+        .registerOnSharedPreferenceChangeListener(this);
+
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        this.getPreferenceManager().getSharedPreferences()
+        .unregisterOnSharedPreferenceChangeListener(this);
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(
+            final SharedPreferences sharedPreferences, final String key) {
+        final String unitsKey = this.getResources().getString(
+                R.string.weather_preferences_units_key);
+
+        if (key.equals(unitsKey)) {
+            final Preference connectionPref = this.findPreference(key);
+            connectionPref.setSummary(sharedPreferences.getString(key, ""));
+        }
+
+    }
+
+}