From ea0d90c61a1795315c97bbfa2abe0fcb50f76292 Mon Sep 17 00:00:00 2001 From: "gu.martinm@gmail.com" Date: Sat, 6 Sep 2014 22:52:12 +0200 Subject: [PATCH] WeatherInformation Android Removing GeocodingData object MapActivity is done Read/Insert/Update database done No tested code. --- .../src/de/example/exampletdd/MapActivity.java | 71 ++++--- .../de/example/exampletdd/SpecificActivity.java | 17 +- .../exampletdd/WeatherInformationApplication.java | 29 ++- .../exampletdd/WeatherInformationBatch.java | 60 +++--- .../de/example/exampletdd/WeatherTabsActivity.java | 19 +- .../fragment/current/CurrentFragment.java | 56 ++++-- .../fragment/overview/OverviewFragment.java | 53 +++-- .../fragment/specific/SpecificFragment.java | 32 ++- .../example/exampletdd/model/DatabaseQueries.java | 44 +++++ .../de/example/exampletdd/model/GeocodingData.java | 106 ---------- .../example/exampletdd/model/WeatherLocation.java | 106 +++++----- .../exampletdd/model/WeatherLocationDbQueries.java | 111 +++++++++-- .../service/ServicePersistenceStorage.java | 217 --------------------- 13 files changed, 382 insertions(+), 539 deletions(-) create mode 100644 Android/WeatherInformation/src/de/example/exampletdd/model/DatabaseQueries.java delete mode 100644 Android/WeatherInformation/src/de/example/exampletdd/model/GeocodingData.java delete mode 100644 Android/WeatherInformation/src/de/example/exampletdd/service/ServicePersistenceStorage.java diff --git a/Android/WeatherInformation/src/de/example/exampletdd/MapActivity.java b/Android/WeatherInformation/src/de/example/exampletdd/MapActivity.java index 0f871e2..c489ebd 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/MapActivity.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/MapActivity.java @@ -42,9 +42,8 @@ import com.google.android.gms.maps.model.MarkerOptions; import de.example.exampletdd.fragment.ErrorDialogFragment; import de.example.exampletdd.fragment.ProgressDialogFragment; import de.example.exampletdd.gms.GPlayServicesErrorDialogFragment; +import de.example.exampletdd.model.DatabaseQueries; import de.example.exampletdd.model.WeatherLocation; -import de.example.exampletdd.model.WeatherLocationDbHelper; -import de.example.exampletdd.model.WeatherLocationDbQueries; public class MapActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks, @@ -123,7 +122,8 @@ public class MapActivity extends FragmentActivity implements // just once this.mRestoreUI = null; } else { - weatherLocation = queryDataBase(); + final DatabaseQueries query = new DatabaseQueries(this); + weatherLocation = query.queryDataBase(); } if (weatherLocation != null) { @@ -144,10 +144,11 @@ public class MapActivity extends FragmentActivity implements double latitude = point.latitude; double longitude = point.longitude; - final WeatherLocation location = new WeatherLocation.Builder(). - setCity(cityString).setCountry(countryString). - setLatitude(latitude).setLongitude(longitude). - build(); + final WeatherLocation location = new WeatherLocation() + .setCity(cityString) + .setCountry(countryString) + .setLatitude(latitude) + .setLongitude(longitude); savedInstanceState.putSerializable("WeatherLocation", location); } @@ -161,7 +162,28 @@ public class MapActivity extends FragmentActivity implements } public void onClickSaveLocation(final View v) { - + if (this.mMarker == null) { + final LatLng position = this.mMarker.getPosition(); + + final DatabaseQueries query = new DatabaseQueries(this); + final WeatherLocation weatherLocation = query.queryDataBase(); + if (weatherLocation != null) { + query.updateDataBase(weatherLocation); + } else { + final TextView city = (TextView) this.findViewById(R.id.weather_map_city); + final TextView country = (TextView) this.findViewById(R.id.weather_map_country); + final String cityString = city.getText().toString(); + final String countryString = country.getText().toString(); + + final WeatherLocation location = new WeatherLocation() + .setCity(cityString) + .setCountry(countryString) + .setIsSelected(true) + .setLatitude(position.latitude) + .setLongitude(position.longitude); + query.insertIntoDataBase(location); + } + } } public void onClickGetLocation(final View v) { @@ -174,6 +196,7 @@ public class MapActivity extends FragmentActivity implements locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); locationRequest.setInterval(1000); final FusedLocationProviderApi fusedLocationApi = LocationServices.FusedLocationApi; + // TODO: What if between mGoogleApiClient.isConnected() and this point mGoogleApiClient is disconnected? Android sucks? fusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this); } else { // TODO: string resource @@ -181,17 +204,6 @@ public class MapActivity extends FragmentActivity implements } } } - - private WeatherLocation queryDataBase() { - - final WeatherLocationDbHelper dbHelper = new WeatherLocationDbHelper(this); - try { - final WeatherLocationDbQueries queryDb = new WeatherLocationDbQueries(dbHelper); - return queryDb.queryDataBase(this); - } finally { - dbHelper.close(); - } - } private void updateUI(final WeatherLocation weatherLocation) { @@ -217,6 +229,7 @@ public class MapActivity extends FragmentActivity implements private static final String TAG = "GetAddressTask"; // Store the context passed to the AsyncTask when the system instantiates it. private final Context localContext; + // TODO: siempre tuve problemas usando fragmentos y recreando activities (rotar, volver a activity, etc, etc) private final DialogFragment newFragment; private GetAddressTask(final Context context) { @@ -283,10 +296,11 @@ public class MapActivity extends FragmentActivity implements } } - return new WeatherLocation.Builder() - .setLatitude(latitude).setLongitude(longitude) - .setCity(city).setCountry(country) - .build(); + return new WeatherLocation() + .setLatitude(latitude) + .setLongitude(longitude) + .setCity(city) + .setCountry(country); } } @@ -333,10 +347,11 @@ public class MapActivity extends FragmentActivity implements // Default values final String city = this.getString(R.string.city_not_found); final String country = this.getString(R.string.country_not_found); - final WeatherLocation weatherLocation = new WeatherLocation.Builder(). - setLatitude(latitude).setLongitude(longitude). - setCity(city).setCountry(country). - build(); + final WeatherLocation weatherLocation = new WeatherLocation() + .setLatitude(latitude) + .setLongitude(longitude) + .setCity(city) + .setCountry(country); updateUI(weatherLocation); } @@ -512,6 +527,7 @@ public class MapActivity extends FragmentActivity implements // Make sure the app is not already connected or attempting to connect if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) { + // TODO: What if between mGoogleApiClient.isConnected() and this point mGoogleApiClient is disconnected? Android sucks? mGoogleApiClient.connect(); } @@ -577,6 +593,7 @@ public class MapActivity extends FragmentActivity implements final FusedLocationProviderApi fusedLocationApi = LocationServices.FusedLocationApi; // TODO: if user clicks many times onClickGetLocation I may not assure how many times // onLocationChanged will be called. Is it a problem? AFAIK it isn't. + // TODO: What if between mGoogleApiClient.isConnected() and this point mGoogleApiClient is disconnected? Android sucks? fusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); } diff --git a/Android/WeatherInformation/src/de/example/exampletdd/SpecificActivity.java b/Android/WeatherInformation/src/de/example/exampletdd/SpecificActivity.java index 9465571..3cb5da4 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/SpecificActivity.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/SpecificActivity.java @@ -3,7 +3,8 @@ package de.example.exampletdd; import android.app.ActionBar; import android.os.Bundle; import android.support.v4.app.FragmentActivity; -import de.example.exampletdd.model.GeocodingData; +import de.example.exampletdd.model.DatabaseQueries; +import de.example.exampletdd.model.WeatherLocation; public class SpecificActivity extends FragmentActivity { @@ -24,17 +25,13 @@ public class SpecificActivity extends FragmentActivity { public void onResume() { super.onResume(); - // TODO: retrive data from data base (like I do on WindowsPhone 8) // 1. Update title. - final GeocodingData geocodingData = new GeocodingData.Builder().build(); - 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(); - final ActionBar actionBar = this.getActionBar(); + final DatabaseQueries query = new DatabaseQueries(this); + final WeatherLocation weatherLocation = query.queryDataBase(); + if (weatherLocation != null) { + final ActionBar actionBar = this.getActionBar(); // TODO: I18N and comma :/ - actionBar.setTitle(city + "," + country); + actionBar.setTitle(weatherLocation.getCity() + "," + weatherLocation.getCountry()); } } } diff --git a/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationApplication.java b/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationApplication.java index 7067c3b..679a2ca 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationApplication.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationApplication.java @@ -1,22 +1,15 @@ package de.example.exampletdd; import android.app.Application; -import de.example.exampletdd.model.GeocodingData; import de.example.exampletdd.model.currentweather.Current; import de.example.exampletdd.model.forecastweather.Forecast; public class WeatherInformationApplication extends Application { private Forecast mForecast; private Current mCurrent; - private GeocodingData mGeocodingData; + private String mCity; + private String mCountry; - protected void setGeocodingData(final GeocodingData geocodingData) { - this.mGeocodingData = geocodingData; - } - - protected GeocodingData getGeocodingData() { - return this.mGeocodingData; - } public void setForecast(final Forecast forecast) { this.mForecast = forecast; @@ -33,4 +26,20 @@ public class WeatherInformationApplication extends Application { public Current getCurrent() { return this.mCurrent; } -} + + public void setCity(final String city) { + this.mCity = city; + } + + public String getCity() { + return this.mCity; + } + + public void setCountry(final String country) { + this.mCountry = country; + } + + public String getCountry() { + return this.mCountry; + } +} diff --git a/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationBatch.java b/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationBatch.java index 22591d4..3a0e678 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationBatch.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/WeatherInformationBatch.java @@ -18,17 +18,17 @@ import android.util.Log; import com.fasterxml.jackson.core.JsonParseException; import de.example.exampletdd.httpclient.CustomHTTPClient; -import de.example.exampletdd.model.GeocodingData; +import de.example.exampletdd.model.WeatherLocation; +import de.example.exampletdd.model.WeatherLocationDbHelper; +import de.example.exampletdd.model.WeatherLocationDbQueries; import de.example.exampletdd.model.currentweather.Current; import de.example.exampletdd.model.forecastweather.Forecast; import de.example.exampletdd.parser.JPOSWeatherParser; import de.example.exampletdd.service.ServiceParser; -import de.example.exampletdd.service.ServicePersistenceStorage; public class WeatherInformationBatch extends IntentService { private static final String TAG = "WeatherInformationBatch"; private static final String resultsNumber = "14"; - private ServicePersistenceStorage mWeatherServicePersistenceFile; public WeatherInformationBatch() { @@ -38,7 +38,6 @@ public class WeatherInformationBatch extends IntentService { @Override public int onStartCommand(final Intent intent, final int flags, final int startId) { Log.i(TAG, "WeatherInformationBatch onStartCommand"); - this.mWeatherServicePersistenceFile = new ServicePersistenceStorage(this); return super.onStartCommand(intent, flags, startId); } @@ -46,19 +45,18 @@ public class WeatherInformationBatch extends IntentService { @Override protected void onHandleIntent(final Intent intent) { - final GeocodingData geocodingData = this.mWeatherServicePersistenceFile.getGeocodingData(); Log.i(TAG, "WeatherInformationBatch onHandleIntent"); - if (geocodingData != null) { + final WeatherLocation weatherLocation = this.queryDataBase(); + if (weatherLocation != null) { Log.i(TAG, "WeatherInformationBatch onHandleIntent, geocodingData not null"); final ServiceParser weatherService = new ServiceParser(new JPOSWeatherParser()); final CustomHTTPClient weatherHTTPClient = new CustomHTTPClient( AndroidHttpClient.newInstance("Android Weather Information Agent")); try { - final WeatherData weatherData = this.doInBackgroundThrowable(geocodingData, - weatherHTTPClient, weatherService); - this.onPostExecuteThrowable(weatherData); + this.doInBackgroundThrowable(weatherLocation,weatherHTTPClient, weatherService); + this.onPostExecuteThrowable(); } catch (final JsonParseException e) { Log.e(TAG, "doInBackground exception: ", e); } catch (final ClientProtocolException e) { @@ -76,7 +74,7 @@ public class WeatherInformationBatch extends IntentService { } } - private WeatherData doInBackgroundThrowable(final GeocodingData geocodingData, + private void doInBackgroundThrowable(final WeatherLocation weatherLocation, final CustomHTTPClient weatherHTTPClient, final ServiceParser weatherService) throws ClientProtocolException, MalformedURLException, URISyntaxException, JsonParseException, IOException { @@ -88,7 +86,7 @@ public class WeatherInformationBatch extends IntentService { String urlAPI = WeatherInformationBatch.this.getResources().getString( R.string.uri_api_weather_today); String url = weatherService.createURIAPICurrent(urlAPI, APIVersion, - geocodingData.getLatitude(), geocodingData.getLongitude()); + weatherLocation.getLatitude(), weatherLocation.getLongitude()); String jsonData = weatherHTTPClient.retrieveDataAsString(new URL(url)); final Current currentWeatherData = weatherService .retrieveCurrentFromJPOS(jsonData); @@ -99,22 +97,15 @@ public class WeatherInformationBatch extends IntentService { urlAPI = WeatherInformationBatch.this.getResources().getString( R.string.uri_api_weather_forecast); url = weatherService.createURIAPIForecast(urlAPI, APIVersion, - geocodingData.getLatitude(), geocodingData.getLongitude(), resultsNumber); + weatherLocation.getLatitude(), weatherLocation.getLongitude(), resultsNumber); jsonData = weatherHTTPClient.retrieveDataAsString(new URL(url)); final Forecast forecastWeatherData = weatherService .retrieveForecastFromJPOS(jsonData); - - return new WeatherData(forecastWeatherData, currentWeatherData); } - private void onPostExecuteThrowable(final WeatherData weatherData) + private void onPostExecuteThrowable() throws FileNotFoundException, IOException { - WeatherInformationBatch.this.mWeatherServicePersistenceFile - .storeCurrentWeatherData(weatherData.getCurrentWeatherData()); - WeatherInformationBatch.this.mWeatherServicePersistenceFile - .storeForecastWeatherData(weatherData.getForecastWeatherData()); - // Update weather views. final Intent updateCurrentWeather = new Intent( "de.example.exampletdd.UPDATECURRENTWEATHER"); @@ -126,23 +117,16 @@ public class WeatherInformationBatch extends IntentService { updateOverviewWeather); } - - private class WeatherData { - private final Forecast mForecastWeatherData; - private final Current mCurrentWeatherData; - - public WeatherData(final Forecast mForecastWeatherData, - final Current mCurrentWeatherData) { - this.mForecastWeatherData = mForecastWeatherData; - this.mCurrentWeatherData = mCurrentWeatherData; - } - - public Forecast getForecastWeatherData() { - return this.mForecastWeatherData; - } - - public Current getCurrentWeatherData() { - return this.mCurrentWeatherData; - } + + private WeatherLocation queryDataBase() { + + // TODO: repeating the same code!!! + final WeatherLocationDbHelper dbHelper = new WeatherLocationDbHelper(this); + try { + final WeatherLocationDbQueries queryDb = new WeatherLocationDbQueries(dbHelper); + return queryDb.queryDataBase(); + } finally { + dbHelper.close(); + } } } diff --git a/Android/WeatherInformation/src/de/example/exampletdd/WeatherTabsActivity.java b/Android/WeatherInformation/src/de/example/exampletdd/WeatherTabsActivity.java index bf48f00..cf89a7c 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/WeatherTabsActivity.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/WeatherTabsActivity.java @@ -17,7 +17,8 @@ import android.view.Menu; import android.view.MenuItem; import de.example.exampletdd.fragment.current.CurrentFragment; import de.example.exampletdd.fragment.overview.OverviewFragment; -import de.example.exampletdd.model.GeocodingData; +import de.example.exampletdd.model.DatabaseQueries; +import de.example.exampletdd.model.WeatherLocation; public class WeatherTabsActivity extends FragmentActivity { private static final int NUM_ITEMS = 2; @@ -126,16 +127,12 @@ public class WeatherTabsActivity extends FragmentActivity { final ActionBar actionBar = this.getActionBar(); - // TODO: retrive data from data base (like I do on WindowsPhone 8) // 1. Update title. - final GeocodingData geocodingData = new GeocodingData.Builder().build(); - 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(); + final DatabaseQueries query = new DatabaseQueries(this); + final WeatherLocation weatherLocation = query.queryDataBase(); + if (weatherLocation != null) { // TODO: I18N and comma :/ - actionBar.setTitle(city + "," + country); + actionBar.setTitle(weatherLocation.getCity() + "," + weatherLocation.getCountry()); } // 2. Update forecast tab text. @@ -156,10 +153,6 @@ public class WeatherTabsActivity extends FragmentActivity { @Override public void onSaveInstanceState(final Bundle savedInstanceState) { - final WeatherInformationApplication application = (WeatherInformationApplication) this - .getApplication(); - savedInstanceState.putSerializable("GEOCODINGDATA", application.getGeocodingData()); - super.onSaveInstanceState(savedInstanceState); } diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/current/CurrentFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/current/CurrentFragment.java index cc177ad..3f41ba0 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/fragment/current/CurrentFragment.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/fragment/current/CurrentFragment.java @@ -33,7 +33,8 @@ import com.fasterxml.jackson.core.JsonParseException; import de.example.exampletdd.R; import de.example.exampletdd.WeatherInformationApplication; import de.example.exampletdd.httpclient.CustomHTTPClient; -import de.example.exampletdd.model.GeocodingData; +import de.example.exampletdd.model.DatabaseQueries; +import de.example.exampletdd.model.WeatherLocation; import de.example.exampletdd.model.currentweather.Current; import de.example.exampletdd.parser.JPOSWeatherParser; import de.example.exampletdd.service.IconsList; @@ -77,9 +78,9 @@ public class CurrentFragment extends Fragment { public void onResume() { super.onResume(); - // TODO: retrive data from data base (like I do on WindowsPhone 8) - final GeocodingData geocodingData = new GeocodingData.Builder().build(); - if (geocodingData == null) { + final DatabaseQueries query = new DatabaseQueries(this.getActivity()); + final WeatherLocation weatherLocation = query.queryDataBase(); + if (weatherLocation == null) { // Nothing to do. return; } @@ -88,17 +89,17 @@ public class CurrentFragment extends Fragment { (WeatherInformationApplication) getActivity().getApplication(); final Current current = application.getCurrent(); - // TODO: Also check whether data is fresh (like I do on WindowsPhone 8) using data base - if (current != null /* && dataIsFresh() */) { + if (current != null && this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) { this.updateUI(current); } else { // Load remote data (aynchronous) // Gets the data from the web. final CurrentTask task = new CurrentTask( + this, new CustomHTTPClient(AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")), new ServiceParser(new JPOSWeatherParser())); - task.execute(geocodingData); + task.execute(weatherLocation.getLatitude(), weatherLocation.getLongitude()); // TODO: make sure UI thread keeps running in parallel after that. I guess. } } @@ -268,26 +269,45 @@ public class CurrentFragment extends Fragment { sunSetTimeView.setText(sunSetTime); } + private boolean isDataFresh(final Date lastUpdate) { + if (lastUpdate == null) { + return false; + } + + final Calendar calendar = Calendar.getInstance(); + final Date currentTime = calendar.getTime(); + if (((currentTime.getTime() - lastUpdate.getTime()) / 1000) < 30) { + return true; + } + + return false; + } + // TODO: How could I show just one progress dialog when I have two fragments in tabs // activity doing the same in background? // I mean, if OverviewTask shows one progress dialog and CurrentTask does the same I will have // have two progress dialogs... How may I solve this problem? I HATE ANDROID. - private class CurrentTask extends AsyncTask { + private class CurrentTask extends AsyncTask { + private final Fragment localFragment; final CustomHTTPClient weatherHTTPClient; final ServiceParser weatherService; - public CurrentTask(final CustomHTTPClient weatherHTTPClient, final ServiceParser weatherService) { + public CurrentTask(final Fragment fragment, final CustomHTTPClient weatherHTTPClient, + final ServiceParser weatherService) { + this.localFragment = fragment; this.weatherHTTPClient = weatherHTTPClient; this.weatherService = weatherService; } @Override - protected Current doInBackground(final GeocodingData... params) { - Log.i(TAG, "CurrentTask doInBackground"); + protected Current doInBackground(final Object... params) { + Log.i(TAG, "CurrentTask doInBackground"); + final double latitude = (Double) params[0]; + final double longitude = (Double) params[1]; + Current current = null; - try { - current = this.doInBackgroundThrowable(params[0], weatherHTTPClient, weatherService); + current = this.doInBackgroundThrowable(latitude, longitude, weatherHTTPClient, weatherService); } catch (final JsonParseException e) { Log.e(TAG, "CurrentTask doInBackground exception: ", e); } catch (final ClientProtocolException e) { @@ -306,14 +326,13 @@ public class CurrentFragment extends Fragment { return current; } - private Current doInBackgroundThrowable(final GeocodingData geocodingData, + private Current doInBackgroundThrowable(final double latitude, final double longitude, final CustomHTTPClient HTTPClient, final ServiceParser serviceParser) throws URISyntaxException, ClientProtocolException, JsonParseException, IOException { final String APIVersion = getResources().getString(R.string.api_version); final String urlAPI = getResources().getString(R.string.uri_api_weather_today); - final String url = weatherService.createURIAPICurrent(urlAPI, APIVersion, - geocodingData.getLatitude(), geocodingData.getLongitude()); + final String url = weatherService.createURIAPICurrent(urlAPI, APIVersion, latitude, longitude); final String jsonData = weatherHTTPClient.retrieveDataAsString(new URL(url)); final Current current = weatherService .retrieveCurrentFromJPOS(jsonData); @@ -341,7 +360,10 @@ public class CurrentFragment extends Fragment { (WeatherInformationApplication) getActivity().getApplication(); application.setCurrent(current); - // TODO: update last time update using data base (like I do on Windows Phone 8) + final DatabaseQueries query = new DatabaseQueries(this.localFragment.getActivity()); + final WeatherLocation weatherLocation = query.queryDataBase(); + weatherLocation.setLastCurrentUIUpdate(new Date()); + query.updateDataBase(weatherLocation); } } } diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/overview/OverviewFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/overview/OverviewFragment.java index a326a1b..f112dfa 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/fragment/overview/OverviewFragment.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/fragment/overview/OverviewFragment.java @@ -25,6 +25,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Parcelable; import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; import android.support.v4.app.ListFragment; import android.util.Log; import android.view.View; @@ -36,7 +37,8 @@ import de.example.exampletdd.R; import de.example.exampletdd.WeatherInformationApplication; import de.example.exampletdd.fragment.specific.SpecificFragment; import de.example.exampletdd.httpclient.CustomHTTPClient; -import de.example.exampletdd.model.GeocodingData; +import de.example.exampletdd.model.DatabaseQueries; +import de.example.exampletdd.model.WeatherLocation; import de.example.exampletdd.model.forecastweather.Forecast; import de.example.exampletdd.parser.JPOSWeatherParser; import de.example.exampletdd.service.IconsList; @@ -90,9 +92,9 @@ public class OverviewFragment extends ListFragment { public void onResume() { super.onResume(); - // TODO: retrive data from data base (like I do on WindowsPhone 8) - final GeocodingData geocodingData = new GeocodingData.Builder().build(); - if (geocodingData == null) { + final DatabaseQueries query = new DatabaseQueries(this.getActivity()); + final WeatherLocation weatherLocation = query.queryDataBase(); + if (weatherLocation == null) { // Nothing to do. return; } @@ -101,17 +103,17 @@ public class OverviewFragment extends ListFragment { (WeatherInformationApplication) getActivity().getApplication(); final Forecast forecast = application.getForecast(); - // TODO: Also check whether data is fresh (like I do on WindowsPhone 8) using data base - if (forecast != null /* && dataIsFresh() */) { + if (forecast != null && this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) { this.updateUI(forecast); } else { // Load remote data (aynchronous) // Gets the data from the web. final OverviewTask task = new OverviewTask( + this, new CustomHTTPClient(AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")), new ServiceParser(new JPOSWeatherParser())); - task.execute(geocodingData); + task.execute(weatherLocation.getLatitude(), weatherLocation.getLongitude()); // TODO: make sure thread UI keeps running in parallel after that. I guess. } @@ -255,27 +257,46 @@ public class OverviewFragment extends ListFragment { this.setListAdapter(adapter); } + private boolean isDataFresh(final Date lastUpdate) { + if (lastUpdate == null) { + return false; + } + + final Calendar calendar = Calendar.getInstance(); + final Date currentTime = calendar.getTime(); + if (((currentTime.getTime() - lastUpdate.getTime()) / 1000) < 30) { + return true; + } + + return false; + } // TODO: How could I show just one progress dialog when I have two fragments in tabs // activity doing the same in background? // I mean, if OverviewTask shows one progress dialog and CurrentTask does the same I will have // have two progress dialogs... How may I solve this problem? I HATE ANDROID. - private class OverviewTask extends AsyncTask { + private class OverviewTask extends AsyncTask { + private final Fragment localFragment; final CustomHTTPClient weatherHTTPClient; final ServiceParser weatherService; - public OverviewTask(final CustomHTTPClient weatherHTTPClient, final ServiceParser weatherService) { + public OverviewTask(final Fragment fragment, final CustomHTTPClient weatherHTTPClient, + final ServiceParser weatherService) { + this.localFragment = fragment; this.weatherHTTPClient = weatherHTTPClient; this.weatherService = weatherService; } @Override - protected Forecast doInBackground(final GeocodingData... params) { + protected Forecast doInBackground(final Object... params) { Log.i(TAG, "OverviewFragment doInBackground"); + final double latitude = (Double) params[0]; + final double longitude = (Double) params[1]; + Forecast forecast = null; try { - forecast = this.doInBackgroundThrowable(params[0], weatherHTTPClient, weatherService); + forecast = this.doInBackgroundThrowable(latitude, longitude, weatherHTTPClient, weatherService); } catch (final JsonParseException e) { Log.e(TAG, "OverviewTask doInBackground exception: ", e); } catch (final ClientProtocolException e) { @@ -294,15 +315,14 @@ public class OverviewFragment extends ListFragment { return forecast; } - private Forecast doInBackgroundThrowable(final GeocodingData geocodingData, + private Forecast doInBackgroundThrowable(final double latitude, final double longitude, final CustomHTTPClient HTTPClient, final ServiceParser serviceParser) throws URISyntaxException, ClientProtocolException, JsonParseException, IOException { final String APIVersion = getResources().getString(R.string.api_version); final String urlAPI = getResources().getString(R.string.uri_api_weather_forecast); // TODO: number as resource - final String url = serviceParser.createURIAPIForecast(urlAPI, APIVersion, - geocodingData.getLatitude(), geocodingData.getLongitude(), "14"); + final String url = serviceParser.createURIAPIForecast(urlAPI, APIVersion, latitude, longitude, "14"); final String jsonData = HTTPClient.retrieveDataAsString(new URL(url)); return serviceParser.retrieveForecastFromJPOS(jsonData); @@ -325,7 +345,10 @@ public class OverviewFragment extends ListFragment { (WeatherInformationApplication) getActivity().getApplication(); application.setForecast(forecast); - // TODO: update last time update using data base (like I do on Windows Phone 8) + final DatabaseQueries query = new DatabaseQueries(this.localFragment.getActivity()); + final WeatherLocation weatherLocation = query.queryDataBase(); + weatherLocation.setLastForecastUIUpdate(new Date()); + query.updateDataBase(weatherLocation); } } } diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/SpecificFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/SpecificFragment.java index 4a1dc3f..27b4ad7 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/SpecificFragment.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/fragment/specific/SpecificFragment.java @@ -8,7 +8,6 @@ import java.util.Date; import java.util.Locale; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; @@ -30,22 +29,7 @@ public class SpecificFragment extends Fragment { @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - - // Inflate the layout for this fragment - return inflater.inflate(R.layout.weather_specific_fragment, container, false); - } - - @Override - public void onConfigurationChanged(final Configuration newConfig) { - // I could do the same in onCreate because I allow rotations. - // see: http://stackoverflow.com/a/11286961 - // Anyhow I wanted to try this way just for fun. - + final Bundle extras = this.getActivity().getIntent().getExtras(); if (extras != null) { @@ -59,6 +43,14 @@ public class SpecificFragment extends Fragment { } @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + // Inflate the layout for this fragment + return inflater.inflate(R.layout.weather_specific_fragment, container, false); + } + + @Override public void onActivityCreated(final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -74,7 +66,7 @@ public class SpecificFragment extends Fragment { application.setForecast(forecast); } - this.mChosenDay = savedInstanceState.getInt("Chosen day"); + this.mChosenDay = savedInstanceState.getInt("mChosenDay"); } } @@ -92,9 +84,7 @@ public class SpecificFragment extends Fragment { savedInstanceState.putSerializable("Forecast", forecast); } - savedInstanceState.putInt("Chosend day", this.mChosenDay); - - // TODO: Why don't I need mListState? + savedInstanceState.putInt("mChosenDay", this.mChosenDay); super.onSaveInstanceState(savedInstanceState); } diff --git a/Android/WeatherInformation/src/de/example/exampletdd/model/DatabaseQueries.java b/Android/WeatherInformation/src/de/example/exampletdd/model/DatabaseQueries.java new file mode 100644 index 0000000..e53f97d --- /dev/null +++ b/Android/WeatherInformation/src/de/example/exampletdd/model/DatabaseQueries.java @@ -0,0 +1,44 @@ +package de.example.exampletdd.model; + +import android.content.Context; + +public class DatabaseQueries { + private final Context localContext; + + public DatabaseQueries(final Context context) { + this.localContext = context; + } + + public WeatherLocation queryDataBase() { + + final WeatherLocationDbHelper dbHelper = new WeatherLocationDbHelper(this.localContext); + try { + final WeatherLocationDbQueries queryDb = new WeatherLocationDbQueries(dbHelper); + return queryDb.queryDataBase(); + } finally { + dbHelper.close(); + } + } + + public long insertIntoDataBase(final WeatherLocation weatherLocation) { + + final WeatherLocationDbHelper dbHelper = new WeatherLocationDbHelper(this.localContext); + try { + final WeatherLocationDbQueries queryDb = new WeatherLocationDbQueries(dbHelper); + return queryDb.insertIntoDataBase(weatherLocation); + } finally { + dbHelper.close(); + } + } + + public void updateDataBase(final WeatherLocation weatherLocation) { + + final WeatherLocationDbHelper dbHelper = new WeatherLocationDbHelper(this.localContext); + try { + final WeatherLocationDbQueries queryDb = new WeatherLocationDbQueries(dbHelper); + queryDb.updateDataBase(weatherLocation); + } finally { + dbHelper.close(); + } + } +} diff --git a/Android/WeatherInformation/src/de/example/exampletdd/model/GeocodingData.java b/Android/WeatherInformation/src/de/example/exampletdd/model/GeocodingData.java deleted file mode 100644 index 0627bcd..0000000 --- a/Android/WeatherInformation/src/de/example/exampletdd/model/GeocodingData.java +++ /dev/null @@ -1,106 +0,0 @@ -package de.example.exampletdd.model; - -import java.io.Serializable; - - -public class GeocodingData implements Serializable { - private static final long serialVersionUID = 8607995242110846833L; - private final String city; - private final String country; - private final double latitude; - private final double longitude; - - public static class Builder { - private String mCity; - private String mCountry; - private double mLatitude; - private double mLongitude; - - public Builder setCity(final String city) { - this.mCity = city; - return this; - } - - public Builder setCountry(final String country) { - this.mCountry = country; - return this; - } - - public Builder setLatitude(final double latitude) { - this.mLatitude = latitude; - return this; - } - - public Builder setLongitude(final double longitude) { - this.mLongitude = longitude; - return this; - } - - public GeocodingData build() { - return new GeocodingData(this); - } - } - - private GeocodingData(final Builder builder) { - this.city = builder.mCity; - this.country = builder.mCountry; - this.latitude = builder.mLatitude; - this.longitude = builder.mLongitude; - } - - public String getCity() { - return this.city; - } - - public String getCountry() { - return this.country; - } - - public double getLatitude() { - return this.latitude; - } - - public double getLongitude() { - return this.longitude; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = (prime * result) + ((this.city == null) ? 0 : this.city.hashCode()); - result = (prime * result) + ((this.country == null) ? 0 : this.country.hashCode()); - long temp; - temp = Double.doubleToLongBits(this.latitude); - result = (prime * result) + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(this.longitude); - result = (prime * result) + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (this.getClass() != obj.getClass()) - return false; - final GeocodingData other = (GeocodingData) obj; - if (this.city == null) { - if (other.city != null) - return false; - } else if (!this.city.equals(other.city)) - return false; - if (this.country == null) { - if (other.country != null) - return false; - } else if (!this.country.equals(other.country)) - return false; - if (Double.doubleToLongBits(this.latitude) != Double.doubleToLongBits(other.latitude)) - return false; - if (Double.doubleToLongBits(this.longitude) != Double.doubleToLongBits(other.longitude)) - return false; - return true; - } -} diff --git a/Android/WeatherInformation/src/de/example/exampletdd/model/WeatherLocation.java b/Android/WeatherInformation/src/de/example/exampletdd/model/WeatherLocation.java index ae21c8f..f20b0b6 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/model/WeatherLocation.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/model/WeatherLocation.java @@ -5,66 +5,60 @@ import java.util.Date; public class WeatherLocation implements Serializable { - private static final long serialVersionUID = 1379832318334553377L; - private final String city; - private final String country; - private final double latitude; - private final double longitude; - private final Date lastCurrentUIUpdate; - private final Date lastForecastUIUpdate; + private static final long serialVersionUID = -1469725417020355109L; + private int id; + private String city; + private String country; + private boolean isSelected; + private double latitude; + private double longitude; + private Date lastCurrentUIUpdate; + private Date lastForecastUIUpdate; - public static class Builder { - private String mCity; - private String mCountry; - private double mLatitude; - private double mLongitude; - private Date mlastCurrentUIUpdate; - private Date mlastForecastUIUpdate; + public WeatherLocation setId(int id) { + this.id = id; + return this; + } - public Builder setCity(final String city) { - this.mCity = city; - return this; - } + public WeatherLocation setCity(String city) { + this.city = city; + return this; + } - public Builder setCountry(final String country) { - this.mCountry = country; - return this; - } + public WeatherLocation setCountry(String country) { + this.country = country; + return this; + } - public Builder setLatitude(final double latitude) { - this.mLatitude = latitude; - return this; - } + public WeatherLocation setIsSelected(boolean isSelected) { + this.isSelected = isSelected; + return this; + } - public Builder setLongitude(final double longitude) { - this.mLongitude = longitude; - return this; - } - - public Builder setlastCurrentUIUpdate(final Date lastCurrentUIUpdate) { - this.mlastCurrentUIUpdate = lastCurrentUIUpdate; - return this; - } - - public Builder setlastForecastUIUpdate(final Date lastForecastUIUpdate) { - this.mlastForecastUIUpdate = lastForecastUIUpdate; - return this; - } + public WeatherLocation setLatitude(double latitude) { + this.latitude = latitude; + return this; + } - public WeatherLocation build() { - return new WeatherLocation(this); - } - } + public WeatherLocation setLongitude(double longitude) { + this.longitude = longitude; + return this; + } - private WeatherLocation(final Builder builder) { - this.city = builder.mCity; - this.country = builder.mCountry; - this.latitude = builder.mLatitude; - this.longitude = builder.mLongitude; - this.lastCurrentUIUpdate = builder.mlastCurrentUIUpdate; - this.lastForecastUIUpdate = builder.mlastForecastUIUpdate; - } + public WeatherLocation setLastCurrentUIUpdate(Date lastCurrentUIUpdate) { + this.lastCurrentUIUpdate = lastCurrentUIUpdate; + return this; + } + public WeatherLocation setLastForecastUIUpdate(Date lastForecastUIUpdate) { + this.lastForecastUIUpdate = lastForecastUIUpdate; + return this; + } + + public int getId() { + return this.id; + } + public String getCity() { return this.city; } @@ -72,6 +66,10 @@ public class WeatherLocation implements Serializable { public String getCountry() { return this.country; } + + public boolean getIsSelected() { + return this.isSelected; + } public double getLatitude() { return this.latitude; @@ -81,11 +79,11 @@ public class WeatherLocation implements Serializable { return this.longitude; } - public Date getlastCurrentUIUpdate() { + public Date getLastCurrentUIUpdate() { return this.lastCurrentUIUpdate; } - public Date getlastForecastUIUpdate() { + public Date getLastForecastUIUpdate() { return this.lastForecastUIUpdate; } } diff --git a/Android/WeatherInformation/src/de/example/exampletdd/model/WeatherLocationDbQueries.java b/Android/WeatherInformation/src/de/example/exampletdd/model/WeatherLocationDbQueries.java index da96165..9f2e3e8 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/model/WeatherLocationDbQueries.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/model/WeatherLocationDbQueries.java @@ -1,6 +1,9 @@ package de.example.exampletdd.model; -import android.content.Context; +import java.util.Calendar; +import java.util.Date; + +import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; @@ -17,7 +20,7 @@ public class WeatherLocationDbQueries { this.mDbHelper = dbHelper; } - public WeatherLocation queryDataBase(final Context context) { + public WeatherLocation queryDataBase() { final String selection = WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED + " = ?"; final String[] selectionArgs = { "1" }; final String[] projection = { @@ -36,19 +39,46 @@ public class WeatherLocationDbQueries { @Override public WeatherLocation doQuery(final Cursor cursor) { - String city = cursor.getString(cursor. + final Calendar calendar = Calendar.getInstance(); + + final int id = cursor.getInt(cursor.getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation._ID)); + final String city = cursor.getString(cursor. getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_CITY)); - String country = cursor.getString(cursor. + final String country = cursor.getString(cursor. getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_COUNTRY)); - double latitude = cursor.getDouble(cursor. + final boolean isSelected = (cursor.getInt(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED)) == 0) ? false : true; + Date lastCurrentUIUpdate = null; + if (!cursor.isNull(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE))) { + final int UNIXTime = cursor.getInt(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE)); + calendar.setTimeInMillis((long)UNIXTime * 1000L); + lastCurrentUIUpdate = calendar.getTime(); + } + Date lasForecastUIUpdate = null; + if (!cursor.isNull(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE))) { + final int UNIXTime = cursor.getInt(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE)); + calendar.setTimeInMillis((long)UNIXTime * 1000L); + lastCurrentUIUpdate = calendar.getTime(); + } + final double latitude = cursor.getDouble(cursor. getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE)); - double longitude = cursor.getDouble(cursor. + final double longitude = cursor.getDouble(cursor. getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE)); + - return new WeatherLocation.Builder(). - setCity(city).setCountry(country). - setLatitude(latitude).setLongitude(longitude). - build(); + return new WeatherLocation() + .setId(id) + .setCity(city) + .setCountry(country) + .setIsSelected(isSelected) + .setLastCurrentUIUpdate(lastCurrentUIUpdate) + .setLastForecastUIUpdate(lasForecastUIUpdate) + .setLatitude(latitude) + .setLongitude(longitude); } }; @@ -56,7 +86,45 @@ public class WeatherLocationDbQueries { WeatherLocationContract.WeatherLocation.TABLE_NAME, projection, selectionArgs, selection, doQuery); } - + + public long insertIntoDataBase(final WeatherLocation weatherLocation) { + // Create a new map of values, where column names are the keys + final ContentValues values = new ContentValues(); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_CITY, weatherLocation.getCity()); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_COUNTRY, weatherLocation.getCountry()); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED, weatherLocation.getIsSelected()); + Date javaTime = weatherLocation.getLastCurrentUIUpdate(); + if (javaTime != null) { + final int UNIXTime = (int) javaTime.getTime() / 1000; + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE, UNIXTime); + } + javaTime = weatherLocation.getLastForecastUIUpdate(); + if (javaTime != null) { + final int UNIXTime = (int) javaTime.getTime() / 1000; + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE, UNIXTime); + } + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE, weatherLocation.getLatitude()); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE, weatherLocation.getLongitude()); + + return this.insertIntoDataBase(WeatherLocationContract.WeatherLocation.TABLE_NAME, values); + } + + public void updateDataBase(final WeatherLocation weatherLocation) { + final String selection = WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED + " = ?"; + final String[] selectionArgs = { "1" }; + // Create a new map of values, where column names are the keys + final ContentValues values = new ContentValues(); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_CITY, weatherLocation.getCity()); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_COUNTRY, weatherLocation.getCountry()); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED, weatherLocation.getIsSelected()); + values.putNull(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE); + values.putNull(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE, weatherLocation.getLatitude()); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE, weatherLocation.getLongitude()); + + this.updateDataBase(WeatherLocationContract.WeatherLocation.TABLE_NAME, selectionArgs, selection, values); + } + // TODO: May I perform another query after this method (after closing almost everything but mDbHelper) private WeatherLocation queryDataBase(final String table, final String[] projection, final String[] selectionArgs, @@ -80,4 +148,25 @@ public class WeatherLocationDbQueries { } } + // TODO: May I perform another query after this method (after closing almost everything but mDbHelper) + private long insertIntoDataBase(final String table, final ContentValues values) { + final SQLiteDatabase db = this.mDbHelper.getWritableDatabase(); + try { + return db.insert(table, null, values); + } finally { + db.close(); + } + } + + // TODO: May I perform another query after this method (after closing almost everything but mDbHelper) + private long updateDataBase(final String table, final String[] selectionArgs, + final String selection, final ContentValues values) { + final SQLiteDatabase db = this.mDbHelper.getReadableDatabase(); + try { + return db.update(table, values, selection, selectionArgs); + } finally { + db.close(); + } + } + } diff --git a/Android/WeatherInformation/src/de/example/exampletdd/service/ServicePersistenceStorage.java b/Android/WeatherInformation/src/de/example/exampletdd/service/ServicePersistenceStorage.java deleted file mode 100644 index 139ce46..0000000 --- a/Android/WeatherInformation/src/de/example/exampletdd/service/ServicePersistenceStorage.java +++ /dev/null @@ -1,217 +0,0 @@ -package de.example.exampletdd.service; - -import java.io.File; -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 android.util.Log; -import de.example.exampletdd.model.GeocodingData; -import de.example.exampletdd.model.currentweather.Current; -import de.example.exampletdd.model.forecastweather.Forecast; - -/** - * TODO: show some error message when there is no enough space for saving files. :/ - * - */ -public class ServicePersistenceStorage { - private static final String TAG = "ServicePersistenceStorage"; - private static final String CURRENT_WEATHER_DATA_FILE = "current_weatherdata.file"; - private static final String CURRENT_WEATHER_DATA_TEMPORARY_FILE = "current_weatherdata.tmp.file"; - private static final String FORECAST_WEATHER_DATA_FILE = "forecast_weatherdata.file"; - private static final String FORECAST_WEATHER_DATA_TEMPORARY_FILE = "forecast_weatherdata.tmp.file"; - private static final String WEATHER_GEOCODING_FILE = "weathergeocoding.file"; - private static final String WEATHER_GEOCODING_TEMPORARY_FILE = "weathergeocoding.tmp.file"; - private final Context context; - - public ServicePersistenceStorage(final Context context) { - this.context = context; - } - - public void storeGeocodingData(final GeocodingData geocodingData) - throws FileNotFoundException, IOException { - final OutputStream persistenceFile = this.context.openFileOutput( - WEATHER_GEOCODING_TEMPORARY_FILE, Context.MODE_PRIVATE); - - ObjectOutputStream oos = null; - try { - oos = new ObjectOutputStream(persistenceFile); - - oos.writeObject(geocodingData); - } finally { - if (oos != null) { - oos.close(); - } - } - - this.renameFile(WEATHER_GEOCODING_TEMPORARY_FILE, WEATHER_GEOCODING_FILE); - } - - public GeocodingData getGeocodingData() { - GeocodingData geocodingData = null; - - try { - geocodingData = this.getGeocodingDataThrowable(); - } catch (final StreamCorruptedException e) { - Log.e(TAG, "getGeocodingData exception: ", e); - } catch (final FileNotFoundException e) { - Log.e(TAG, "getGeocodingData exception: ", e); - } catch (final IOException e) { - Log.e(TAG, "getGeocodingData exception: ", e); - } catch (final ClassNotFoundException e) { - Log.e(TAG, "getGeocodingData exception: ", e); - } - - return geocodingData; - } - - private GeocodingData getGeocodingDataThrowable() - throws StreamCorruptedException, FileNotFoundException, - IOException, ClassNotFoundException { - final InputStream persistenceFile = this.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 removeGeocodingData() { - this.context.deleteFile(WEATHER_GEOCODING_FILE); - } - - public void storeCurrentWeatherData(final Current currentWeatherData) - throws FileNotFoundException, IOException { - final OutputStream persistenceFile = this.context.openFileOutput( - CURRENT_WEATHER_DATA_FILE, Context.MODE_PRIVATE); - - ObjectOutputStream oos = null; - try { - oos = new ObjectOutputStream(persistenceFile); - - oos.writeObject(currentWeatherData); - } finally { - if (oos != null) { - oos.close(); - } - } - - this.renameFile(CURRENT_WEATHER_DATA_TEMPORARY_FILE, CURRENT_WEATHER_DATA_FILE); - } - - public Current getCurrentWeatherData() { - Current currentWeatherData = null; - - try { - currentWeatherData = this.getCurrentWeatherDataThrowable(); - } catch (final StreamCorruptedException e) { - Log.e(TAG, "getWeatherData exception: ", e); - } catch (final FileNotFoundException e) { - Log.e(TAG, "getWeatherData exception: ", e); - } catch (final IOException e) { - Log.e(TAG, "getWeatherData exception: ", e); - } catch (final ClassNotFoundException e) { - Log.e(TAG, "getWeatherData exception: ", e); - } - - return currentWeatherData; - } - - private Current getCurrentWeatherDataThrowable() - throws StreamCorruptedException, - FileNotFoundException, IOException, ClassNotFoundException { - final InputStream persistenceFile = this.context.openFileInput( - CURRENT_WEATHER_DATA_FILE); - - ObjectInputStream ois = null; - try { - ois = new ObjectInputStream(persistenceFile); - - return (Current) ois.readObject(); - } finally { - if (ois != null) { - ois.close(); - } - } - } - - public void removeCurrentWeatherData() { - this.context.deleteFile(CURRENT_WEATHER_DATA_FILE); - } - - public void storeForecastWeatherData(final Forecast forecastWeatherData) - throws FileNotFoundException, IOException { - final OutputStream persistenceFile = this.context.openFileOutput(FORECAST_WEATHER_DATA_FILE, - Context.MODE_PRIVATE); - - ObjectOutputStream oos = null; - try { - oos = new ObjectOutputStream(persistenceFile); - - oos.writeObject(forecastWeatherData); - } finally { - if (oos != null) { - oos.close(); - } - } - - this.renameFile(FORECAST_WEATHER_DATA_TEMPORARY_FILE, FORECAST_WEATHER_DATA_FILE); - } - - public Forecast getForecastWeatherData() { - Forecast forecastWeatherData = null; - - try { - forecastWeatherData = this.getForecastWeatherDataThrowable(); - } catch (final StreamCorruptedException e) { - Log.e(TAG, "getWeatherData exception: ", e); - } catch (final FileNotFoundException e) { - Log.e(TAG, "getWeatherData exception: ", e); - } catch (final IOException e) { - Log.e(TAG, "getWeatherData exception: ", e); - } catch (final ClassNotFoundException e) { - Log.e(TAG, "getWeatherData exception: ", e); - } - - return forecastWeatherData; - } - - private Forecast getForecastWeatherDataThrowable() throws StreamCorruptedException, - FileNotFoundException, IOException, ClassNotFoundException { - final InputStream persistenceFile = this.context.openFileInput(FORECAST_WEATHER_DATA_FILE); - - ObjectInputStream ois = null; - try { - ois = new ObjectInputStream(persistenceFile); - - return (Forecast) ois.readObject(); - } finally { - if (ois != null) { - ois.close(); - } - } - } - - public void removeForecastWeatherData() { - this.context.deleteFile(FORECAST_WEATHER_DATA_FILE); - } - - private void renameFile(final String temporaryName, final String finalName) { - final File filesDir = this.context.getFilesDir(); - final File temporaryFile = new File(filesDir, temporaryName); - final File endFile = new File(filesDir, finalName); - temporaryFile.renameTo(endFile); - } -} -- 2.1.4