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,
// just once
this.mRestoreUI = null;
} else {
- weatherLocation = queryDataBase();
+ final DatabaseQueries query = new DatabaseQueries(this);
+ weatherLocation = query.queryDataBase();
}
if (weatherLocation != null) {
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);
}
}
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) {
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
}
}
}
-
- 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) {
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) {
}
}
- return new WeatherLocation.Builder()
- .setLatitude(latitude).setLongitude(longitude)
- .setCity(city).setCountry(country)
- .build();
+ return new WeatherLocation()
+ .setLatitude(latitude)
+ .setLongitude(longitude)
+ .setCity(city)
+ .setCountry(country);
}
}
// 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);
}
// 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();
}
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);
}
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 {
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());
}
}
}
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;
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;
+ }
+}
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() {
@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);
}
@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) {
}
}
- private WeatherData doInBackgroundThrowable(final GeocodingData geocodingData,
+ private void doInBackgroundThrowable(final WeatherLocation weatherLocation,
final CustomHTTPClient weatherHTTPClient, final ServiceParser weatherService)
throws ClientProtocolException, MalformedURLException, URISyntaxException,
JsonParseException, IOException {
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);
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");
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();
+ }
}
}
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;
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.
@Override
public void onSaveInstanceState(final Bundle savedInstanceState) {
- final WeatherInformationApplication application = (WeatherInformationApplication) this
- .getApplication();
- savedInstanceState.putSerializable("GEOCODINGDATA", application.getGeocodingData());
-
super.onSaveInstanceState(savedInstanceState);
}
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;
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;
}
(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.
}
}
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<GeocodingData, Void, Current> {
+ private class CurrentTask extends AsyncTask<Object, Void, Current> {
+ 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) {
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);
(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);
}
}
}
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;
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;
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;
}
(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.
}
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<GeocodingData, Void, Forecast> {
+ private class OverviewTask extends AsyncTask<Object, Void, Forecast> {
+ 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) {
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);
(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);
}
}
}
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;
@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) {
}
@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);
application.setForecast(forecast);
}
- this.mChosenDay = savedInstanceState.getInt("Chosen day");
+ this.mChosenDay = savedInstanceState.getInt("mChosenDay");
}
}
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);
}
--- /dev/null
+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();
+ }
+ }
+}
+++ /dev/null
-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;
- }
-}
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;
}
public String getCountry() {
return this.country;
}
+
+ public boolean getIsSelected() {
+ return this.isSelected;
+ }
public double getLatitude() {
return this.latitude;
return this.longitude;
}
- public Date getlastCurrentUIUpdate() {
+ public Date getLastCurrentUIUpdate() {
return this.lastCurrentUIUpdate;
}
- public Date getlastForecastUIUpdate() {
+ public Date getLastForecastUIUpdate() {
return this.lastForecastUIUpdate;
}
}
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;
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 = {
@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);
}
};
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,
}
}
+ // 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();
+ }
+ }
+
}
+++ /dev/null
-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);
- }
-}