No time for comments
authorgu.martinm@gmail.com <gu.martinm@gmail.com>
Thu, 10 Apr 2014 16:17:09 +0000 (18:17 +0200)
committergu.martinm@gmail.com <gu.martinm@gmail.com>
Thu, 10 Apr 2014 16:17:09 +0000 (18:17 +0200)
18 files changed:
Android/WeatherInformation/res/layout-large/weather_main.xml [new file with mode: 0644]
Android/WeatherInformation/res/layout/weather_data_list.xml
Android/WeatherInformation/res/layout/weather_specific_data.xml [new file with mode: 0644]
Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationActivity.java
Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationPreferencesActivity.java
Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationSpecificDataActivity.java [new file with mode: 0644]
Android/WeatherInformation/src/de/example/exampletdd/activityinterface/ErrorMessage.java [deleted file]
Android/WeatherInformation/src/de/example/exampletdd/activityinterface/GetWeather.java
Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherDataAdapter.java [deleted file]
Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherDataEntry.java [deleted file]
Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationDataFragment.java [deleted file]
Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationPreferencesFragment.java [deleted file]
Android/WeatherInformation/src/de/example/exampletdd/fragment/overview/WeatherInformationOverviewFragment.java
Android/WeatherInformation/src/de/example/exampletdd/fragment/preferences/WeatherInformationPreferencesFragment.java [new file with mode: 0644]
Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/WeatherInformationSpecificDataFragment.java [new file with mode: 0644]
Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/WeatherSpecificDataAdapter.java [new file with mode: 0644]
Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/WeatherSpecificDataEntry.java [new file with mode: 0644]
Android/WeatherInformation/src/de/example/exampletdd/service/WeatherServicePersistence.java [new file with mode: 0644]

diff --git a/Android/WeatherInformation/res/layout-large/weather_main.xml b/Android/WeatherInformation/res/layout-large/weather_main.xml
new file mode 100644 (file)
index 0000000..8250d57
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="de.example.exampletdd.WeatherInformationActivity"
+    tools:ignore="MergeRootFrame" >
+
+    <fragment
+        android:id="@+id/weather_overview_fragment"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        class="de.example.exampletdd.fragment.overview.WeatherInformationOverviewFragment" />
+    
+    <fragment
+        android:id="@+id/weather_specific_data__fragment"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        class="de.example.exampletdd.fragment.specific.WeatherInformationSpecificDataFragment" />
+
+</FrameLayout>
\ No newline at end of file
index e10ceb3..1abb201 100644 (file)
@@ -7,8 +7,8 @@
 
     <ImageView
         android:id="@+id/weather_picture"
-        android:layout_width="100dp"
-        android:layout_height="100dp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:contentDescription="@string/icon_weather_description"
         android:scaleType="fitCenter"
         android:src="@drawable/ic_launcher" />
diff --git a/Android/WeatherInformation/res/layout/weather_specific_data.xml b/Android/WeatherInformation/res/layout/weather_specific_data.xml
new file mode 100644 (file)
index 0000000..8c9fc01
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="de.example.exampletdd.WeatherInformationActivity"
+    tools:ignore="MergeRootFrame" >
+
+     <fragment
+        android:id="@+id/weather_specific_data_fragment"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        class="de.example.exampletdd.fragment.specific.WeatherInformationSpecificDataFragment" />
+
+</FrameLayout>
\ No newline at end of file
index 9864454..978160c 100644 (file)
@@ -8,7 +8,6 @@ import java.io.StreamCorruptedException;
 
 import android.app.ActionBar;
 import android.app.Activity;
-import android.app.DialogFragment;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Bundle;
@@ -16,13 +15,11 @@ import android.preference.PreferenceManager;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
-import de.example.exampletdd.activityinterface.ErrorMessage;
 import de.example.exampletdd.activityinterface.GetWeather;
-import de.example.exampletdd.fragment.ErrorDialogFragment;
 import de.example.exampletdd.fragment.overview.WeatherInformationOverviewFragment;
 import de.example.exampletdd.model.GeocodingData;
 
-public class WeatherInformationActivity extends Activity implements ErrorMessage {
+public class WeatherInformationActivity extends Activity {
     private static final String WEATHER_GEOCODING_FILE = "weathergeocoding.file";
     private static final String TAG = "WeatherInformationActivity";
     private GetWeather mGetWeather;
@@ -120,12 +117,6 @@ public class WeatherInformationActivity extends Activity implements ErrorMessage
 
     }
 
-    @Override
-    public void createErrorDialog(final int title) {
-        final DialogFragment newFragment = ErrorDialogFragment
-                .newInstance(title);
-        newFragment.show(this.getFragmentManager(), "errorDialog");
-    }
 
     public void getWeather() {
         this.mGetWeather.getWeather();
index 3fe6e9a..e70cfc1 100644 (file)
@@ -2,7 +2,7 @@ package de.example.exampletdd;
 
 import android.app.Activity;
 import android.os.Bundle;
-import de.example.exampletdd.fragment.WeatherInformationPreferencesFragment;
+import de.example.exampletdd.fragment.preferences.WeatherInformationPreferencesFragment;
 
 public class WeatherInformationPreferencesActivity extends Activity {
 
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationSpecificDataActivity.java b/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationSpecificDataActivity.java
new file mode 100644 (file)
index 0000000..ab7b326
--- /dev/null
@@ -0,0 +1,89 @@
+package de.example.exampletdd;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.StreamCorruptedException;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import de.example.exampletdd.fragment.specific.WeatherInformationSpecificDataFragment;
+import de.example.exampletdd.model.GeocodingData;
+
+public class WeatherInformationSpecificDataActivity extends Activity {
+    private static final String WEATHER_GEOCODING_FILE = "weathergeocoding.file";
+    private static final String TAG = "WeatherInformationSpecificDataActivity";
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        this.setContentView(R.layout.weather_specific_data);
+
+        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.setDisplayHomeAsUpEnabled(true);
+
+        final WeatherInformationSpecificDataFragment fragment =
+                new WeatherInformationSpecificDataFragment();
+
+        if (savedInstanceState == null) {
+            this.getFragmentManager().beginTransaction()
+            .add(R.id.container, fragment).commit();
+        }
+
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        final ActionBar actionBar = this.getActionBar();
+
+        GeocodingData geocodingData = null;
+        try {
+            geocodingData = this.restoreGeocodingDataFromFile();
+        } catch (final StreamCorruptedException e) {
+            Log.e(TAG, "onCreate exception: ", e);
+        } catch (final FileNotFoundException e) {
+            Log.e(TAG, "onCreate exception: ", e);
+        } catch (final IOException e) {
+            Log.e(TAG, "onCreate exception: ", e);
+        } catch (final ClassNotFoundException e) {
+            Log.e(TAG, "onCreate exception: ", e);
+        }
+        if (geocodingData != null) {
+            final String city = (geocodingData.getCity() == null) ? this.getString(R.string.city_not_found)
+                    : geocodingData.getCity();
+            final String country = (geocodingData.getCountry() == null) ? this.getString(R.string.country_not_found)
+                    : geocodingData.getCountry();
+            actionBar.setTitle(city + "," + country);
+        }
+
+    }
+
+    private GeocodingData restoreGeocodingDataFromFile()
+            throws StreamCorruptedException, FileNotFoundException,
+            IOException, ClassNotFoundException {
+        final InputStream persistenceFile = this.openFileInput(
+                WEATHER_GEOCODING_FILE);
+
+        ObjectInputStream ois = null;
+        try {
+            ois = new ObjectInputStream(persistenceFile);
+
+            return (GeocodingData) ois.readObject();
+        } finally {
+            if (ois != null) {
+                ois.close();
+            }
+        }
+    }
+}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/activityinterface/ErrorMessage.java b/Android/WeatherInformation/src/de/example/exampletdd/activityinterface/ErrorMessage.java
deleted file mode 100644 (file)
index 50907b9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-package de.example.exampletdd.activityinterface;
-
-public interface ErrorMessage {
-
-    public void createErrorDialog(final int title);
-}
index 9e8b330..98734cd 100644 (file)
@@ -1,11 +1,8 @@
 package de.example.exampletdd.activityinterface;
 
-import de.example.exampletdd.model.WeatherData;
 
 public interface GetWeather {
 
     public void getWeather();
 
-    public void updateWeatherData(final WeatherData weatherData);
-
 }
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherDataAdapter.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherDataAdapter.java
deleted file mode 100644 (file)
index 71d6cb2..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-package de.example.exampletdd.fragment;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-import de.example.exampletdd.R;
-
-public class WeatherDataAdapter extends ArrayAdapter<WeatherDataEntry> {
-    private final int resource;
-
-    public WeatherDataAdapter(final Context context, final int resource) {
-        super(context, 0);
-
-        this.resource = resource;
-    }
-
-    @Override
-    public View getView(final int position, final View convertView,
-            final ViewGroup parent) {
-
-        // We need to get the best view (re-used if possible) and then
-        // retrieve its corresponding ViewHolder, which optimizes lookup
-        // efficiency
-        final View view = this.getWorkingView(convertView);
-        final ViewHolder viewHolder = this.getViewHolder(view);
-        final WeatherDataEntry entry = this.getItem(position);
-
-
-        // Setting the text view
-        viewHolder.headerView.setText(entry.getHeader());
-        viewHolder.bodyView.setText(entry.getBody());
-
-
-        return view;
-    }
-
-    private View getWorkingView(final View convertView) {
-        // The workingView is basically just the convertView re-used if possible
-        // or inflated new if not possible
-        View workingView = null;
-
-        if(null == convertView) {
-            final Context context = this.getContext();
-            final LayoutInflater inflater = (LayoutInflater)context.getSystemService
-                    (Context.LAYOUT_INFLATER_SERVICE);
-
-            workingView = inflater.inflate(this.resource, null);
-        } else {
-            workingView = convertView;
-        }
-
-        return workingView;
-    }
-
-    private ViewHolder getViewHolder(final View workingView) {
-        // The viewHolder allows us to avoid re-looking up view references
-        // Since views are recycled, these references will never change
-        final Object tag = workingView.getTag();
-        ViewHolder viewHolder = null;
-
-
-        if((null == tag) || !(tag instanceof ViewHolder)) {
-            viewHolder = new ViewHolder();
-
-            viewHolder.headerView = (TextView) workingView
-                    .findViewById(R.id.weather_data_entry_header);
-            viewHolder.bodyView = (TextView) workingView
-                    .findViewById(R.id.weather_data_entry_body);
-
-            workingView.setTag(viewHolder);
-
-        } else {
-            viewHolder = (ViewHolder) tag;
-        }
-
-        return viewHolder;
-    }
-
-    /**
-     * ViewHolder allows us to avoid re-looking up view references
-     * Since views are recycled, these references will never change
-     */
-    private static class ViewHolder {
-        public TextView headerView;
-        public TextView bodyView;
-    }
-
-}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherDataEntry.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherDataEntry.java
deleted file mode 100644 (file)
index 45dd979..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.example.exampletdd.fragment;
-
-public class WeatherDataEntry {
-    private final String header;
-    private final String body;
-
-    public WeatherDataEntry(final String header, final String body) {
-        this.header = header;
-        this.body = body;
-    }
-
-    public String getHeader() {
-        return this.header;
-    }
-
-    public String getBody() {
-        return this.body;
-    }
-
-}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationDataFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationDataFragment.java
deleted file mode 100644 (file)
index 5d60ecf..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-package de.example.exampletdd.fragment;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.io.StreamCorruptedException;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.text.DecimalFormat;
-import java.text.NumberFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-
-import org.apache.http.client.ClientProtocolException;
-import org.json.JSONException;
-
-import android.app.DialogFragment;
-import android.app.Fragment;
-import android.content.Context;
-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.ImageView;
-import android.widget.ListView;
-import de.example.exampletdd.R;
-import de.example.exampletdd.activityinterface.ErrorMessage;
-import de.example.exampletdd.activityinterface.GetWeather;
-import de.example.exampletdd.httpclient.WeatherHTTPClient;
-import de.example.exampletdd.model.GeocodingData;
-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 GetWeather {
-    private static final String WEATHER_DATA_FILE = "weatherdata.file";
-    private static final String WEATHER_GEOCODING_FILE = "weathergeocoding.file";
-    private static final String TAG = "WeatherInformationDataFragment";
-    private boolean mIsFahrenheit;
-    private String mLanguage;
-
-    @Override
-    public void onCreate(final Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        this.getActivity().deleteFile(WEATHER_DATA_FILE);
-
-        final SharedPreferences sharedPreferences = PreferenceManager
-                .getDefaultSharedPreferences(this.getActivity());
-        final String keyPreference = this.getResources().getString(
-                R.string.weather_preferences_language_key);
-        this.mLanguage = sharedPreferences.getString(
-                keyPreference, "");
-    }
-
-    @Override
-    public View onCreateView(final LayoutInflater inflater,
-            final ViewGroup container, final Bundle savedInstanceState) {
-        final View rootView = inflater.inflate(R.layout.weather_data_list,
-                container, false);
-
-        return rootView;
-    }
-
-    @Override
-    public void onActivityCreated(final Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-
-        final ListView listWeatherView = (ListView) this.getActivity().findViewById(
-                R.id.weather_data_list_view);
-
-        final WeatherDataAdapter adapter = new WeatherDataAdapter(this.getActivity(),
-                R.layout.weather_data_entry_list);
-
-        final Collection<WeatherDataEntry> entries = this.createEmptyEntriesList();
-
-        adapter.addAll(entries);
-        listWeatherView.setAdapter(adapter);
-
-        if (savedInstanceState != null) {
-            // Restore state
-            final WeatherData weatherData = (WeatherData) savedInstanceState
-                    .getSerializable("weatherData");
-            try {
-                this.storeWeatherDataToFile(weatherData);
-            } catch (final IOException e) {
-                ((ErrorMessage) WeatherInformationDataFragment.this
-                        .getActivity())
-                        .createErrorDialog(R.string.error_dialog_generic_error);
-            }
-        }
-    }
-
-    @Override
-    public void onSaveInstanceState(final Bundle savedInstanceState) {
-
-        // Save state
-        WeatherData weatherData = null;
-        try {
-            weatherData = this.restoreWeatherDataFromFile();
-        } catch (final StreamCorruptedException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        } catch (final FileNotFoundException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        } catch (final IOException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        } catch (final ClassNotFoundException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        }
-
-        if (weatherData != null) {
-            savedInstanceState.putSerializable("weatherData", weatherData);
-        }
-
-        super.onSaveInstanceState(savedInstanceState);
-    }
-
-    @Override
-    public void getWeather() {
-
-        GeocodingData geocodingData = null;
-        try {
-            geocodingData = this.restoreGeocodingDataFromFile();
-        } catch (final StreamCorruptedException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        } catch (final FileNotFoundException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        } catch (final IOException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        } catch (final ClassNotFoundException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        }
-
-        if (geocodingData != null) {
-            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);
-
-
-            weatherTask.execute(geocodingData);
-        }
-    }
-
-    @Override
-    public void updateWeatherData(final WeatherData weatherData) {
-        final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.getDefault());
-        tempFormatter.applyPattern("#####.#####");
-        final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss Z", Locale.getDefault());
-
-        final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
-
-        final List<WeatherDataEntry> entries = this.createEmptyEntriesList();
-
-        final ListView listWeatherView = (ListView) this.getActivity().findViewById(
-                R.id.weather_data_list_view);
-
-        final WeatherDataAdapter adapter = new WeatherDataAdapter(this.getActivity(),
-                R.layout.weather_data_entry_list);
-
-        if (weatherData.getWeather() != null) {
-            entries.set(0, new WeatherDataEntry(this.getString(R.string.text_field_description), weatherData.getWeather()
-                    .getDescription()));
-            double conversion = weatherData.getMain().getTemp();
-            conversion = conversion - tempUnits;
-            entries.set(1, new WeatherDataEntry(this.getString(R.string.text_field_tem), tempFormatter.format(conversion)));
-            conversion = weatherData.getMain().getMaxTemp();
-            conversion = conversion - tempUnits;
-            entries.set(2, new WeatherDataEntry(this.getString(R.string.text_field_tem_max), tempFormatter.format(conversion)));
-            conversion = weatherData.getMain().getMinTemp();
-            conversion = conversion - tempUnits;
-            entries.set(3, new WeatherDataEntry(this.getString(R.string.text_field_tem_min), tempFormatter.format(conversion)));
-        }
-
-        if (weatherData.getSystem() != null) {
-            long unixTime = weatherData.getSystem().getSunRiseTime();
-            Date unixDate = new Date(unixTime * 1000L);
-            String dateFormatUnix = dateFormat.format(unixDate);
-            entries.set(4, new WeatherDataEntry(this.getString(R.string.text_field_sun_rise), dateFormatUnix));
-
-            unixTime = weatherData.getSystem().getSunSetTime();
-            unixDate = new Date(unixTime * 1000L);
-            dateFormatUnix = dateFormat.format(unixDate);
-            entries.set(5, new WeatherDataEntry(this.getString(R.string.text_field_sun_set), dateFormatUnix));
-        }
-
-        if (weatherData.getClouds() != null) {
-            final double cloudiness = weatherData.getClouds().getCloudiness();
-            entries.set(6, new WeatherDataEntry(this.getString(R.string.text_field_cloudiness), tempFormatter.format(cloudiness)));
-        }
-
-        if (weatherData.getWeather().getIcon() != null) {
-            final Bitmap icon = BitmapFactory.decodeByteArray(
-                    weatherData.getIconData(), 0,
-                    weatherData.getIconData().length);
-            final ImageView imageIcon = (ImageView) this.getActivity()
-                    .findViewById(R.id.weather_picture);
-            imageIcon.setImageBitmap(icon);
-        }
-
-
-
-        listWeatherView.setAdapter(null);
-        adapter.addAll(entries);
-        listWeatherView.setAdapter(adapter);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-
-        final SharedPreferences sharedPreferences = PreferenceManager
-                .getDefaultSharedPreferences(this.getActivity());
-
-        // 1. Update units of measurement.
-        String keyPreference = this.getResources().getString(
-                R.string.weather_preferences_units_key);
-        final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
-        final String celsius = this.getResources().getString(
-                R.string.weather_preferences_units_celsius);
-        if (unitsPreferenceValue.equals(celsius)) {
-            this.mIsFahrenheit = false;
-        } else {
-            this.mIsFahrenheit = true;
-        }
-
-
-        // 2. Update current data on display.
-        WeatherData weatherData = null;
-        try {
-            weatherData = this.restoreWeatherDataFromFile();
-        } catch (final StreamCorruptedException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        } catch (final FileNotFoundException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        } catch (final IOException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        } catch (final ClassNotFoundException e) {
-            Log.e(TAG, "onResume exception: ", e);
-        }
-        if (weatherData != null) {
-            this.updateWeatherData(weatherData);
-        }
-
-
-        // 3. If language changed, try to retrieve new data for new language
-        // (new strings with the chosen language)
-        keyPreference = this.getResources().getString(
-                R.string.weather_preferences_language_key);
-        final String languagePreferenceValue = sharedPreferences.getString(
-                keyPreference, "");
-        if (!languagePreferenceValue.equals(this.mLanguage)) {
-            this.mLanguage = languagePreferenceValue;
-            this.getWeather();
-        }
-    }
-
-    public class WeatherTask extends AsyncTask<Object, Void, WeatherData> {
-        private static final String TAG = "WeatherTask";
-        private final WeatherHTTPClient weatherHTTPClient;
-        private final WeatherService weatherService;
-        private final DialogFragment newFragment;
-
-        public WeatherTask(final WeatherHTTPClient weatherHTTPClient,
-                final WeatherService weatherService) {
-            this.weatherHTTPClient = weatherHTTPClient;
-            this.weatherService = weatherService;
-            this.newFragment = ProgressDialogFragment.newInstance(
-                    R.string.progress_dialog_get_remote_data,
-                    WeatherInformationDataFragment.this
-                    .getString(R.string.progress_dialog_generic_message));
-        }
-
-        @Override
-        protected void onPreExecute() {
-            this.newFragment.show(WeatherInformationDataFragment.this.getActivity()
-                    .getFragmentManager(), "progressDialog");
-        }
-
-        @Override
-        protected WeatherData doInBackground(final Object... params) {
-            WeatherData weatherData = null;
-
-            try {
-                weatherData = this.doInBackgroundThrowable(params);
-            } catch (final ClientProtocolException e) {
-                Log.e(TAG, "doInBackground exception: ", e);
-            } catch (final MalformedURLException e) {
-                Log.e(TAG, "doInBackground exception: ", e);
-            } catch (final URISyntaxException e) {
-                Log.e(TAG, "doInBackground exception: ", e);
-            } catch (final IOException e) {
-                // logger infrastructure swallows UnknownHostException :/
-                Log.e(TAG, "doInBackground exception: " + e.getMessage(), e);
-            } catch (final JSONException e) {
-                Log.e(TAG, "doInBackground exception: ", e);
-            } finally {
-                this.weatherHTTPClient.close();
-            }
-
-            return weatherData;
-        }
-
-        @Override
-        protected void onPostExecute(final WeatherData weatherData) {
-            this.weatherHTTPClient.close();
-
-            this.newFragment.dismiss();
-
-            if (weatherData != null) {
-                try {
-                    this.onPostExecuteThrowable(weatherData);
-                } catch (final IOException e) {
-                    Log.e(TAG, "WeatherTask onPostExecute exception: ", e);
-                    ((ErrorMessage) WeatherInformationDataFragment.this
-                            .getActivity())
-                            .createErrorDialog(R.string.error_dialog_generic_error);
-                }
-            } else {
-                ((ErrorMessage) WeatherInformationDataFragment.this
-                        .getActivity())
-                        .createErrorDialog(R.string.error_dialog_generic_error);
-            }
-        }
-
-        @Override
-        protected void onCancelled(final WeatherData weatherData) {
-            this.weatherHTTPClient.close();
-
-            ((ErrorMessage) WeatherInformationDataFragment.this.getActivity())
-            .createErrorDialog(R.string.error_dialog_connection_tiemout);
-        }
-
-        private WeatherData doInBackgroundThrowable(final Object... params)
-                throws ClientProtocolException, MalformedURLException,
-                URISyntaxException, IOException, JSONException {
-            final SharedPreferences sharedPreferences = PreferenceManager
-                    .getDefaultSharedPreferences(WeatherInformationDataFragment.this
-                            .getActivity());
-
-            final String keyPreference = WeatherInformationDataFragment.this
-                    .getActivity().getString(
-                            R.string.weather_preferences_language_key);
-            final String languagePreferenceValue = sharedPreferences.getString(keyPreference, "");
-
-            final GeocodingData geocodingData = (GeocodingData) params[0];
-            final String urlAPICoord = WeatherInformationDataFragment.this.getResources()
-                    .getString(R.string.uri_api_coord);
-            final String APIVersion = WeatherInformationDataFragment.this.getResources()
-                    .getString(R.string.api_version);
-            String url = this.weatherService.createURIAPICoord(geocodingData.getLatitude(),
-                    geocodingData.getLongitude(), urlAPICoord, APIVersion, languagePreferenceValue);
-
-
-            final String jsonData = this.weatherHTTPClient.retrieveJSONDataFromAPI(new URL(url));
-
-
-            final WeatherData weatherData = this.weatherService.retrieveDataFromJPOS(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;
-        }
-
-        private void onPostExecuteThrowable(final WeatherData weatherData)
-                throws FileNotFoundException, IOException {
-            WeatherInformationDataFragment.this.storeWeatherDataToFile(weatherData);
-
-            WeatherInformationDataFragment.this.updateWeatherData(weatherData);
-        }
-    }
-
-    private List<WeatherDataEntry> createEmptyEntriesList() {
-        final List<WeatherDataEntry> entries = new ArrayList<WeatherDataEntry>();
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_description), null));
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_tem), null));
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_tem_max), null));
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_tem_min), null));
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_sun_rise), null));
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_sun_set), null));
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_cloudiness), null));
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_rain_time), null));
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_rain_amount), null));
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_wind_speed), null));
-        entries.add(new WeatherDataEntry(this.getString(R.string.text_field_humidity), null));
-
-        return entries;
-    }
-
-    private void storeWeatherDataToFile(final WeatherData weatherData)
-            throws FileNotFoundException, IOException {
-        final OutputStream persistenceFile = this.getActivity().openFileOutput(
-                WEATHER_DATA_FILE, Context.MODE_PRIVATE);
-
-        ObjectOutputStream oos = null;
-        try {
-            oos = new ObjectOutputStream(persistenceFile);
-
-            oos.writeObject(weatherData);
-        } finally {
-            if (oos != null) {
-                oos.close();
-            }
-        }
-    }
-
-    private WeatherData restoreWeatherDataFromFile() throws StreamCorruptedException,
-    FileNotFoundException, IOException, ClassNotFoundException {
-        final InputStream persistenceFile = this.getActivity().openFileInput(
-                WEATHER_DATA_FILE);
-
-        ObjectInputStream ois = null;
-        try {
-            ois = new ObjectInputStream(persistenceFile);
-
-            return (WeatherData) ois.readObject();
-        } finally {
-            if (ois != null) {
-                ois.close();
-            }
-        }
-    }
-
-    private GeocodingData restoreGeocodingDataFromFile()
-            throws StreamCorruptedException, FileNotFoundException,
-            IOException, ClassNotFoundException {
-        final InputStream persistenceFile = this.getActivity()
-                .openFileInput(WEATHER_GEOCODING_FILE);
-
-        ObjectInputStream ois = null;
-        try {
-            ois = new ObjectInputStream(persistenceFile);
-
-            return (GeocodingData) ois.readObject();
-        } finally {
-            if (ois != null) {
-                ois.close();
-            }
-        }
-    }
-}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationPreferencesFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/WeatherInformationPreferencesFragment.java
deleted file mode 100644 (file)
index 5e43c0c..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-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);
-
-        String keyPreference = this.getActivity().getString(
-                R.string.weather_preferences_units_key);
-        Preference connectionPref = this.findPreference(keyPreference);
-        connectionPref.setSummary(this.getPreferenceManager()
-                .getSharedPreferences().getString(keyPreference, ""));
-
-        keyPreference = this.getActivity().getString(
-                R.string.weather_preferences_language_key);
-        connectionPref = this.findPreference(keyPreference);
-        connectionPref.setSummary(this.getPreferenceManager()
-                .getSharedPreferences().getString(keyPreference, ""));
-    }
-
-    @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) {
-        String keyValue = this.getActivity().getString(
-                R.string.weather_preferences_units_key);
-
-        if (key.equals(keyValue)) {
-            final Preference connectionPref = this.findPreference(key);
-            connectionPref.setSummary(sharedPreferences.getString(key, ""));
-        }
-
-        keyValue = this.getActivity().getString(
-                R.string.weather_preferences_language_key);
-        if (key.equals(keyValue)) {
-            final Preference connectionPref = this.findPreference(key);
-            connectionPref.setSummary(sharedPreferences.getString(key, ""));
-        }
-
-    }
-
-}
index 2c973d9..5061dd5 100644 (file)
@@ -25,7 +25,9 @@ import org.json.JSONException;
 
 import android.app.DialogFragment;
 import android.app.ListFragment;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.SharedPreferences;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -34,15 +36,13 @@ import android.os.AsyncTask;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
 import android.util.Log;
-import android.view.ActionMode;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.AbsListView.MultiChoiceModeListener;
+import android.view.View;
 import android.widget.ListView;
 import de.example.exampletdd.R;
-import de.example.exampletdd.activityinterface.ErrorMessage;
 import de.example.exampletdd.activityinterface.GetWeather;
+import de.example.exampletdd.fragment.ErrorDialogFragment;
 import de.example.exampletdd.fragment.ProgressDialogFragment;
+import de.example.exampletdd.fragment.specific.WeatherInformationSpecificDataFragment;
 import de.example.exampletdd.httpclient.WeatherHTTPClient;
 import de.example.exampletdd.model.GeocodingData;
 import de.example.exampletdd.model.WeatherData;
@@ -79,36 +79,6 @@ GetWeather {
         final ListView listWeatherView = this.getListView();
 
         listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE);
-        listWeatherView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
-
-            @Override
-            public boolean onCreateActionMode(final ActionMode mode,
-                    final Menu menu) {
-                return false;
-            }
-
-            @Override
-            public boolean onPrepareActionMode(final ActionMode mode,
-                    final Menu menu) {
-                return false;
-            }
-
-            @Override
-            public boolean onActionItemClicked(final ActionMode mode,
-                    final MenuItem item) {
-                return false;
-            }
-
-            @Override
-            public void onDestroyActionMode(final ActionMode mode) {
-            }
-
-            @Override
-            public void onItemCheckedStateChanged(
-                    final ActionMode mode, final int position,
-                    final long id, final boolean checked) {
-            }
-        });
 
         if (savedInstanceState != null) {
             // Restore state
@@ -117,9 +87,9 @@ GetWeather {
             try {
                 this.storeWeatherDataToFile(weatherData);
             } catch (final IOException e) {
-                ((ErrorMessage) WeatherInformationOverviewFragment.this
-                        .getActivity())
-                        .createErrorDialog(R.string.error_dialog_generic_error);
+                final DialogFragment newFragment = ErrorDialogFragment
+                        .newInstance(R.string.error_dialog_generic_error);
+                newFragment.show(this.getFragmentManager(), "errorDialog");
             }
         }
 
@@ -139,6 +109,22 @@ GetWeather {
     }
 
     @Override
+    public void onListItemClick(final ListView l, final View v, final int position, final long id) {
+        final WeatherInformationSpecificDataFragment fragment = (WeatherInformationSpecificDataFragment) getFragmentManager()
+                .findFragmentById(R.id.weather_specific_data__fragment);
+        if (fragment == null) {
+            // handset layout
+            final Intent intent = new Intent("de.example.exampletdd.WEATHERINFO").
+                    setComponent(new ComponentName("de.example.exampletdd",
+                            "de.example.exampletdd.specific.WeatherInformationSpecificDataActivity"));
+            WeatherInformationOverviewFragment.this.getActivity().startActivity(intent);
+        } else {
+            // tablet layout
+            fragment.getWeather();
+        }
+    }
+
+    @Override
     public void onSaveInstanceState(final Bundle savedInstanceState) {
 
         // Save state
@@ -194,7 +180,6 @@ GetWeather {
         }
     }
 
-    @Override
     public void updateWeatherData(final WeatherData weatherData) {
         final List<WeatherOverviewEntry> entries = this.createEmptyEntriesList();
         final WeatherOverviewAdapter adapter = new WeatherOverviewAdapter(this.getActivity(),
@@ -345,14 +330,14 @@ GetWeather {
                     this.onPostExecuteThrowable(weatherData);
                 } catch (final IOException e) {
                     Log.e(TAG, "WeatherTask onPostExecute exception: ", e);
-                    ((ErrorMessage) WeatherInformationOverviewFragment.this
-                            .getActivity())
-                            .createErrorDialog(R.string.error_dialog_generic_error);
+                    final DialogFragment newFragment = ErrorDialogFragment
+                            .newInstance(R.string.error_dialog_generic_error);
+                    newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
                 }
             } else {
-                ((ErrorMessage) WeatherInformationOverviewFragment.this
-                        .getActivity())
-                        .createErrorDialog(R.string.error_dialog_generic_error);
+                final DialogFragment newFragment = ErrorDialogFragment
+                        .newInstance(R.string.error_dialog_generic_error);
+                newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
             }
         }
 
@@ -360,8 +345,9 @@ GetWeather {
         protected void onCancelled(final WeatherData weatherData) {
             this.weatherHTTPClient.close();
 
-            ((ErrorMessage) WeatherInformationOverviewFragment.this.getActivity())
-            .createErrorDialog(R.string.error_dialog_connection_tiemout);
+            final DialogFragment newFragment = ErrorDialogFragment
+                    .newInstance(R.string.error_dialog_connection_tiemout);
+            newFragment.show(WeatherInformationOverviewFragment.this.getFragmentManager(), "errorDialog");
         }
 
         private WeatherData doInBackgroundThrowable(final Object... params)
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/preferences/WeatherInformationPreferencesFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/preferences/WeatherInformationPreferencesFragment.java
new file mode 100644 (file)
index 0000000..13f77db
--- /dev/null
@@ -0,0 +1,68 @@
+package de.example.exampletdd.fragment.preferences;
+
+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);
+
+        String keyPreference = this.getActivity().getString(
+                R.string.weather_preferences_units_key);
+        Preference connectionPref = this.findPreference(keyPreference);
+        connectionPref.setSummary(this.getPreferenceManager()
+                .getSharedPreferences().getString(keyPreference, ""));
+
+        keyPreference = this.getActivity().getString(
+                R.string.weather_preferences_language_key);
+        connectionPref = this.findPreference(keyPreference);
+        connectionPref.setSummary(this.getPreferenceManager()
+                .getSharedPreferences().getString(keyPreference, ""));
+    }
+
+    @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) {
+        String keyValue = this.getActivity().getString(
+                R.string.weather_preferences_units_key);
+
+        if (key.equals(keyValue)) {
+            final Preference connectionPref = this.findPreference(key);
+            connectionPref.setSummary(sharedPreferences.getString(key, ""));
+        }
+
+        keyValue = this.getActivity().getString(
+                R.string.weather_preferences_language_key);
+        if (key.equals(keyValue)) {
+            final Preference connectionPref = this.findPreference(key);
+            connectionPref.setSummary(sharedPreferences.getString(key, ""));
+        }
+
+    }
+
+}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/WeatherInformationSpecificDataFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/WeatherInformationSpecificDataFragment.java
new file mode 100644 (file)
index 0000000..b53d4a6
--- /dev/null
@@ -0,0 +1,301 @@
+package de.example.exampletdd.fragment.specific;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.StreamCorruptedException;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+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.ImageView;
+import android.widget.ListView;
+import de.example.exampletdd.R;
+import de.example.exampletdd.activityinterface.GetWeather;
+import de.example.exampletdd.fragment.ErrorDialogFragment;
+import de.example.exampletdd.model.WeatherData;
+
+public class WeatherInformationSpecificDataFragment extends Fragment implements GetWeather {
+    private static final String WEATHER_DATA_FILE = "weatherdata.file";
+    private static final String TAG = "WeatherInformationDataFragment";
+    private boolean mIsFahrenheit;
+    private String mLanguage;
+
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        this.getActivity().deleteFile(WEATHER_DATA_FILE);
+
+        final SharedPreferences sharedPreferences = PreferenceManager
+                .getDefaultSharedPreferences(this.getActivity());
+        final String keyPreference = this.getResources().getString(
+                R.string.weather_preferences_language_key);
+        this.mLanguage = sharedPreferences.getString(
+                keyPreference, "");
+    }
+
+    @Override
+    public View onCreateView(final LayoutInflater inflater,
+            final ViewGroup container, final Bundle savedInstanceState) {
+        final View rootView = inflater.inflate(R.layout.weather_data_list,
+                container, false);
+
+        return rootView;
+    }
+
+    @Override
+    public void onActivityCreated(final Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        final ListView listWeatherView = (ListView) this.getActivity().findViewById(
+                R.id.weather_data_list_view);
+
+        final WeatherSpecificDataAdapter adapter = new WeatherSpecificDataAdapter(this.getActivity(),
+                R.layout.weather_data_entry_list);
+
+        final Collection<WeatherSpecificDataEntry> entries = this.createEmptyEntriesList();
+
+        adapter.addAll(entries);
+        listWeatherView.setAdapter(adapter);
+
+        if (savedInstanceState != null) {
+            // Restore state
+            final WeatherData weatherData = (WeatherData) savedInstanceState
+                    .getSerializable("weatherData");
+            try {
+                this.storeWeatherDataToFile(weatherData);
+            } catch (final IOException e) {
+                final DialogFragment newFragment = ErrorDialogFragment
+                        .newInstance(R.string.error_dialog_generic_error);
+                newFragment.show(this.getFragmentManager(), "errorDialog");
+            }
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(final Bundle savedInstanceState) {
+
+        // Save state
+        WeatherData weatherData = null;
+        try {
+            weatherData = this.restoreWeatherDataFromFile();
+        } catch (final StreamCorruptedException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        } catch (final FileNotFoundException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        } catch (final IOException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        } catch (final ClassNotFoundException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        }
+
+        if (weatherData != null) {
+            savedInstanceState.putSerializable("weatherData", weatherData);
+        }
+
+        super.onSaveInstanceState(savedInstanceState);
+    }
+
+    @Override
+    public void getWeather() {
+        WeatherData weatherData = null;
+        try {
+            weatherData = this.restoreWeatherDataFromFile();
+        } catch (final StreamCorruptedException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        } catch (final FileNotFoundException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        } catch (final IOException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        } catch (final ClassNotFoundException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        }
+        if (weatherData != null) {
+            this.updateWeatherData(weatherData);
+        }
+    }
+
+    public void updateWeatherData(final WeatherData weatherData) {
+        final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.getDefault());
+        tempFormatter.applyPattern("#####.#####");
+        final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss Z", Locale.getDefault());
+
+        final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
+
+        final List<WeatherSpecificDataEntry> entries = this.createEmptyEntriesList();
+
+        final ListView listWeatherView = (ListView) this.getActivity().findViewById(
+                R.id.weather_data_list_view);
+
+        final WeatherSpecificDataAdapter adapter = new WeatherSpecificDataAdapter(this.getActivity(),
+                R.layout.weather_data_entry_list);
+
+        if (weatherData.getWeather() != null) {
+            entries.set(0, new WeatherSpecificDataEntry(this.getString(R.string.text_field_description), weatherData.getWeather()
+                    .getDescription()));
+            double conversion = weatherData.getMain().getTemp();
+            conversion = conversion - tempUnits;
+            entries.set(1, new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem), tempFormatter.format(conversion)));
+            conversion = weatherData.getMain().getMaxTemp();
+            conversion = conversion - tempUnits;
+            entries.set(2, new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem_max), tempFormatter.format(conversion)));
+            conversion = weatherData.getMain().getMinTemp();
+            conversion = conversion - tempUnits;
+            entries.set(3, new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem_min), tempFormatter.format(conversion)));
+        }
+
+        if (weatherData.getSystem() != null) {
+            long unixTime = weatherData.getSystem().getSunRiseTime();
+            Date unixDate = new Date(unixTime * 1000L);
+            String dateFormatUnix = dateFormat.format(unixDate);
+            entries.set(4, new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_rise), dateFormatUnix));
+
+            unixTime = weatherData.getSystem().getSunSetTime();
+            unixDate = new Date(unixTime * 1000L);
+            dateFormatUnix = dateFormat.format(unixDate);
+            entries.set(5, new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_set), dateFormatUnix));
+        }
+
+        if (weatherData.getClouds() != null) {
+            final double cloudiness = weatherData.getClouds().getCloudiness();
+            entries.set(6, new WeatherSpecificDataEntry(this.getString(R.string.text_field_cloudiness), tempFormatter.format(cloudiness)));
+        }
+
+        if (weatherData.getWeather().getIcon() != null) {
+            final Bitmap icon = BitmapFactory.decodeByteArray(
+                    weatherData.getIconData(), 0,
+                    weatherData.getIconData().length);
+            final ImageView imageIcon = (ImageView) this.getActivity()
+                    .findViewById(R.id.weather_picture);
+            imageIcon.setImageBitmap(icon);
+        }
+
+
+
+        listWeatherView.setAdapter(null);
+        adapter.addAll(entries);
+        listWeatherView.setAdapter(adapter);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        final SharedPreferences sharedPreferences = PreferenceManager
+                .getDefaultSharedPreferences(this.getActivity());
+
+        // 1. Update units of measurement.
+        String keyPreference = this.getResources().getString(
+                R.string.weather_preferences_units_key);
+        final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
+        final String celsius = this.getResources().getString(
+                R.string.weather_preferences_units_celsius);
+        if (unitsPreferenceValue.equals(celsius)) {
+            this.mIsFahrenheit = false;
+        } else {
+            this.mIsFahrenheit = true;
+        }
+
+
+        // 2. Update current data on display.
+        WeatherData weatherData = null;
+        try {
+            weatherData = this.restoreWeatherDataFromFile();
+        } catch (final StreamCorruptedException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        } catch (final FileNotFoundException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        } catch (final IOException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        } catch (final ClassNotFoundException e) {
+            Log.e(TAG, "onResume exception: ", e);
+        }
+        if (weatherData != null) {
+            this.updateWeatherData(weatherData);
+        }
+
+
+        // 3. If language changed, try to retrieve new data for new language
+        // (new strings with the chosen language)
+        keyPreference = this.getResources().getString(
+                R.string.weather_preferences_language_key);
+        final String languagePreferenceValue = sharedPreferences.getString(
+                keyPreference, "");
+        if (!languagePreferenceValue.equals(this.mLanguage)) {
+            this.mLanguage = languagePreferenceValue;
+            this.getWeather();
+        }
+    }
+
+    private List<WeatherSpecificDataEntry> createEmptyEntriesList() {
+        final List<WeatherSpecificDataEntry> entries = new ArrayList<WeatherSpecificDataEntry>();
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_description), null));
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem), null));
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem_max), null));
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_tem_min), null));
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_rise), null));
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_sun_set), null));
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_cloudiness), null));
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_rain_time), null));
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_rain_amount), null));
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_wind_speed), null));
+        entries.add(new WeatherSpecificDataEntry(this.getString(R.string.text_field_humidity), null));
+
+        return entries;
+    }
+
+    private void storeWeatherDataToFile(final WeatherData weatherData)
+            throws FileNotFoundException, IOException {
+        final OutputStream persistenceFile = this.getActivity().openFileOutput(
+                WEATHER_DATA_FILE, Context.MODE_PRIVATE);
+
+        ObjectOutputStream oos = null;
+        try {
+            oos = new ObjectOutputStream(persistenceFile);
+
+            oos.writeObject(weatherData);
+        } finally {
+            if (oos != null) {
+                oos.close();
+            }
+        }
+    }
+
+    private WeatherData restoreWeatherDataFromFile() throws StreamCorruptedException,
+    FileNotFoundException, IOException, ClassNotFoundException {
+        final InputStream persistenceFile = this.getActivity().openFileInput(
+                WEATHER_DATA_FILE);
+
+        ObjectInputStream ois = null;
+        try {
+            ois = new ObjectInputStream(persistenceFile);
+
+            return (WeatherData) ois.readObject();
+        } finally {
+            if (ois != null) {
+                ois.close();
+            }
+        }
+    }
+}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/WeatherSpecificDataAdapter.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/WeatherSpecificDataAdapter.java
new file mode 100644 (file)
index 0000000..0b9491d
--- /dev/null
@@ -0,0 +1,92 @@
+package de.example.exampletdd.fragment.specific;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+import de.example.exampletdd.R;
+import de.example.exampletdd.fragment.specific.WeatherSpecificDataEntry;
+
+public class WeatherSpecificDataAdapter extends ArrayAdapter<WeatherSpecificDataEntry> {
+    private final int resource;
+
+    public WeatherSpecificDataAdapter(final Context context, final int resource) {
+        super(context, 0);
+
+        this.resource = resource;
+    }
+
+    @Override
+    public View getView(final int position, final View convertView,
+            final ViewGroup parent) {
+
+        // We need to get the best view (re-used if possible) and then
+        // retrieve its corresponding ViewHolder, which optimizes lookup
+        // efficiency
+        final View view = this.getWorkingView(convertView);
+        final ViewHolder viewHolder = this.getViewHolder(view);
+        final WeatherSpecificDataEntry entry = this.getItem(position);
+
+
+        // Setting the text view
+        viewHolder.headerView.setText(entry.getHeader());
+        viewHolder.bodyView.setText(entry.getBody());
+
+
+        return view;
+    }
+
+    private View getWorkingView(final View convertView) {
+        // The workingView is basically just the convertView re-used if possible
+        // or inflated new if not possible
+        View workingView = null;
+
+        if(null == convertView) {
+            final Context context = this.getContext();
+            final LayoutInflater inflater = (LayoutInflater)context.getSystemService
+                    (Context.LAYOUT_INFLATER_SERVICE);
+
+            workingView = inflater.inflate(this.resource, null);
+        } else {
+            workingView = convertView;
+        }
+
+        return workingView;
+    }
+
+    private ViewHolder getViewHolder(final View workingView) {
+        // The viewHolder allows us to avoid re-looking up view references
+        // Since views are recycled, these references will never change
+        final Object tag = workingView.getTag();
+        ViewHolder viewHolder = null;
+
+
+        if((null == tag) || !(tag instanceof ViewHolder)) {
+            viewHolder = new ViewHolder();
+
+            viewHolder.headerView = (TextView) workingView
+                    .findViewById(R.id.weather_data_entry_header);
+            viewHolder.bodyView = (TextView) workingView
+                    .findViewById(R.id.weather_data_entry_body);
+
+            workingView.setTag(viewHolder);
+
+        } else {
+            viewHolder = (ViewHolder) tag;
+        }
+
+        return viewHolder;
+    }
+
+    /**
+     * ViewHolder allows us to avoid re-looking up view references
+     * Since views are recycled, these references will never change
+     */
+    private static class ViewHolder {
+        public TextView headerView;
+        public TextView bodyView;
+    }
+
+}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/WeatherSpecificDataEntry.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/WeatherSpecificDataEntry.java
new file mode 100644 (file)
index 0000000..2d5f492
--- /dev/null
@@ -0,0 +1,20 @@
+package de.example.exampletdd.fragment.specific;
+
+public class WeatherSpecificDataEntry {
+    private final String header;
+    private final String body;
+
+    public WeatherSpecificDataEntry(final String header, final String body) {
+        this.header = header;
+        this.body = body;
+    }
+
+    public String getHeader() {
+        return this.header;
+    }
+
+    public String getBody() {
+        return this.body;
+    }
+
+}
diff --git a/Android/WeatherInformation/src/de/example/exampletdd/service/WeatherServicePersistence.java b/Android/WeatherInformation/src/de/example/exampletdd/service/WeatherServicePersistence.java
new file mode 100644 (file)
index 0000000..e76e625
--- /dev/null
@@ -0,0 +1,93 @@
+package de.example.exampletdd.service;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.StreamCorruptedException;
+
+import android.content.Context;
+import de.example.exampletdd.model.GeocodingData;
+import de.example.exampletdd.model.WeatherData;
+
+public class WeatherServicePersistence {
+    private static final String WEATHER_DATA_FILE = "weatherdata.file";
+    private static final String WEATHER_GEOCODING_FILE = "weathergeocoding.file";
+    private final Context context;
+
+    public WeatherServicePersistence(final Context context) {
+        this.context = context;
+    }
+
+    public void storeGeocodingDataToFile(final GeocodingData geocodingData)
+            throws FileNotFoundException, IOException {
+        final OutputStream persistenceFile = context.openFileOutput(
+                WEATHER_GEOCODING_FILE, Context.MODE_PRIVATE);
+
+        ObjectOutputStream oos = null;
+        try {
+            oos = new ObjectOutputStream(persistenceFile);
+
+            oos.writeObject(geocodingData);
+        } finally {
+            if (oos != null) {
+                oos.close();
+            }
+        }
+    }
+
+    public GeocodingData restoreGeocodingDataFromFile()
+            throws StreamCorruptedException, FileNotFoundException,
+            IOException, ClassNotFoundException {
+        final InputStream persistenceFile = context.openFileInput(
+                WEATHER_GEOCODING_FILE);
+
+        ObjectInputStream ois = null;
+        try {
+            ois = new ObjectInputStream(persistenceFile);
+
+            return (GeocodingData) ois.readObject();
+        } finally {
+            if (ois != null) {
+                ois.close();
+            }
+        }
+    }
+
+    public void storeWeatherDataToFile(final WeatherData weatherData)
+            throws FileNotFoundException, IOException {
+        final OutputStream persistenceFile = context.openFileOutput(
+                WEATHER_DATA_FILE, Context.MODE_PRIVATE);
+
+        ObjectOutputStream oos = null;
+        try {
+            oos = new ObjectOutputStream(persistenceFile);
+
+            oos.writeObject(weatherData);
+        } finally {
+            if (oos != null) {
+                oos.close();
+            }
+        }
+    }
+
+    public WeatherData restoreWeatherDataFromFile()
+            throws StreamCorruptedException,
+            FileNotFoundException, IOException, ClassNotFoundException {
+        final InputStream persistenceFile = context.openFileInput(
+                WEATHER_DATA_FILE);
+
+        ObjectInputStream ois = null;
+        try {
+            ois = new ObjectInputStream(persistenceFile);
+
+            return (WeatherData) ois.readObject();
+        } finally {
+            if (ois != null) {
+                ois.close();
+            }
+        }
+    }
+}