android:theme="@style/AppTheme" >
<activity
android:name="de.example.exampletdd.WeatherInformationActivity"
+ android:uiOptions="splitActionBarWhenNarrow"
android:hardwareAccelerated="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_above="@+id/buttonweather"
- android:layout_below="@+id/weather_map_citycountry_data" />
-
- <Button
- android:id="@+id/buttonweather"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
- android:layout_centerHorizontal="true"
- android:onClick="setChosenLocation"
- android:text="@string/button_set_chosen_location" />
-
+ android:layout_below="@+id/weather_map_citycountry_data" />
</RelativeLayout>
package de.example.exampletdd;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.StreamCorruptedException;
+
import android.app.ActionBar;
import android.app.Activity;
import android.app.DialogFragment;
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceManager;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import de.example.exampletdd.activityinterface.ErrorMessage;
import de.example.exampletdd.activityinterface.GetWeather;
import de.example.exampletdd.fragment.ErrorDialogFragment;
import de.example.exampletdd.fragment.WeatherInformationDataFragment;
+import de.example.exampletdd.model.GeocodingData;
+import de.example.exampletdd.model.WeatherData;
public class WeatherInformationActivity extends Activity implements ErrorMessage {
+ private static final String WEATHER_DATA_FILE = "weatherdata.file";
+ private static final String WEATHER_GEOCODING_FILE = "weathergeocoding.file";
+ private static final String TAG = "WeatherInformationActivity";
private GetWeather mGetWeather;
@Override
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE);
- actionBar.setTitle(this.getString(R.string.header_action_bar));
actionBar.setDisplayHomeAsUpEnabled(true);
// Better using xml files? How to deal with savedInstanceState with xml files?
.getFragmentManager().findFragmentById(R.id.weather_data_frag);
this.mGetWeather = weatherDataFragment;
-
}
@Override
}
@Override
+ public void onResume() {
+ super.onResume();
+
+ final ActionBar actionBar = this.getActionBar();
+
+ GeocodingData geocodingData = null;
+ try {
+ geocodingData = this.restoreGeocodingDataFromFile();
+ } catch (final StreamCorruptedException e) {
+ Log.e(TAG, "onCreate exception: ", e);
+ } catch (final FileNotFoundException e) {
+ Log.e(TAG, "onCreate exception: ", e);
+ } catch (final IOException e) {
+ Log.e(TAG, "onCreate exception: ", e);
+ } catch (final ClassNotFoundException e) {
+ Log.e(TAG, "onCreate exception: ", e);
+ }
+ if (geocodingData != null) {
+ final String city = (geocodingData.getCity() == null) ? "city not found"
+ : geocodingData.getCity();
+ final String country = (geocodingData.getCountry() == null) ? "country not found"
+ : geocodingData.getCountry();
+ actionBar.setTitle(city + "," + country);
+ }
+
+ }
+
+ @Override
+ public void onRestoreInstanceState(final Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+
+ final ActionBar actionBar = this.getActionBar();
+
+ GeocodingData geocodingData = null;
+ try {
+ geocodingData = this.restoreGeocodingDataFromFile();
+ } catch (final StreamCorruptedException e) {
+ Log.e(TAG, "onCreate exception: ", e);
+ } catch (final FileNotFoundException e) {
+ Log.e(TAG, "onCreate exception: ", e);
+ } catch (final IOException e) {
+ Log.e(TAG, "onCreate exception: ", e);
+ } catch (final ClassNotFoundException e) {
+ Log.e(TAG, "onCreate exception: ", e);
+ }
+ if (geocodingData != null) {
+ final String city = (geocodingData.getCity() == null) ? "city not found"
+ : geocodingData.getCity();
+ final String country = (geocodingData.getCountry() == null) ? "country not found"
+ : geocodingData.getCountry();
+ actionBar.setTitle(city + "," + country);
+ }
+
+ WeatherData weatherData = null;
+ try {
+ weatherData = this.restoreWeatherDataFromFile();
+ } catch (final StreamCorruptedException e) {
+ Log.e(TAG, "onResume exception: ", e);
+ } catch (final FileNotFoundException e) {
+ Log.e(TAG, "onResume exception: ", e);
+ } catch (final IOException e) {
+ Log.e(TAG, "onResume exception: ", e);
+ } catch (final ClassNotFoundException e) {
+ Log.e(TAG, "onResume exception: ", e);
+ }
+
+ if (weatherData != null) {
+ this.mGetWeather.updateWeatherData(weatherData);
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(final Bundle savedInstanceState) {
+
+ super.onSaveInstanceState(savedInstanceState);
+ }
+
+ @Override
public void createErrorDialog(final int title) {
final DialogFragment newFragment = ErrorDialogFragment
.newInstance(title);
this.mGetWeather.getWeather();
}
+ private GeocodingData restoreGeocodingDataFromFile()
+ throws StreamCorruptedException, FileNotFoundException,
+ IOException, ClassNotFoundException {
+ final InputStream persistenceFile = this.openFileInput(
+ WEATHER_GEOCODING_FILE);
+
+ ObjectInputStream ois = null;
+ try {
+ ois = new ObjectInputStream(persistenceFile);
+
+ return (GeocodingData) ois.readObject();
+ } finally {
+ if (ois != null) {
+ ois.close();
+ }
+ }
+ }
+
+ private WeatherData restoreWeatherDataFromFile()
+ throws StreamCorruptedException, FileNotFoundException,
+ IOException, ClassNotFoundException {
+ final InputStream persistenceFile = this.openFileInput(WEATHER_DATA_FILE);
+
+ ObjectInputStream ois = null;
+ try {
+ ois = new ObjectInputStream(persistenceFile);
+
+ return (WeatherData) ois.readObject();
+ } finally {
+ if (ois != null) {
+ ois.close();
+ }
+ }
+ }
}
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.StreamCorruptedException;
-import java.text.DecimalFormat;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import android.app.Activity;
-import android.app.DialogFragment;
import android.content.Context;
+import android.location.Address;
+import android.location.Geocoder;
import android.os.Bundle;
import android.util.Log;
-import android.view.View;
import android.widget.TextView;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
-import de.example.exampletdd.fragment.ErrorDialogFragment;
import de.example.exampletdd.model.GeocodingData;
public class WeatherInformationMapActivity extends Activity {
private static final String TAG = "WeatherInformationMapActivity";
private GoogleMap mMap;
private Marker mMarker;
+ private ExecutorService mExec;
@Override
protected void onCreate(final Bundle savedInstanceState) {
this.mMap.getUiSettings().setCompassEnabled(false);
this.mMap.setOnMapLongClickListener(new LongClickListener());
this.mMap.setOnMarkerClickListener(new MarkerClickListener());
+
+
+ this.mExec = Executors.newSingleThreadExecutor();
}
@Override
point).draggable(
true));
- final DecimalFormat tempFormatter = new DecimalFormat("#####.#####");
final TextView cityCountry = (TextView) WeatherInformationMapActivity.this
.findViewById(R.id.weather_map_citycountry_data);
- final String latitude = tempFormatter.format(point.latitude);
- final String longitude = tempFormatter.format(point.longitude);
- cityCountry.setText(latitude + "," + longitude);
+ final String city = (geocodingData.getCity() == null) ? "city not found"
+ : geocodingData.getCity();
+ final String country = (geocodingData.getCountry() == null) ? "country not found"
+ : geocodingData.getCountry();
+ cityCountry.setText(city + "," + country);
}
}
- public void setChosenLocation(final View view) {
-
- if (this.mMarker == null) {
- return;
- }
-
- final LatLng coordinates = this.mMarker.getPosition();
-
- final GeocodingData geocodingData = new GeocodingData.Builder()
- .setLatitude(coordinates.latitude)
- .setLongitude(coordinates.longitude).build();
-
- try {
- this.storeGeocodingDataToFile(geocodingData);
- } catch (final IOException e) {
- Log.e(TAG, "Store geocoding data exception: ", e);
- this.createErrorDialog(R.string.error_dialog_store_geocoding_data);
+ @Override
+ public void onDestroy() {
+ if (this.mExec != null) {
+ this.mExec.shutdownNow();
}
-
- }
-
- public void createErrorDialog(final int title) {
- final DialogFragment newFragment = ErrorDialogFragment
- .newInstance(title);
- newFragment.show(this.getFragmentManager(), "errorDialog");
+ super.onDestroy();
}
private void storeGeocodingDataToFile(final GeocodingData geocodingData)
}
private class LongClickListener implements OnMapLongClickListener {
+ private static final String TAG = "LongClickListener";
@Override
public void onMapLongClick(final LatLng point) {
WeatherInformationMapActivity.this.mMarker.setPosition(point);
}
- final DecimalFormat tempFormatter = new DecimalFormat("#####.#####");
- final TextView cityCountry = (TextView) WeatherInformationMapActivity.this
- .findViewById(R.id.weather_map_citycountry_data);
- final String latitude = tempFormatter.format(point.latitude);
- final String longitude = tempFormatter.format(point.longitude);
- cityCountry.setText(latitude + "," + longitude);
+ final Future<GeocodingData> task = WeatherInformationMapActivity.this.mExec
+ .submit(new GeocoderTask(point.latitude, point.longitude));
+ try {
+ final GeocodingData geocodingData = task.get(5,
+ TimeUnit.SECONDS);
+ final TextView cityCountry = (TextView) WeatherInformationMapActivity.this
+ .findViewById(R.id.weather_map_citycountry_data);
+
+ final String city = (geocodingData.getCity() == null) ? "city not found"
+ : geocodingData.getCity();
+ final String country = (geocodingData.getCountry() == null) ? "country not found"
+ : geocodingData.getCountry();
+ cityCountry.setText(city + "," + country);
+
+ WeatherInformationMapActivity.this
+ .storeGeocodingDataToFile(geocodingData);
+ } catch (final InterruptedException e) {
+ Log.e(TAG, "LongClickListener exception: ", e);
+ Thread.currentThread().interrupt();
+ } catch (final ExecutionException e) {
+ final Throwable cause = e.getCause();
+ Log.e(TAG, "LongClickListener exception: ", cause);
+ } catch (final TimeoutException e) {
+ Log.e(TAG, "LongClickListener exception: ", e);
+ } catch (final FileNotFoundException e) {
+ Log.e(TAG, "LongClickListener exception: ", e);
+ } catch (final IOException e) {
+ Log.e(TAG, "LongClickListener exception: ", e);
+ } finally {
+ task.cancel(true);
+ }
+
+ }
+ }
+
+ public class GeocoderTask implements Callable<GeocodingData> {
+ private final double latitude;
+ private final double longitude;
+
+ public GeocoderTask(final double latitude, final double longitude) {
+ this.latitude = latitude;
+ this.longitude = longitude;
+ }
+
+ @Override
+ public GeocodingData call() throws Exception {
+ final Geocoder geocoder = new Geocoder(
+ WeatherInformationMapActivity.this, Locale.getDefault());
+ final List<Address> addresses = geocoder.getFromLocation(
+ this.latitude, this.longitude, 1);
+
+ if (addresses == null) {
+ return null;
+ }
+
+ if (addresses.size() <= 0) {
+ return null;
+ }
+
+ return new GeocodingData.Builder()
+ .setLatitude(this.latitude)
+ .setLongitude(this.longitude)
+ .setCity(addresses.get(0).getLocality())
+ .setCountry(addresses.get(0).getCountryName())
+ .build();
}
}
package de.example.exampletdd.activityinterface;
+import de.example.exampletdd.model.WeatherData;
public interface GetWeather {
public void getWeather();
+ public void updateWeatherData(final WeatherData weatherData);
+
}
import java.net.URISyntaxException;
import java.net.URL;
import java.text.DecimalFormat;
+import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
+import java.util.Locale;
import org.apache.http.client.ClientProtocolException;
import org.json.JSONException;
}
}
+ @Override
public void updateWeatherData(final WeatherData weatherData) {
- final DecimalFormat tempFormatter = new DecimalFormat("#####.#####");
- final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss Z");
+ final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
+ tempFormatter.applyPattern("#####.#####");
+ final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss Z", Locale.US);
+
final double tempUnits = this.mIsFahrenheit ? 0 : 273.15;
final List<WeatherDataEntry> entries = this.createEmptyEntriesList();
package de.example.exampletdd.model;
import java.io.Serializable;
-import java.util.HashMap;
public class GeocodingData implements Serializable {
- private static final long serialVersionUID = -6774793966351174343L;
+ private static final long serialVersionUID = 8607995242110846833L;
private final String city;
private final String country;
- private final GeocodingStatus status;
private final double latitude;
private final double longitude;
public static class Builder {
private String mCity;
private String mCountry;
- private GeocodingStatus mStatus;
private double mLatitude;
private double mLongitude;
return this;
}
- public Builder setStatus(final GeocodingStatus status) {
- this.mStatus = status;
- return this;
- }
-
public Builder setLatitude(final double latitude) {
this.mLatitude = latitude;
return this;
super();
this.city = builder.mCity;
this.country = builder.mCountry;
- this.status = builder.mStatus;
this.latitude = builder.mLatitude;
this.longitude = builder.mLongitude;
}
return this.country;
}
- public GeocodingStatus getStatus() {
- return this.status;
- }
-
public double getLatitude() {
return this.latitude;
}
public double getLongitude() {
return this.longitude;
}
-
- public enum GeocodingStatus {
- // see: https://developers.google.com/maps/documentation/geocoding/
- OK("OK"),
- ZERO_RESULTS("ZERO_RESULTS"),
- OVER_QUERY_LIMIT("OVER_QUERY_LIMIT"),
- REQUEST_DENIED("REQUEST_DENIED"),
- INVALID_REQUEST("INVALID_REQUEST"),
- UNKNOWN_ERROR("UNKNOWN_ERROR");
-
- private final String codeValue;
- private static final HashMap<String, GeocodingStatus> mapStatus =
- new HashMap<String, GeocodingStatus>();
-
- static {
- for (final GeocodingStatus status : GeocodingStatus.values()) {
- mapStatus.put(status.codeValue, status);
- }
- }
-
- private GeocodingStatus(final String codeValue) {
- this.codeValue = codeValue;
- }
-
- public static GeocodingStatus getGeocodingStatus(final String value) {
- return mapStatus.get(value);
- }
-
- }
}