From: Gustavo Martin Morcuende Date: Sat, 15 Nov 2014 14:52:00 +0000 (+0100) Subject: WeatherInformation: using package name.gumartinm.weather.information X-Git-Tag: weatherinformation-1.0~67 X-Git-Url: https://git.gumartinm.name/?a=commitdiff_plain;h=b82b32d7da39f509e3eb466f9e190c39f31d5262;p=AndroidWeatherInformation WeatherInformation: using package name.gumartinm.weather.information --- diff --git a/app/build.gradle b/app/build.gradle index f3c4e75..464cb5e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,11 +5,11 @@ android { buildToolsVersion "20.0.0" defaultConfig { - applicationId "com.weather.information" + applicationId "name.gumartinm.weather.information" minSdkVersion 18 targetSdkVersion 18 - testApplicationId "com.weather.information.test" + testApplicationId "name.gumartinm.weather.information.test" testInstrumentationRunner "android.test.InstrumentationTestRunner" } diff --git a/app/src/androidTest/java/com/weather/information/test/JPOSWeatherParserTest.java b/app/src/androidTest/java/com/weather/information/test/JPOSWeatherParserTest.java deleted file mode 100644 index 9ffb646..0000000 --- a/app/src/androidTest/java/com/weather/information/test/JPOSWeatherParserTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.weather.information.test; - -import com.weather.information.parser.JPOSWeatherParser; - -import junit.framework.TestCase; - -import org.json.JSONException; - -public class JPOSWeatherParserTest extends TestCase { - private JPOSWeatherParser jposWeatherParser; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - this.jposWeatherParser = new JPOSWeatherParser(); - } - - public void testRetrieveWeatherFromJPOS() throws JSONException { - // Arrange - final String jsonData = "{\"coord\":{\"lon\":139,\"lat\":35}}"; - final double longitude = 139; - final double latitude = 35; - final WeatherData.Coord coord = new WeatherData.Coord(longitude, latitude); - final WeatherData expectedWeather = new WeatherData.Builder().setCoord(coord).build(); - - // Act - final WeatherData finalWeather = this.jposWeatherParser.retrieveWeatherFromJPOS(jsonData); - - // Assert - assertEquals(expectedWeather.toString(), finalWeather.toString()); - } - -} diff --git a/app/src/androidTest/java/com/weather/information/test/WeatherInformationActivityUnitTest.java b/app/src/androidTest/java/com/weather/information/test/WeatherInformationActivityUnitTest.java deleted file mode 100644 index 7feba9a..0000000 --- a/app/src/androidTest/java/com/weather/information/test/WeatherInformationActivityUnitTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.weather.information.test; - -import android.content.Intent; -import android.widget.Button; - -public class WeatherInformationActivityUnitTest extends - ActivityUnitTestCase { - - private WeatherInformationActivity activity; - - public WeatherInformationActivityUnitTest() { - super(WeatherInformationActivity.class); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - final Intent intent = new Intent(this.getInstrumentation().getTargetContext(), - WeatherInformationActivity.class); - this.startActivity(intent, null, null); - this.activity = this.getActivity(); - } - - public void testIntentTriggerViaOnClick() { - final int buttonweather = com.weather.information.R.id.buttonweather; - final Button view = (Button) this.activity.findViewById(buttonweather); - assertNotNull("Button Weather not allowed to be null", view); - - view.performClick(); - - // TouchUtils cannot be used, only allowed in - // InstrumentationTestCase or ActivityInstrumentationTestCase2 - - // Check the intent which was started - final Intent triggeredIntent = this.getStartedActivityIntent(); - assertNotNull("Intent was null", triggeredIntent); - final String data = triggeredIntent.getDataString(); - - assertEquals("Incorrect data passed via the intent", - "http://gumartinm.name", data); - } -} diff --git a/app/src/androidTest/java/name/gumartinm/weather/information/test/JPOSWeatherParserTest.java b/app/src/androidTest/java/name/gumartinm/weather/information/test/JPOSWeatherParserTest.java new file mode 100644 index 0000000..3583d52 --- /dev/null +++ b/app/src/androidTest/java/name/gumartinm/weather/information/test/JPOSWeatherParserTest.java @@ -0,0 +1,34 @@ +package name.gumartinm.weather.information.test; + +import name.gumartinm.weather.information.parser.JPOSWeatherParser; + +import junit.framework.TestCase; + +import org.json.JSONException; + +public class JPOSWeatherParserTest extends TestCase { + private JPOSWeatherParser jposWeatherParser; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + this.jposWeatherParser = new JPOSWeatherParser(); + } + + public void testRetrieveWeatherFromJPOS() throws JSONException { + // Arrange + final String jsonData = "{\"coord\":{\"lon\":139,\"lat\":35}}"; + final double longitude = 139; + final double latitude = 35; + final WeatherData.Coord coord = new WeatherData.Coord(longitude, latitude); + final WeatherData expectedWeather = new WeatherData.Builder().setCoord(coord).build(); + + // Act + final WeatherData finalWeather = this.jposWeatherParser.retrieveWeatherFromJPOS(jsonData); + + // Assert + assertEquals(expectedWeather.toString(), finalWeather.toString()); + } + +} diff --git a/app/src/androidTest/java/name/gumartinm/weather/information/test/WeatherInformationActivityUnitTest.java b/app/src/androidTest/java/name/gumartinm/weather/information/test/WeatherInformationActivityUnitTest.java new file mode 100644 index 0000000..1a57bc7 --- /dev/null +++ b/app/src/androidTest/java/name/gumartinm/weather/information/test/WeatherInformationActivityUnitTest.java @@ -0,0 +1,42 @@ +package name.gumartinm.weather.information.test; + +import android.content.Intent; +import android.widget.Button; + +public class WeatherInformationActivityUnitTest extends + ActivityUnitTestCase { + + private WeatherInformationActivity activity; + + public WeatherInformationActivityUnitTest() { + super(WeatherInformationActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + final Intent intent = new Intent(this.getInstrumentation().getTargetContext(), + WeatherInformationActivity.class); + this.startActivity(intent, null, null); + this.activity = this.getActivity(); + } + + public void testIntentTriggerViaOnClick() { + final int buttonweather = name.gumartinm.weather.information.R.id.buttonweather; + final Button view = (Button) this.activity.findViewById(buttonweather); + assertNotNull("Button Weather not allowed to be null", view); + + view.performClick(); + + // TouchUtils cannot be used, only allowed in + // InstrumentationTestCase or ActivityInstrumentationTestCase2 + + // Check the intent which was started + final Intent triggeredIntent = this.getStartedActivityIntent(); + assertNotNull("Intent was null", triggeredIntent); + final String data = triggeredIntent.getDataString(); + + assertEquals("Incorrect data passed via the intent", + "http://gumartinm.name", data); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e9f29e5..084b98b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ diff --git a/app/src/main/java/com/weather/information/activity/AboutActivity.java b/app/src/main/java/com/weather/information/activity/AboutActivity.java deleted file mode 100644 index dd84525..0000000 --- a/app/src/main/java/com/weather/information/activity/AboutActivity.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.weather.information.activity; - -import android.app.ActionBar; -import android.app.Activity; -import android.content.ComponentName; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.View; - -import com.weather.information.R; - -public class AboutActivity extends Activity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.weather_about); - } - - @Override - public void onResume() { - super.onResume(); - - final ActionBar actionBar = this.getActionBar(); - actionBar.setTitle(this.getString(R.string.weather_about_action)); - } - - public void onClickLegalInformation(final View view) { - final Intent intent = new Intent("com.weather.information.WEATHERINFO") - .setComponent(new ComponentName("com.weather.information", - "com.weather.information.activity.LicensesActivity")); - this.startActivity(intent); - } - - public void onClickSourceCode(final View view) { - final String url = this.getString(R.string.application_source_code_url); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - } - - public void onClickRemoteData(final View view) { - final String url = this.getString(R.string.openweahtermap_url); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - } - - public void onClickMyWeb(final View view) { - final String url = this.getString(R.string.my_url); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - } -} diff --git a/app/src/main/java/com/weather/information/activity/LicensesActivity.java b/app/src/main/java/com/weather/information/activity/LicensesActivity.java deleted file mode 100644 index 13ecb68..0000000 --- a/app/src/main/java/com/weather/information/activity/LicensesActivity.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.weather.information.activity; - -import android.app.ActionBar; -import android.app.Activity; -import android.os.Bundle; -import android.util.Log; -import android.webkit.WebView; - -import com.google.android.gms.common.GooglePlayServicesUtil; -import com.weather.information.R; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; - -public class LicensesActivity extends Activity { - private static final String TAG = "LicensesActivity"; - private WebView mWebView; - - - @Override - public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.weather_licenses); - - mWebView = (WebView) this.findViewById(R.id.weather_licenses); - } - - @Override - public void onResume() { - super.onResume(); - - final ActionBar actionBar = this.getActionBar(); - actionBar.setTitle(this.getString(R.string.weather_licenses_title)); - - final String googlePlayServices = GooglePlayServicesUtil.getOpenSourceSoftwareLicenseInfo(this.getApplicationContext()); - try { - final StringBuilder stringBuilder = this.loadData(); - stringBuilder.append(googlePlayServices).append("").append("").append(""); - mWebView.loadDataWithBaseURL(null, stringBuilder.toString(), "text/html", "UTF-8", null); - } catch (final UnsupportedEncodingException e) { - Log.e(TAG, "Load data error", e); - } catch (final IOException e) { - Log.e(TAG, "Load data error", e); - } - } - - private StringBuilder loadData() throws UnsupportedEncodingException, IOException { - final InputStream inputStream = this.getResources().openRawResource(R.raw.licenses); - try { - final InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8")); - try { - final BufferedReader reader = new BufferedReader(inputStreamReader); - try { - final StringBuilder stringBuilder = new StringBuilder(); - String line; - while ((line = reader.readLine()) != null) { - stringBuilder.append(line); - stringBuilder.append("\n"); - } - return stringBuilder; - } finally { - reader.close(); - } - } finally { - inputStreamReader.close(); - } - } finally { - inputStream.close(); - } - } -} diff --git a/app/src/main/java/com/weather/information/activity/MapActivity.java b/app/src/main/java/com/weather/information/activity/MapActivity.java deleted file mode 100644 index cee2de3..0000000 --- a/app/src/main/java/com/weather/information/activity/MapActivity.java +++ /dev/null @@ -1,399 +0,0 @@ -package com.weather.information.activity; - -import android.app.ActionBar; -import android.content.Context; -import android.location.Criteria; -import android.location.Geocoder; -import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; -import android.os.Build; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentTransaction; -import android.view.View; -import android.widget.Button; -import android.widget.TextView; -import android.widget.Toast; - -import com.google.android.gms.maps.CameraUpdateFactory; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener; -import com.google.android.gms.maps.MapFragment; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.Marker; -import com.google.android.gms.maps.model.MarkerOptions; -import com.weather.information.R; -import com.weather.information.fragment.map.MapButtonsFragment; -import com.weather.information.fragment.map.MapProgressFragment; -import com.weather.information.model.DatabaseQueries; -import com.weather.information.model.WeatherLocation; - - -public class MapActivity extends FragmentActivity implements - LocationListener, - MapProgressFragment.TaskCallbacks { - private static final String PROGRESS_FRAGMENT_TAG = "PROGRESS_FRAGMENT"; - private static final String BUTTONS_FRAGMENT_TAG = "BUTTONS_FRAGMENT"; - private WeatherLocation mRestoreUI; - - // Google Play Services Map - private GoogleMap mMap; - // TODO: read and store from different threads? Hopefully always from UI thread. - private Marker mMarker; - - private LocationManager mLocationManager; - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - this.setContentView(R.layout.weather_map); - - // Acquire a reference to the system Location Manager - this.mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); - - // Google Play Services Map - final MapFragment mapFragment = (MapFragment) this.getFragmentManager() - .findFragmentById(R.id.weather_map_fragment_map); - this.mMap = mapFragment.getMap(); - this.mMap.setMyLocationEnabled(false); - this.mMap.getUiSettings().setMyLocationButtonEnabled(false); - this.mMap.getUiSettings().setZoomControlsEnabled(true); - this.mMap.getUiSettings().setCompassEnabled(true); - this.mMap.setOnMapLongClickListener(new MapActivityOnMapLongClickListener(this)); - } - - @Override - protected void onRestoreInstanceState(final Bundle savedInstanceState) { - // Instead of restoring the state during onCreate() you may choose to - // implement onRestoreInstanceState(), which the system calls after the - // onStart() method. The system calls onRestoreInstanceState() only if - // there is a saved state to restore, so you do not need to check whether - // the Bundle is null: - super.onRestoreInstanceState(savedInstanceState); - - // Restore UI state - this.mRestoreUI = (WeatherLocation) savedInstanceState.getSerializable("WeatherLocation"); - } - - @Override - public void onResume() { - super.onResume(); - - final ActionBar actionBar = this.getActionBar(); - actionBar.setTitle(this.getString(R.string.weather_map_mark_location)); - - WeatherLocation weatherLocation; - if (this.mRestoreUI != null) { - // Restore UI state - weatherLocation = this.mRestoreUI; - // just once - this.mRestoreUI = null; - } else if (this.mMarker != null ) { - 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 LatLng point = this.mMarker.getPosition(); - double latitude = point.latitude; - double longitude = point.longitude; - - weatherLocation = new WeatherLocation() - .setCity(cityString) - .setCountry(countryString) - .setLatitude(latitude) - .setLongitude(longitude); - } else { - final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext()); - weatherLocation = query.queryDataBase(); - } - - if (weatherLocation != null) { - this.updateUI(weatherLocation); - } - } - - /** - * I am not using fragment transactions in the right way. But I do not know other way for doing what I am doing. - * - * {@link http://stackoverflow.com/questions/16265733/failure-delivering-result-onactivityforresult} - */ - @Override - public void onPostResume() { - super.onPostResume(); - - final FragmentManager fm = getSupportFragmentManager(); - final Fragment progressFragment = fm.findFragmentByTag(PROGRESS_FRAGMENT_TAG); - if (progressFragment == null) { - this.addButtonsFragment(); - } else { - this.removeProgressFragment(); - final Bundle bundle = progressFragment.getArguments(); - double latitude = bundle.getDouble("latitude"); - double longitude = bundle.getDouble("longitude"); - this.addProgressFragment(latitude, longitude); - } - } - - @Override - public void onSaveInstanceState(final Bundle savedInstanceState) { - // Save UI state - // Save Google Maps Marker - if (this.mMarker != null) { - 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 LatLng point = this.mMarker.getPosition(); - double latitude = point.latitude; - double longitude = point.longitude; - - final WeatherLocation location = new WeatherLocation() - .setCity(cityString) - .setCountry(countryString) - .setLatitude(latitude) - .setLongitude(longitude); - savedInstanceState.putSerializable("WeatherLocation", location); - } - - super.onSaveInstanceState(savedInstanceState); - } - - @Override - public void onPause() { - super.onPause(); - - this.mLocationManager.removeUpdates(this); - } - - public void onClickSaveLocation(final View v) { - if (this.mMarker != null) { - final LatLng position = this.mMarker.getPosition(); - - 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 DatabaseQueries query = new DatabaseQueries(this.getApplicationContext()); - final WeatherLocation weatherLocation = query.queryDataBase(); - if (weatherLocation != null) { - weatherLocation - .setCity(cityString) - .setCountry(countryString) - .setLatitude(position.latitude) - .setLongitude(position.longitude) - .setLastCurrentUIUpdate(null) - .setLastForecastUIUpdate(null) - .setIsNew(true); - query.updateDataBase(weatherLocation); - } else { - final WeatherLocation location = new WeatherLocation() - .setCity(cityString) - .setCountry(countryString) - .setIsSelected(true) - .setLatitude(position.latitude) - .setLongitude(position.longitude) - .setIsNew(true); - query.insertIntoDataBase(location); - } - } - } - - public void onClickGetLocation(final View v) { - // TODO: Somehow I should show a progress dialog. - // If Google Play Services is available - if (this.mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { - // TODO: Hopefully there will be results even if location did not change... - final Criteria criteria = new Criteria(); - criteria.setAccuracy(Criteria.ACCURACY_FINE); - criteria.setAltitudeRequired(false); - criteria.setBearingAccuracy(Criteria.NO_REQUIREMENT); - criteria.setBearingRequired(false); - criteria.setCostAllowed(false); - criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); - criteria.setPowerRequirement(Criteria.POWER_MEDIUM); - criteria.setSpeedAccuracy(Criteria.NO_REQUIREMENT); - criteria.setSpeedRequired(false); - criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH); - - this.mLocationManager.requestSingleUpdate(criteria, this, null); - } else { - Toast.makeText(this, this.getString(R.string.weather_map_not_enabled_location), Toast.LENGTH_LONG).show(); - } - // Trying to use the synchronous calls. Problems: mGoogleApiClient read/store from different threads. - // new GetLocationTask(this).execute(); - } - - private void updateUI(final WeatherLocation weatherLocation) { - - final TextView city = (TextView) this.findViewById(R.id.weather_map_city); - final TextView country = (TextView) this.findViewById(R.id.weather_map_country); - city.setText(weatherLocation.getCity()); - country.setText(weatherLocation.getCountry()); - - final LatLng point = new LatLng(weatherLocation.getLatitude(), weatherLocation.getLongitude()); - if (this.mMarker != null) { - // Just one marker on map - this.mMarker.remove(); - } - this.mMarker = this.mMap.addMarker(new MarkerOptions().position(point).draggable(true)); - this.mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(point, 5)); - this.mMap.animateCamera(CameraUpdateFactory.zoomIn()); - this.mMap.animateCamera(CameraUpdateFactory.zoomTo(8), 2000, null); - } - - private class MapActivityOnMapLongClickListener implements OnMapLongClickListener { - // Store the context passed to the AsyncTask when the system instantiates it. - private final Context localContext; - - private MapActivityOnMapLongClickListener(final Context context) { - this.localContext = context; - } - - @Override - public void onMapLongClick(final LatLng point) { - final MapActivity activity = (MapActivity) this.localContext; - activity.getAddressAndUpdateUI(point.latitude, point.longitude); - } - - } - - /** - * Getting the address of the current location, using reverse geocoding only works if - * a geocoding service is available. - * - */ - private void getAddressAndUpdateUI(final double latitude, final double longitude) { - // In Gingerbread and later, use Geocoder.isPresent() to see if a geocoder is available. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && Geocoder.isPresent()) { - this.removeButtonsFragment(); - this.removeProgressFragment(); - this.addProgressFragment(latitude, longitude); - } else { - this.removeProgressFragment(); - this.addButtonsFragment(); - // No geocoder is present. Issue an error message. - Toast.makeText(this, this.getString(R.string.weather_map_no_geocoder_available), Toast.LENGTH_LONG).show(); - - // 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() - .setLatitude(latitude) - .setLongitude(longitude) - .setCity(city) - .setCountry(country); - - updateUI(weatherLocation); - } - } - - /***************************************************************************************************** - * - * MapProgressFragment.TaskCallbacks - * - *****************************************************************************************************/ - @Override - public void onPostExecute(WeatherLocation weatherLocation) { - - this.updateUI(weatherLocation); - this.removeProgressFragment(); - - this.addButtonsFragment(); - } - - /***************************************************************************************************** - * - * MapProgressFragment - * I am not using fragment transactions in the right way. But I do not know other way for doing what I am doing. - * Android sucks. - * - * "Avoid performing transactions inside asynchronous callback methods." :( - * see: http://stackoverflow.com/questions/16265733/failure-delivering-result-onactivityforresult - * see: http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html - * How do you do what I am doing in a different way without using fragments? - *****************************************************************************************************/ - - private void addProgressFragment(final double latitude, final double longitude) { - final Fragment progressFragment = new MapProgressFragment(); - progressFragment.setRetainInstance(true); - final Bundle args = new Bundle(); - args.putDouble("latitude", latitude); - args.putDouble("longitude", longitude); - progressFragment.setArguments(args); - - final FragmentManager fm = this.getSupportFragmentManager(); - final FragmentTransaction fragmentTransaction = fm.beginTransaction(); - fragmentTransaction.setCustomAnimations(R.anim.weather_map_enter_progress, R.anim.weather_map_exit_progress); - fragmentTransaction.add(R.id.weather_map_buttons_container, progressFragment, PROGRESS_FRAGMENT_TAG).commit(); - fm.executePendingTransactions(); - } - - private void removeProgressFragment() { - final FragmentManager fm = this.getSupportFragmentManager(); - final Fragment progressFragment = fm.findFragmentByTag(PROGRESS_FRAGMENT_TAG); - if (progressFragment != null) { - final FragmentTransaction fragmentTransaction = fm.beginTransaction(); - fragmentTransaction.remove(progressFragment).commit(); - fm.executePendingTransactions(); - } - } - - private void addButtonsFragment() { - final FragmentManager fm = this.getSupportFragmentManager(); - Fragment buttonsFragment = fm.findFragmentByTag(BUTTONS_FRAGMENT_TAG); - if (buttonsFragment == null) { - buttonsFragment = new MapButtonsFragment(); - buttonsFragment.setRetainInstance(true); - final FragmentTransaction fragmentTransaction = fm.beginTransaction(); - fragmentTransaction.setCustomAnimations(R.anim.weather_map_enter_progress, R.anim.weather_map_exit_progress); - fragmentTransaction.add(R.id.weather_map_buttons_container, buttonsFragment, BUTTONS_FRAGMENT_TAG).commit(); - fm.executePendingTransactions(); - } - - if (this.mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { - final Button getLocationButton = (Button) this.findViewById(R.id.weather_map_button_getlocation); - getLocationButton.setEnabled(true); - } - } - - private void removeButtonsFragment() { - final FragmentManager fm = this.getSupportFragmentManager(); - final Fragment buttonsFragment = fm.findFragmentByTag(BUTTONS_FRAGMENT_TAG); - if (buttonsFragment != null) { - final FragmentTransaction fragmentTransaction = fm.beginTransaction(); - fragmentTransaction.remove(buttonsFragment).commit(); - fm.executePendingTransactions(); - } - } - - /***************************************************************************************************** - * - * android.location.LocationListener - * - *****************************************************************************************************/ - - @Override - public void onLocationChanged(final Location location) { - // It was called from onClickGetLocation (UI thread) This method will run in the same thread (the UI thread) - // so, I do no think there should be any problem. - - // Display the current location in the UI - // TODO: May location not be null? - this.getAddressAndUpdateUI(location.getLatitude(), location.getLongitude()); - } - - @Override - public void onStatusChanged(String provider, int status, Bundle extras) {} - - @Override - public void onProviderEnabled(String provider) {} - - @Override - public void onProviderDisabled(String provider) {} -} diff --git a/app/src/main/java/com/weather/information/activity/SpecificActivity.java b/app/src/main/java/com/weather/information/activity/SpecificActivity.java deleted file mode 100644 index 00ae603..0000000 --- a/app/src/main/java/com/weather/information/activity/SpecificActivity.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.weather.information.activity; - -import android.app.ActionBar; -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; - -import com.weather.information.R; -import com.weather.information.model.DatabaseQueries; -import com.weather.information.model.WeatherLocation; - -import java.text.MessageFormat; -import java.util.Locale; - -public class SpecificActivity extends FragmentActivity { - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - this.setContentView(R.layout.weather_specific); - - final ActionBar actionBar = this.getActionBar(); - - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE); - actionBar.setDisplayHomeAsUpEnabled(true); - - } - - @Override - public void onResume() { - super.onResume(); - - // 1. Update title. - final DatabaseQueries query = new DatabaseQueries(this); - final WeatherLocation weatherLocation = query.queryDataBase(); - if (weatherLocation != null) { - final ActionBar actionBar = this.getActionBar(); - final String[] array = new String[2]; - array[0] = weatherLocation.getCity(); - array[1] = weatherLocation.getCountry(); - final MessageFormat message = new MessageFormat("{0},{1}", Locale.US); - final String cityCountry = message.format(array); - actionBar.setTitle(cityCountry); - } - } -} diff --git a/app/src/main/java/com/weather/information/activity/WeatherInformationPreferencesActivity.java b/app/src/main/java/com/weather/information/activity/WeatherInformationPreferencesActivity.java deleted file mode 100644 index 015142f..0000000 --- a/app/src/main/java/com/weather/information/activity/WeatherInformationPreferencesActivity.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.weather.information.activity; - -import android.app.ActionBar; -import android.app.Activity; -import android.os.Bundle; - -import com.weather.information.R; -import com.weather.information.fragment.preferences.WeatherInformationPreferencesFragment; - -public class WeatherInformationPreferencesActivity extends Activity { - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - this.getFragmentManager() - .beginTransaction() - .replace(android.R.id.content, - new WeatherInformationPreferencesFragment()).commit(); - } - - @Override - public void onResume() { - super.onResume(); - - final ActionBar actionBar = this.getActionBar(); - actionBar.setTitle(this.getString(R.string.weather_preferences_action_settings)); - } -} diff --git a/app/src/main/java/com/weather/information/activity/WeatherTabsActivity.java b/app/src/main/java/com/weather/information/activity/WeatherTabsActivity.java deleted file mode 100644 index d6edf7d..0000000 --- a/app/src/main/java/com/weather/information/activity/WeatherTabsActivity.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.weather.information.activity; - -import android.app.ActionBar; -import android.app.ActionBar.Tab; -import android.app.FragmentTransaction; -import android.content.ComponentName; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentPagerAdapter; -import android.support.v4.view.ViewPager; -import android.view.Menu; -import android.view.MenuItem; - -import com.weather.information.R; -import com.weather.information.fragment.current.CurrentFragment; -import com.weather.information.fragment.overview.OverviewFragment; -import com.weather.information.model.DatabaseQueries; -import com.weather.information.model.WeatherLocation; - -import java.text.MessageFormat; -import java.util.Locale; - - -public class WeatherTabsActivity extends FragmentActivity { - private static final int NUM_ITEMS = 2; - private ViewPager mPager; - - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - this.setContentView(R.layout.fragment_pager); - - this.mPager = (ViewPager)this.findViewById(R.id.pager); - this.mPager.setAdapter(new TabsAdapter(this.getSupportFragmentManager())); - - - this.mPager.setOnPageChangeListener( - new ViewPager.SimpleOnPageChangeListener() { - @Override - public void onPageSelected(final int position) { - WeatherTabsActivity.this.getActionBar().setSelectedNavigationItem(position); - } - }); - - - final ActionBar actionBar = this.getActionBar(); - - PreferenceManager.setDefaultValues(this, R.xml.weather_preferences, false); - - // Specify that tabs should be displayed in the action bar. - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); - actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE); - actionBar.setDisplayHomeAsUpEnabled(true); - - // Create a tab listener that is called when the user changes tabs. - final ActionBar.TabListener tabListener = new ActionBar.TabListener() { - - @Override - public void onTabSelected(final Tab tab, final FragmentTransaction ft) { - WeatherTabsActivity.this.mPager.setCurrentItem(tab.getPosition()); - - } - - @Override - public void onTabUnselected(final Tab tab, final FragmentTransaction ft) { - - } - - @Override - public void onTabReselected(final Tab tab, final FragmentTransaction ft) { - - } - - }; - - actionBar.addTab(actionBar.newTab().setText("CURRENTLY").setTabListener(tabListener)); - actionBar.addTab(actionBar.newTab().setText("FORECAST").setTabListener(tabListener)); - } - - @Override - public boolean onCreateOptionsMenu(final Menu menu) { - - this.getMenuInflater().inflate(R.menu.weather_main_menu, menu); - - return super.onCreateOptionsMenu(menu); - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - // Handle action bar item clicks here. The action bar will - // automatically handle clicks on the Home/Up button, so long - // as you specify a parent activity in AndroidManifest.xml. - super.onOptionsItemSelected(item); - - Intent intent; - final int itemId = item.getItemId(); - if (itemId == R.id.weather_menu_settings) { - intent = new Intent("com.weather.information.WEATHERINFO") - .setComponent(new ComponentName("com.weather.information", - "com.weather.information.activity.WeatherInformationPreferencesActivity")); - this.startActivity(intent); - return true; - } else if (itemId == R.id.weather_menu_map) { - intent = new Intent("com.weather.information.WEATHERINFO"). - setComponent(new ComponentName("com.weather.information", - "com.weather.information.activity.MapActivity")); - this.startActivity(intent); - return true; - } else if (itemId == R.id.weather_menu_about) { - intent = new Intent("com.weather.information.WEATHERINFO"). - setComponent(new ComponentName("com.weather.information", - "com.weather.information.activity.AboutActivity")); - this.startActivity(intent); - return true; - } else { - } - - // TODO: calling again super method? - return super.onOptionsItemSelected(item); - } - - @Override - protected void onRestoreInstanceState(final Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - } - - - @Override - public void onResume() { - super.onResume(); - - final ActionBar actionBar = this.getActionBar(); - - // 1. Update title. - final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext()); - final WeatherLocation weatherLocation = query.queryDataBase(); - if (weatherLocation != null) { - final String[] array = new String[2]; - array[0] = weatherLocation.getCity(); - array[1] = weatherLocation.getCountry(); - final MessageFormat message = new MessageFormat("{0},{1}", Locale.US); - final String cityCountry = message.format(array); - actionBar.setTitle(cityCountry); - } else { - actionBar.setTitle(this.getString(R.string.text_field_no_chosen_location)); - } - - // 2. Update forecast tab text. - final SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(this); - final String keyPreference = this.getString(R.string.weather_preferences_day_forecast_key); - final String value = sharedPreferences.getString(keyPreference, ""); - String humanValue = ""; - if (value.equals("5")) { - humanValue = "5 DAY FORECAST"; - } else if (value.equals("10")) { - humanValue = "10 DAY FORECAST"; - } else if (value.equals("14")) { - humanValue = "14 DAY FORECAST"; - } - actionBar.getTabAt(1).setText(humanValue); - } - - @Override - public void onSaveInstanceState(final Bundle savedInstanceState) { - super.onSaveInstanceState(savedInstanceState); - } - - private class TabsAdapter extends FragmentPagerAdapter { - public TabsAdapter(final FragmentManager fm) { - super(fm); - } - - @Override - public int getCount() { - return NUM_ITEMS; - } - - @Override - public Fragment getItem(final int position) { - if (position == 0) { - return new CurrentFragment(); - } else { - return new OverviewFragment(); - } - - } - } -} diff --git a/app/src/main/java/com/weather/information/boot/WeatherInformationBootReceiver.java b/app/src/main/java/com/weather/information/boot/WeatherInformationBootReceiver.java deleted file mode 100644 index c695805..0000000 --- a/app/src/main/java/com/weather/information/boot/WeatherInformationBootReceiver.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.weather.information.boot; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.SystemClock; -import android.preference.PreferenceManager; - -import com.weather.information.R; -import com.weather.information.notification.NotificationIntentService; - -public class WeatherInformationBootReceiver extends BroadcastReceiver { - - @Override - public void onReceive(final Context context, final Intent intent) { - - if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { - - // Update Time Rate - final SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(context); - final String keyPreference = context - .getString(R.string.weather_preferences_update_time_rate_key); - final String updateTimeRate = sharedPreferences.getString(keyPreference, ""); - long chosenInterval = 0; - if (updateTimeRate.equals("900")) { - chosenInterval = AlarmManager.INTERVAL_FIFTEEN_MINUTES; - } else if (updateTimeRate.equals("1800")) { - chosenInterval = AlarmManager.INTERVAL_HALF_HOUR; - } else if (updateTimeRate.equals("3600")) { - chosenInterval = AlarmManager.INTERVAL_HOUR; - } else if (updateTimeRate.equals("43200")) { - chosenInterval = AlarmManager.INTERVAL_HALF_DAY; - } else if (updateTimeRate.equals("86400")) { - chosenInterval = AlarmManager.INTERVAL_DAY; - } - - if (chosenInterval != 0) { - final AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - // TODO: better use some string instead of .class? In case I change the service class - // this could be a problem (I guess) - final Intent serviceIntent = new Intent(context, NotificationIntentService.class); - final PendingIntent alarmIntent = PendingIntent.getService( - context, - 0, - serviceIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - alarmMgr.setInexactRepeating( - AlarmManager.ELAPSED_REALTIME, - SystemClock.elapsedRealtime() + chosenInterval, - chosenInterval, - alarmIntent); - } - } - } - -} diff --git a/app/src/main/java/com/weather/information/fragment/ErrorDialogFragment.java b/app/src/main/java/com/weather/information/fragment/ErrorDialogFragment.java deleted file mode 100644 index a6b40b2..0000000 --- a/app/src/main/java/com/weather/information/fragment/ErrorDialogFragment.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.weather.information.fragment; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.DialogInterface; -import android.os.Bundle; -import android.support.v4.app.DialogFragment; - -public class ErrorDialogFragment extends DialogFragment { - - public static ErrorDialogFragment newInstance(final int title) { - final ErrorDialogFragment frag = new ErrorDialogFragment(); - final Bundle args = new Bundle(); - - args.putInt("title", title); - frag.setArguments(args); - - return frag; - } - - @Override - public Dialog onCreateDialog(final Bundle savedInstanceState) { - final int title = this.getArguments().getInt("title"); - - return new AlertDialog.Builder(this.getActivity()) - .setIcon(android.R.drawable.ic_dialog_alert) - .setTitle(title) - .setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - @Override - public void onClick(final DialogInterface dialog, - final int whichButton) { - - } - }).create(); - } - - @Override - public void onDestroyView() { - if (getDialog() != null && getRetainInstance()) { - getDialog().setDismissMessage(null); - } - super.onDestroyView(); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/weather/information/fragment/current/CurrentFragment.java b/app/src/main/java/com/weather/information/fragment/current/CurrentFragment.java deleted file mode 100644 index 53a64ab..0000000 --- a/app/src/main/java/com/weather/information/fragment/current/CurrentFragment.java +++ /dev/null @@ -1,523 +0,0 @@ -package com.weather.information.fragment.current; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - -import org.apache.http.client.ClientProtocolException; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.http.AndroidHttpClient; -import android.os.AsyncTask; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.v4.app.Fragment; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.ProgressBar; -import android.widget.TextView; - -import com.fasterxml.jackson.core.JsonParseException; -import com.weather.information.R; -import com.weather.information.httpclient.CustomHTTPClient; -import com.weather.information.model.DatabaseQueries; -import com.weather.information.model.WeatherLocation; -import com.weather.information.model.currentweather.Current; -import com.weather.information.parser.JPOSWeatherParser; -import com.weather.information.service.IconsList; -import com.weather.information.service.PermanentStorage; -import com.weather.information.service.ServiceParser; -import com.weather.information.widget.WidgetProvider; - -public class CurrentFragment extends Fragment { - private static final String TAG = "CurrentFragment"; - private BroadcastReceiver mReceiver; - - @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_current_fragment, container, false); - } - - @Override - public void onActivityCreated(final Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - if (savedInstanceState != null) { - // Restore UI state - final Current current = (Current) savedInstanceState.getSerializable("Current"); - - if (current != null) { - final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); - store.saveCurrent(current); - } - } - - this.setHasOptionsMenu(false); - - this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE); - this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.VISIBLE); - this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE); - } - - @Override - public void onResume() { - super.onResume(); - - - this.mReceiver = new BroadcastReceiver() { - - @Override - public void onReceive(final Context context, final Intent intent) { - final String action = intent.getAction(); - if (action.equals("com.weather.information.UPDATECURRENT")) { - final Current currentRemote = (Current) intent.getSerializableExtra("current"); - - if (currentRemote != null) { - - // 1. Check conditions. They must be the same as the ones that triggered the AsyncTask. - final DatabaseQueries query = new DatabaseQueries(context.getApplicationContext()); - final WeatherLocation weatherLocation = query.queryDataBase(); - final PermanentStorage store = new PermanentStorage(context.getApplicationContext()); - final Current current = store.getCurrent(); - - if (current == null || !CurrentFragment.this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) { - // 2. Update UI. - CurrentFragment.this.updateUI(currentRemote); - - // 3. Update current data. - store.saveCurrent(currentRemote); - - // 4. Update location data. - weatherLocation.setLastCurrentUIUpdate(new Date()); - query.updateDataBase(weatherLocation); - } - - } else { - // Empty UI and show error message - CurrentFragment.this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE); - CurrentFragment.this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.GONE); - CurrentFragment.this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.VISIBLE); - } - } - } - }; - - // Register receiver - final IntentFilter filter = new IntentFilter(); - filter.addAction("com.weather.information.UPDATECURRENT"); - LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()) - .registerReceiver(this.mReceiver, filter); - - // Empty UI - this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE); - - final DatabaseQueries query = new DatabaseQueries(this.getActivity().getApplicationContext()); - final WeatherLocation weatherLocation = query.queryDataBase(); - if (weatherLocation == null) { - // Nothing to do. - // Show error message - final ProgressBar progress = (ProgressBar) getActivity().findViewById(R.id.weather_current_progressbar); - progress.setVisibility(View.GONE); - final TextView errorMessage = (TextView) getActivity().findViewById(R.id.weather_current_error_message); - errorMessage.setVisibility(View.VISIBLE); - return; - } - - // If is new location update widgets. - if (weatherLocation.getIsNew()) { - WidgetProvider.refreshAllAppWidgets(this.getActivity().getApplicationContext()); - // Update location data. - weatherLocation.setIsNew(false); - query.updateDataBase(weatherLocation); - } - - - final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); - final Current current = store.getCurrent(); - - if (current != null && this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) { - this.updateUI(current); - } else { - // Load remote data (aynchronous) - // Gets the data from the web. - this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.VISIBLE); - this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE); - final CurrentTask task = new CurrentTask( - this.getActivity().getApplicationContext(), - new CustomHTTPClient(AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")), - new ServiceParser(new JPOSWeatherParser())); - - task.execute(weatherLocation.getLatitude(), weatherLocation.getLongitude()); - } - } - - @Override - public void onSaveInstanceState(final Bundle savedInstanceState) { - - // Save UI state - final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); - final Current current = store.getCurrent(); - - if (current != null) { - savedInstanceState.putSerializable("Current", current); - } - - super.onSaveInstanceState(savedInstanceState); - } - - @Override - public void onPause() { - LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()).unregisterReceiver(this.mReceiver); - - super.onPause(); - } - - private interface UnitsConversor { - - public double doConversion(final double value); - } - - private void updateUI(final Current current) { - - final SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(this.getActivity().getApplicationContext()); - - // TODO: repeating the same code in Overview, Specific and Current!!! - // 1. Update units of measurement. - // 1.1 Temperature - String tempSymbol; - UnitsConversor tempUnitsConversor; - String keyPreference = this.getResources().getString(R.string.weather_preferences_temperature_key); - String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); - String unitsPreferenceValue = sharedPreferences.getString( - keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); - if (unitsPreferenceValue.equals(values[0])) { - tempSymbol = values[0]; - tempUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return value - 273.15; - } - - }; - } else if (unitsPreferenceValue.equals(values[1])) { - tempSymbol = values[1]; - tempUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return (value * 1.8) - 459.67; - } - - }; - } else { - tempSymbol = values[2]; - tempUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return value; - } - - }; - } - - // 1.2 Wind - String windSymbol; - UnitsConversor windUnitsConversor; - keyPreference = this.getResources().getString(R.string.weather_preferences_wind_key); - values = this.getResources().getStringArray(R.array.weather_preferences_wind); - unitsPreferenceValue = sharedPreferences.getString( - keyPreference, this.getString(R.string.weather_preferences_wind_meters)); - if (unitsPreferenceValue.equals(values[0])) { - windSymbol = values[0]; - windUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(double value) { - return value; - } - }; - } else { - windSymbol = values[1]; - windUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(double value) { - return value * 2.237; - } - }; - } - - // 1.3 Pressure - String pressureSymbol; - UnitsConversor pressureUnitsConversor; - keyPreference = this.getResources().getString(R.string.weather_preferences_pressure_key); - values = this.getResources().getStringArray(R.array.weather_preferences_pressure); - unitsPreferenceValue = sharedPreferences.getString( - keyPreference, this.getString(R.string.weather_preferences_pressure_pascal)); - if (unitsPreferenceValue.equals(values[0])) { - pressureSymbol = values[0]; - pressureUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(double value) { - return value; - } - }; - } else { - pressureSymbol = values[1]; - pressureUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(double value) { - return value / 113.25d; - } - }; - } - - - // 2. Formatters - final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); - tempFormatter.applyPattern("#####.#####"); - final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.US); - - - // 3. Prepare data for UI. - String tempMax = ""; - if (current.getMain().getTemp_max() != null) { - double conversion = (Double) current.getMain().getTemp_max(); - conversion = tempUnitsConversor.doConversion(conversion); - tempMax = tempFormatter.format(conversion) + tempSymbol; - } - String tempMin = ""; - if (current.getMain().getTemp_min() != null) { - double conversion = (Double) current.getMain().getTemp_min(); - conversion = tempUnitsConversor.doConversion(conversion); - tempMin = tempFormatter.format(conversion) + tempSymbol; - } - Bitmap picture; - if ((current.getWeather().size() > 0) - && (current.getWeather().get(0).getIcon() != null) - && (IconsList.getIcon(current.getWeather().get(0).getIcon()) != null)) { - final String icon = current.getWeather().get(0).getIcon(); - picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon) - .getResourceDrawable()); - } else { - picture = BitmapFactory.decodeResource(this.getResources(), - R.drawable.weather_severe_alert); - } - - String description = this.getString(R.string.text_field_description_when_error); - if (current.getWeather().size() > 0) { - description = current.getWeather().get(0).getDescription(); - } - - String humidityValue = ""; - if ((current.getMain() != null) - && (current.getMain().getHumidity() != null)) { - final double conversion = (Double) current.getMain().getHumidity(); - humidityValue = tempFormatter.format(conversion); - } - String pressureValue = ""; - if ((current.getMain() != null) - && (current.getMain().getPressure() != null)) { - double conversion = (Double) current.getMain().getPressure(); - conversion = pressureUnitsConversor.doConversion(conversion); - pressureValue = tempFormatter.format(conversion); - } - String windValue = ""; - if ((current.getWind() != null) - && (current.getWind().getSpeed() != null)) { - double conversion = (Double) current.getWind().getSpeed(); - conversion = windUnitsConversor.doConversion(conversion); - windValue = tempFormatter.format(conversion); - } - String rainValue = ""; - if ((current.getRain() != null) - && (current.getRain().get3h() != null)) { - final double conversion = (Double) current.getRain().get3h(); - rainValue = tempFormatter.format(conversion); - } - String cloudsValue = ""; - if ((current.getClouds() != null) - && (current.getClouds().getAll() != null)) { - final double conversion = (Double) current.getClouds().getAll(); - cloudsValue = tempFormatter.format(conversion); - } - String snowValue = ""; - if ((current.getSnow() != null) - && (current.getSnow().get3h() != null)) { - final double conversion = (Double) current.getSnow().get3h(); - snowValue = tempFormatter.format(conversion); - } - String feelsLike = ""; - if (current.getMain().getTemp() != null) { - double conversion = (Double) current.getMain().getTemp(); - conversion = tempUnitsConversor.doConversion(conversion); - feelsLike = tempFormatter.format(conversion); - } - String sunRiseTime = ""; - if (current.getSys().getSunrise() != null) { - final long unixTime = (Long) current.getSys().getSunrise(); - final Date unixDate = new Date(unixTime * 1000L); - sunRiseTime = dateFormat.format(unixDate); - } - String sunSetTime = ""; - if (current.getSys().getSunset() != null) { - final long unixTime = (Long) current.getSys().getSunset(); - final Date unixDate = new Date(unixTime * 1000L); - sunSetTime = dateFormat.format(unixDate); - } - - - // 4. Update UI. - final TextView tempMaxView = (TextView) getActivity().findViewById(R.id.weather_current_temp_max); - tempMaxView.setText(tempMax); - final TextView tempMinView = (TextView) getActivity().findViewById(R.id.weather_current_temp_min); - tempMinView.setText(tempMin); - final ImageView pictureView = (ImageView) getActivity().findViewById(R.id.weather_current_picture); - pictureView.setImageBitmap(picture); - - final TextView descriptionView = (TextView) getActivity().findViewById(R.id.weather_current_description); - descriptionView.setText(description); - - ((TextView) getActivity().findViewById(R.id.weather_current_humidity_value)).setText(humidityValue); - ((TextView) getActivity().findViewById(R.id.weather_current_humidity_units)).setText( - this.getActivity().getApplicationContext().getString(R.string.text_units_percent)); - - ((TextView) getActivity().findViewById(R.id.weather_current_pressure_value)).setText(pressureValue); - ((TextView) getActivity().findViewById(R.id.weather_current_pressure_units)).setText(pressureSymbol); - - ((TextView) getActivity().findViewById(R.id.weather_current_wind_value)).setText(windValue); - ((TextView) getActivity().findViewById(R.id.weather_current_wind_units)).setText(windSymbol); - - ((TextView) getActivity().findViewById(R.id.weather_current_rain_value)).setText(rainValue); - ((TextView) getActivity().findViewById(R.id.weather_current_rain_units)).setText( - this.getActivity().getApplicationContext().getString(R.string.text_units_mm3h)); - - ((TextView) getActivity().findViewById(R.id.weather_current_clouds_value)).setText(cloudsValue); - ((TextView) getActivity().findViewById(R.id.weather_current_clouds_units)).setText( - this.getActivity().getApplicationContext().getString(R.string.text_units_percent)); - - ((TextView) getActivity().findViewById(R.id.weather_current_snow_value)).setText(snowValue); - ((TextView) getActivity().findViewById(R.id.weather_current_snow_units)).setText( - this.getActivity().getApplicationContext().getString(R.string.text_units_mm3h)); - - ((TextView) getActivity().findViewById(R.id.weather_current_feelslike_value)).setText(feelsLike); - ((TextView) getActivity().findViewById(R.id.weather_current_feelslike_units)).setText(tempSymbol); - - ((TextView) getActivity().findViewById(R.id.weather_current_sunrise_value)).setText(sunRiseTime); - - ((TextView) getActivity().findViewById(R.id.weather_current_sunset_value)).setText(sunSetTime); - - this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.VISIBLE); - this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.GONE); - this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE); - } - - private boolean isDataFresh(final Date lastUpdate) { - if (lastUpdate == null) { - return false; - } - - final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences( - this.getActivity().getApplicationContext()); - final String keyPreference = this.getString(R.string.weather_preferences_refresh_interval_key); - final String refresh = sharedPreferences.getString( - keyPreference, - this.getResources().getStringArray(R.array.weather_preferences_refresh_interval)[0]); - final Date currentTime = new Date(); - if (((currentTime.getTime() - lastUpdate.getTime())) < Long.valueOf(refresh)) { - return true; - } - - return false; - } - - private class CurrentTask extends AsyncTask { - // Store the context passed to the AsyncTask when the system instantiates it. - private final Context localContext; - final CustomHTTPClient HTTPClient; - final ServiceParser weatherService; - - public CurrentTask(final Context context, final CustomHTTPClient HTTPClient, - final ServiceParser weatherService) { - this.localContext = context; - this.HTTPClient = HTTPClient; - this.weatherService = weatherService; - } - - @Override - protected Current doInBackground(final Object... params) { - final double latitude = (Double) params[0]; - final double longitude = (Double) params[1]; - - Current current = null; - try { - current = this.doInBackgroundThrowable(latitude, longitude); - } catch (final JsonParseException e) { - Log.e(TAG, "CurrentTask doInBackground exception: ", e); - } catch (final ClientProtocolException e) { - Log.e(TAG, "CurrentTask doInBackground exception: ", e); - } catch (final MalformedURLException e) { - Log.e(TAG, "CurrentTask doInBackground exception: ", e); - } catch (final URISyntaxException e) { - Log.e(TAG, "CurrentTask doInBackground exception: ", e); - } catch (final IOException e) { - // logger infrastructure swallows UnknownHostException :/ - Log.e(TAG, "CurrentTask doInBackground exception: " + e.getMessage(), e); - } finally { - HTTPClient.close(); - } - - return current; - } - - private Current doInBackgroundThrowable(final double latitude, final double longitude) - throws URISyntaxException, ClientProtocolException, JsonParseException, IOException { - - final String APIVersion = localContext.getResources().getString(R.string.api_version); - final String urlAPI = localContext.getResources().getString(R.string.uri_api_weather_today); - final String url = weatherService.createURIAPICurrent(urlAPI, APIVersion, latitude, longitude); - final String urlWithoutCache = url.concat("&time=" + System.currentTimeMillis()); - final String jsonData = HTTPClient.retrieveDataAsString(new URL(urlWithoutCache)); - - return weatherService.retrieveCurrentFromJPOS(jsonData); - } - - @Override - protected void onPostExecute(final Current current) { - - // Call updateUI on the UI thread. - final Intent currentData = new Intent("com.weather.information.UPDATECURRENT"); - currentData.putExtra("current", current); - LocalBroadcastManager.getInstance(this.localContext).sendBroadcastSync(currentData); - } - } -} diff --git a/app/src/main/java/com/weather/information/fragment/map/MapButtonsFragment.java b/app/src/main/java/com/weather/information/fragment/map/MapButtonsFragment.java deleted file mode 100644 index 076aa2d..0000000 --- a/app/src/main/java/com/weather/information/fragment/map/MapButtonsFragment.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.weather.information.fragment.map; - -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.weather.information.R; - -public class MapButtonsFragment extends Fragment { - - @Override - public View onCreateView(final LayoutInflater inflater, final ViewGroup container, - final Bundle savedInstanceState) { - - // Inflate the layout for this fragment - return inflater.inflate(R.layout.weather_map_buttons, container, false); - } - - /** - * This method will only be called once when the retained - * Fragment is first created. - */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Retain this fragment across configuration changes. - this.setRetainInstance(true); - } -} diff --git a/app/src/main/java/com/weather/information/fragment/map/MapProgressFragment.java b/app/src/main/java/com/weather/information/fragment/map/MapProgressFragment.java deleted file mode 100644 index f60b618..0000000 --- a/app/src/main/java/com/weather/information/fragment/map/MapProgressFragment.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.weather.information.fragment.map; - -import java.io.IOException; -import java.util.List; -import java.util.Locale; - -import android.app.Activity; -import android.content.Context; -import android.location.Address; -import android.location.Geocoder; -import android.os.AsyncTask; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.weather.information.R; -import com.weather.information.model.WeatherLocation; - -/** - * {@link http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html} - * - */ -public class MapProgressFragment extends Fragment { - - /** - * - * Callback interface through which the fragment will report the - * task's progress and results back to the Activity. - */ - public static interface TaskCallbacks { - void onPostExecute(final WeatherLocation weatherLocation); - } - - private TaskCallbacks mCallbacks; - - @Override - public View onCreateView(final LayoutInflater inflater, final ViewGroup container, - final Bundle savedInstanceState) { - - // Inflate the layout for this fragment - return inflater.inflate(R.layout.weather_map_progress, container, false); - } - - /** - * This method will only be called once when the retained - * Fragment is first created. - */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Retain this fragment across configuration changes. - this.setRetainInstance(true); - - final Bundle bundle = this.getArguments(); - double latitude = bundle.getDouble("latitude"); - double longitude = bundle.getDouble("longitude"); - - // Create and execute the background task. - new GetAddressTask(this.getActivity().getApplicationContext()).execute(latitude, longitude); - } - - /** - * Hold a reference to the parent Activity so we can report the - * task's current progress and results. The Android framework - * will pass us a reference to the newly created Activity after - * each configuration change. - */ - @Override - public void onAttach(final Activity activity) { - super.onAttach(activity); - mCallbacks = (TaskCallbacks) activity; - } - - /** - * Set the callback to null so we don't accidentally leak the - * Activity instance. - */ -// @Override -// public void onDetach() { -// super.onDetach(); -// mCallbacks = null; -// } - - /** - * I am not using onDetach because there are problems when my activity goes to background. - * - * {@link http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html} - */ - @Override - public void onPause() { - super.onPause(); - mCallbacks = null; - } - - private class GetAddressTask extends AsyncTask { - private static final String TAG = "GetAddressTask"; - // Store the context passed to the AsyncTask when the system instantiates it. - private final Context localContext; - - private GetAddressTask(final Context context) { - this.localContext = context; - } - - @Override - protected WeatherLocation doInBackground(final Object... params) { - final double latitude = (Double) params[0]; - final double longitude = (Double) params[1]; - - WeatherLocation weatherLocation = this.doDefaultLocation(latitude, longitude); - try { - weatherLocation = this.getLocation(latitude, longitude); - } catch (final Throwable e) { // Hopefully nothing goes wrong because of catching Throwable. - Log.e(TAG, "GetAddressTask doInBackground exception: ", e); - } - - return weatherLocation; - } - - @Override - protected void onPostExecute(final WeatherLocation weatherLocation) { - - // Call updateUI on the UI thread. - if (mCallbacks != null) { - mCallbacks.onPostExecute(weatherLocation); - } - } - - private WeatherLocation getLocation(final double latitude, final double longitude) throws IOException { - // TODO: i18n Locale.getDefault() - final Geocoder geocoder = new Geocoder(this.localContext, Locale.US); - final List
addresses = geocoder.getFromLocation(latitude, longitude, 1); - - // Default values - WeatherLocation weatherLocation = this.doDefaultLocation(latitude, longitude); - - if (addresses != null && addresses.size() > 0) { - if (addresses.get(0).getLocality() != null) { - weatherLocation.setCity(addresses.get(0).getLocality()); - } - if(addresses.get(0).getCountryName() != null) { - weatherLocation.setCountry(addresses.get(0).getCountryName()); - } - } - - return weatherLocation; - } - - private WeatherLocation doDefaultLocation(final double latitude, final double longitude) { - // Default values - String city = this.localContext.getString(R.string.city_not_found); - String country = this.localContext.getString(R.string.country_not_found); - - return new WeatherLocation() - .setLatitude(latitude) - .setLongitude(longitude) - .setCity(city) - .setCountry(country); - } - } -} diff --git a/app/src/main/java/com/weather/information/fragment/overview/OverviewAdapter.java b/app/src/main/java/com/weather/information/fragment/overview/OverviewAdapter.java deleted file mode 100644 index 392faa7..0000000 --- a/app/src/main/java/com/weather/information/fragment/overview/OverviewAdapter.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.weather.information.fragment.overview; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.TextView; - -import com.weather.information.R; - -public class OverviewAdapter extends ArrayAdapter { - private final int resource; - - public OverviewAdapter(final Context context, final int resource) { - super(context, 0); - - this.resource = resource; - } - - @Override - public View getView(final int position, final View convertView, - final ViewGroup parent) { - - // We need to get the best view (re-used if possible) and then - // retrieve its corresponding ViewHolder, which optimizes lookup - // efficiency - final View view = this.getWorkingView(convertView); - final ViewHolder viewHolder = this.getViewHolder(view); - final OverviewEntry entry = this.getItem(position); - - - // Setting date - viewHolder.dateNameView.setText(entry.getDateName()); - viewHolder.dateNumberView.setText(entry.getDateNumber()); - - // Setting temperature max/min - viewHolder.temperatureMaxView.setText(entry.getMaxTemp()); - viewHolder.temperatureMinView.setText(entry.getMinTemp()); - - // Set image view - viewHolder.pictureView.setImageBitmap(entry.getPicture()); - - - return view; - } - - private View getWorkingView(final View convertView) { - // The workingView is basically just the convertView re-used if possible - // or inflated new if not possible - View workingView = null; - - if(null == convertView) { - final Context context = this.getContext(); - final LayoutInflater inflater = (LayoutInflater)context.getSystemService - (Context.LAYOUT_INFLATER_SERVICE); - - workingView = inflater.inflate(this.resource, null); - } else { - workingView = convertView; - } - - return workingView; - } - - private ViewHolder getViewHolder(final View workingView) { - // The viewHolder allows us to avoid re-looking up view references - // Since views are recycled, these references will never change - final Object tag = workingView.getTag(); - ViewHolder viewHolder = null; - - - if((null == tag) || !(tag instanceof ViewHolder)) { - viewHolder = new ViewHolder(); - - viewHolder.dateNameView = (TextView) workingView - .findViewById(R.id.weather_main_entry_date_name); - viewHolder.dateNumberView = (TextView) workingView - .findViewById(R.id.weather_main_entry_date_number); - viewHolder.temperatureMaxView = (TextView) workingView - .findViewById(R.id.weather_main_entry_temperature_max); - viewHolder.temperatureMinView = (TextView) workingView - .findViewById(R.id.weather_main_entry_temperature_min); - viewHolder.pictureView = (ImageView) workingView - .findViewById(R.id.weather_main_entry_image); - - workingView.setTag(viewHolder); - - } else { - viewHolder = (ViewHolder) tag; - } - - return viewHolder; - } - - /** - * ViewHolder allows us to avoid re-looking up view references - * Since views are recycled, these references will never change - */ - private static class ViewHolder { - public TextView dateNameView; - public TextView dateNumberView; - public TextView temperatureMaxView; - public TextView temperatureMinView; - public ImageView pictureView; - } - -} diff --git a/app/src/main/java/com/weather/information/fragment/overview/OverviewEntry.java b/app/src/main/java/com/weather/information/fragment/overview/OverviewEntry.java deleted file mode 100644 index dfcbb30..0000000 --- a/app/src/main/java/com/weather/information/fragment/overview/OverviewEntry.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.weather.information.fragment.overview; - -import android.graphics.Bitmap; - -public class OverviewEntry { - private final String dateName; - private final String dateNumber; - private final String maxTemp; - private final String minTemp; - private final Bitmap picture; - - public OverviewEntry(final String dateName, final String dateNumber, - final String maxTemp, final String minTemp, - final Bitmap picture) { - this.dateName = dateName; - this.dateNumber = dateNumber; - this.maxTemp = maxTemp; - this.minTemp = minTemp; - this.picture = picture; - } - - public String getDateName() { - return this.dateName; - } - - public String getDateNumber() { - return this.dateNumber; - } - - public String getMaxTemp() { - return this.maxTemp; - } - - public String getMinTemp() { - return this.minTemp; - } - - public Bitmap getPicture() { - return this.picture; - } -} diff --git a/app/src/main/java/com/weather/information/fragment/overview/OverviewFragment.java b/app/src/main/java/com/weather/information/fragment/overview/OverviewFragment.java deleted file mode 100644 index 568b029..0000000 --- a/app/src/main/java/com/weather/information/fragment/overview/OverviewFragment.java +++ /dev/null @@ -1,398 +0,0 @@ -package com.weather.information.fragment.overview; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -import org.apache.http.client.ClientProtocolException; - -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.http.AndroidHttpClient; -import android.os.AsyncTask; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.v4.app.ListFragment; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; -import android.view.View; -import android.widget.ListView; - -import com.fasterxml.jackson.core.JsonParseException; -import com.weather.information.R; -import com.weather.information.fragment.specific.SpecificFragment; -import com.weather.information.httpclient.CustomHTTPClient; -import com.weather.information.model.DatabaseQueries; -import com.weather.information.model.WeatherLocation; -import com.weather.information.model.forecastweather.Forecast; -import com.weather.information.parser.JPOSWeatherParser; -import com.weather.information.service.IconsList; -import com.weather.information.service.PermanentStorage; -import com.weather.information.service.ServiceParser; - -public class OverviewFragment extends ListFragment { - private static final String TAG = "OverviewFragment"; - private BroadcastReceiver mReceiver; - - @Override - public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - @Override - public void onActivityCreated(final Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - final ListView listWeatherView = this.getListView(); - listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE); - - if (savedInstanceState != null) { - // Restore UI state - final Forecast forecast = (Forecast) savedInstanceState.getSerializable("Forecast"); - - if (forecast != null) { - final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); - store.saveForecast(forecast); - } - } - - this.setHasOptionsMenu(false); - - this.setEmptyText(this.getString(R.string.text_field_remote_error)); - this.setListShownNoAnimation(false); - } - - @Override - public void onResume() { - super.onResume(); - - this.mReceiver = new BroadcastReceiver() { - - @Override - public void onReceive(final Context context, final Intent intent) { - final String action = intent.getAction(); - if (action.equals("com.weather.information.UPDATEFORECAST")) { - final Forecast forecastRemote = (Forecast) intent.getSerializableExtra("forecast"); - - if (forecastRemote != null) { - - // 1. Check conditions. They must be the same as the ones that triggered the AsyncTask. - final DatabaseQueries query = new DatabaseQueries(context.getApplicationContext()); - final WeatherLocation weatherLocation = query.queryDataBase(); - final PermanentStorage store = new PermanentStorage(context.getApplicationContext()); - final Forecast forecast = store.getForecast(); - - if (forecast == null || !OverviewFragment.this.isDataFresh(weatherLocation.getLastForecastUIUpdate())) { - // 2. Update UI. - OverviewFragment.this.updateUI(forecastRemote); - - // 3. Update Data. - store.saveForecast(forecastRemote); - weatherLocation.setLastForecastUIUpdate(new Date()); - query.updateDataBase(weatherLocation); - - // 4. Show list. - OverviewFragment.this.setListShownNoAnimation(true); - } - - } else { - // Empty list and show error message (see setEmptyText in onCreate) - OverviewFragment.this.setListAdapter(null); - OverviewFragment.this.setListShownNoAnimation(true); - } - } - } - }; - - // Register receiver - final IntentFilter filter = new IntentFilter(); - filter.addAction("com.weather.information.UPDATEFORECAST"); - LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()) - .registerReceiver(this.mReceiver, filter); - - final DatabaseQueries query = new DatabaseQueries(this.getActivity().getApplicationContext()); - final WeatherLocation weatherLocation = query.queryDataBase(); - if (weatherLocation == null) { - // Nothing to do. - // Empty list and show error message (see setEmptyText in onCreate) - this.setListAdapter(null); - this.setListShownNoAnimation(true); - return; - } - - final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); - final Forecast forecast = store.getForecast(); - - if (forecast != null && this.isDataFresh(weatherLocation.getLastForecastUIUpdate())) { - this.updateUI(forecast); - } else { - // Load remote data (aynchronous) - // Gets the data from the web. - this.setListShownNoAnimation(false); - final OverviewTask task = new OverviewTask( - this.getActivity().getApplicationContext(), - new CustomHTTPClient(AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")), - new ServiceParser(new JPOSWeatherParser())); - - task.execute(weatherLocation.getLatitude(), weatherLocation.getLongitude()); - } - } - - @Override - public void onSaveInstanceState(final Bundle savedInstanceState) { - - // Save UI state - final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); - final Forecast forecast = store.getForecast(); - - if (forecast != null) { - savedInstanceState.putSerializable("Forecast", forecast); - } - - super.onSaveInstanceState(savedInstanceState); - } - - @Override - public void onPause() { - LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()).unregisterReceiver(this.mReceiver); - - super.onPause(); - } - - @Override - public void onListItemClick(final ListView l, final View v, final int position, final long id) { - final SpecificFragment fragment = (SpecificFragment) this - .getFragmentManager().findFragmentById(R.id.weather_specific_fragment); - if (fragment == null) { - // handset layout - final Intent intent = new Intent("com.weather.information.WEATHERINFO") - .setComponent(new ComponentName("com.weather.information", - "com.weather.information.activity.SpecificActivity")); - intent.putExtra("CHOSEN_DAY", (int) id); - OverviewFragment.this.getActivity().startActivity(intent); - } else { - // tablet layout - fragment.updateUIByChosenDay((int) id); - } - } - - private interface UnitsConversor { - - public double doConversion(final double value); - } - - private void updateUI(final Forecast forecastWeatherData) { - - final SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(this.getActivity().getApplicationContext()); - - // TODO: repeating the same code in Overview, Specific and Current!!! - // 1. Update units of measurement. - String symbol; - UnitsConversor unitsConversor; - String keyPreference = this.getResources().getString( - R.string.weather_preferences_temperature_key); - final String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); - final String unitsPreferenceValue = sharedPreferences.getString( - keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); - if (unitsPreferenceValue.equals(values[0])) { - symbol = values[0]; - unitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return value - 273.15; - } - - }; - } else if (unitsPreferenceValue.equals(values[1])) { - symbol = values[1]; - unitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return (value * 1.8) - 459.67; - } - - }; - } else { - symbol = values[2]; - unitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return value; - } - - }; - } - - - // 2. Update number day forecast. - keyPreference = this.getResources().getString(R.string.weather_preferences_day_forecast_key); - final String dayForecast = sharedPreferences.getString(keyPreference, "5"); - final int mDayForecast = Integer.valueOf(dayForecast); - - - // 3. Formatters - final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); - tempFormatter.applyPattern("#####.##"); - final SimpleDateFormat dayNameFormatter = new SimpleDateFormat("EEE", Locale.US); - final SimpleDateFormat monthAndDayNumberormatter = new SimpleDateFormat("MMM d", Locale.US); - - - // 4. Prepare data for UI. - final List entries = new ArrayList(); - final OverviewAdapter adapter = new OverviewAdapter(this.getActivity(), - R.layout.weather_main_entry_list); - final Calendar calendar = Calendar.getInstance(); - int count = mDayForecast; - for (final com.weather.information.model.forecastweather.List forecast : forecastWeatherData - .getList()) { - - Bitmap picture; - - if ((forecast.getWeather().size() > 0) && - (forecast.getWeather().get(0).getIcon() != null) && - (IconsList.getIcon(forecast.getWeather().get(0).getIcon()) != null)) { - final String icon = forecast.getWeather().get(0).getIcon(); - picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon) - .getResourceDrawable()); - } else { - picture = BitmapFactory.decodeResource(this.getResources(), - R.drawable.weather_severe_alert); - } - - final Long forecastUNIXDate = (Long) forecast.getDt(); - calendar.setTimeInMillis(forecastUNIXDate * 1000L); - final Date dayTime = calendar.getTime(); - final String dayTextName = dayNameFormatter.format(dayTime); - final String monthAndDayNumberText = monthAndDayNumberormatter.format(dayTime); - - Double maxTemp = null; - if (forecast.getTemp().getMax() != null) { - maxTemp = (Double) forecast.getTemp().getMax(); - maxTemp = unitsConversor.doConversion(maxTemp); - } - - Double minTemp = null; - if (forecast.getTemp().getMin() != null) { - minTemp = (Double) forecast.getTemp().getMin(); - minTemp = unitsConversor.doConversion(minTemp); - } - - if ((maxTemp != null) && (minTemp != null)) { - entries.add(new OverviewEntry(dayTextName, monthAndDayNumberText, - tempFormatter.format(maxTemp) + symbol, tempFormatter.format(minTemp) + symbol, - picture)); - } - - count = count - 1; - if (count == 0) { - break; - } - } - - - // 5. Update UI. - adapter.addAll(entries); - this.setListAdapter(adapter); - } - - private boolean isDataFresh(final Date lastUpdate) { - if (lastUpdate == null) { - return false; - } - - final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences( - this.getActivity().getApplicationContext()); - final String keyPreference = this.getString(R.string.weather_preferences_refresh_interval_key); - final String refresh = sharedPreferences.getString( - keyPreference, - this.getResources().getStringArray(R.array.weather_preferences_refresh_interval)[0]); - final Date currentTime = new Date(); - if (((currentTime.getTime() - lastUpdate.getTime())) < Long.valueOf(refresh)) { - return true; - } - - return false; - } - - private class OverviewTask extends AsyncTask { - // Store the context passed to the AsyncTask when the system instantiates it. - private final Context localContext; - private final CustomHTTPClient HTTPClient; - private final ServiceParser weatherService; - - public OverviewTask(final Context context, final CustomHTTPClient HTTPClient, - final ServiceParser weatherService) { - this.localContext = context; - this.HTTPClient = HTTPClient; - this.weatherService = weatherService; - } - - @Override - protected Forecast doInBackground(final Object... params) { - final double latitude = (Double) params[0]; - final double longitude = (Double) params[1]; - - Forecast forecast = null; - - try { - forecast = this.doInBackgroundThrowable(latitude, longitude); - } catch (final JsonParseException e) { - Log.e(TAG, "OverviewTask doInBackground exception: ", e); - } catch (final ClientProtocolException e) { - Log.e(TAG, "OverviewTask doInBackground exception: ", e); - } catch (final MalformedURLException e) { - Log.e(TAG, "OverviewTask doInBackground exception: ", e); - } catch (final URISyntaxException e) { - Log.e(TAG, "OverviewTask doInBackground exception: ", e); - } catch (final IOException e) { - // logger infrastructure swallows UnknownHostException :/ - Log.e(TAG, "OverviewTask doInBackground exception: " + e.getMessage(), e); - } finally { - HTTPClient.close(); - } - - return forecast; - } - - private Forecast doInBackgroundThrowable(final double latitude, final double longitude) - throws URISyntaxException, ClientProtocolException, JsonParseException, IOException { - - final String APIVersion = localContext.getResources().getString(R.string.api_version); - final String urlAPI = localContext.getResources().getString(R.string.uri_api_weather_forecast); - // TODO: number as resource - final String url = weatherService.createURIAPIForecast(urlAPI, APIVersion, latitude, longitude, "14"); - final String urlWithoutCache = url.concat("&time=" + System.currentTimeMillis()); - final String jsonData = HTTPClient.retrieveDataAsString(new URL(urlWithoutCache)); - - return weatherService.retrieveForecastFromJPOS(jsonData); - } - - @Override - protected void onPostExecute(final Forecast forecast) { - - // Call updateUI on the UI thread. - final Intent forecastData = new Intent("com.weather.information.UPDATEFORECAST"); - forecastData.putExtra("forecast", forecast); - LocalBroadcastManager.getInstance(this.localContext).sendBroadcastSync(forecastData); - } - } -} diff --git a/app/src/main/java/com/weather/information/fragment/preferences/WeatherInformationPreferencesFragment.java b/app/src/main/java/com/weather/information/fragment/preferences/WeatherInformationPreferencesFragment.java deleted file mode 100644 index dd20c78..0000000 --- a/app/src/main/java/com/weather/information/fragment/preferences/WeatherInformationPreferencesFragment.java +++ /dev/null @@ -1,397 +0,0 @@ -package com.weather.information.fragment.preferences; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.os.Bundle; -import android.os.SystemClock; -import android.preference.Preference; -import android.preference.PreferenceFragment; -import android.preference.SwitchPreference; - -import com.weather.information.R; -import com.weather.information.notification.NotificationIntentService; - -public class WeatherInformationPreferencesFragment extends PreferenceFragment - implements OnSharedPreferenceChangeListener { - - @Override - public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Load the preferences from an XML resource - this.addPreferencesFromResource(R.xml.weather_preferences); - - - // Temperature units - String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); - String[] humanValues = this.getResources().getStringArray(R.array.weather_preferences_temperature_human_value); - String keyPreference = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_temperature_key); - Preference connectionPref = this.findPreference(keyPreference); - String value = this.getPreferenceManager().getSharedPreferences() - .getString(keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); - String humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } - connectionPref.setSummary(humanValue); - - // Wind - values = this.getResources().getStringArray(R.array.weather_preferences_wind); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_wind_human_value); - keyPreference = this.getString(R.string.weather_preferences_wind_key); - connectionPref = this.findPreference(keyPreference); - value = this.getPreferenceManager().getSharedPreferences() - .getString(keyPreference, this.getString(R.string.weather_preferences_wind_meters)); - humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } - connectionPref.setSummary(humanValue); - - // Pressure - values = this.getResources().getStringArray(R.array.weather_preferences_pressure); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_pressure_human_value); - keyPreference = this.getString(R.string.weather_preferences_pressure_key); - connectionPref = this.findPreference(keyPreference); - value = this.getPreferenceManager().getSharedPreferences() - .getString(keyPreference, this.getString(R.string.weather_preferences_pressure_pascal)); - humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } - connectionPref.setSummary(humanValue); - - // Forecast days number - values = this.getResources().getStringArray(R.array.weather_preferences_day_forecast); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_day_forecast_human_value); - keyPreference = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_day_forecast_key); - connectionPref = this.findPreference(keyPreference); - value = this.getPreferenceManager().getSharedPreferences().getString(keyPreference, values[0]); - humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } - connectionPref.setSummary(humanValue); - - // Refresh interval - values = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval_human_value); - keyPreference = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_refresh_interval_key); - connectionPref = this.findPreference(keyPreference); - value = this.getPreferenceManager().getSharedPreferences().getString(keyPreference, values[0]); - humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } else if (value.equals(values[3])) { - humanValue = humanValues[3]; - } else if (value.equals(values[4])) { - humanValue = humanValues[4]; - } else if (value.equals(values[5])) { - humanValue = humanValues[5]; - } else if (value.equals(values[6])) { - humanValue = humanValues[6]; - } - connectionPref.setSummary(humanValue); - - // Update Time Rate - values = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate_human_value); - keyPreference = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_update_time_rate_key); - connectionPref = this.findPreference(keyPreference); - value = this.getPreferenceManager().getSharedPreferences() - .getString(keyPreference, values[0]); - humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } else if (value.equals(values[3])) { - humanValue = humanValues[3]; - } else if (value.equals(values[4])) { - humanValue = humanValues[4]; - } - connectionPref.setSummary(humanValue); - - // Notifications temperature units - values = this.getResources().getStringArray(R.array.weather_preferences_temperature); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_temperature_human_value); - keyPreference = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_notifications_temperature_key); - connectionPref = this.findPreference(keyPreference); - value = this.getPreferenceManager().getSharedPreferences() - .getString(keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); - humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } - connectionPref.setSummary(humanValue); - } - - @Override - public void onResume() { - super.onResume(); - this.getPreferenceManager().getSharedPreferences() - .registerOnSharedPreferenceChangeListener(this); - - } - - @Override - public void onPause() { - super.onPause(); - this.getPreferenceManager().getSharedPreferences() - .unregisterOnSharedPreferenceChangeListener(this); - } - - @Override - public void onSharedPreferenceChanged( - final SharedPreferences sharedPreferences, final String key) { - - // Temperature units - String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); - String[] humanValues = this.getResources().getStringArray(R.array.weather_preferences_temperature_human_value); - String keyValue = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_temperature_key); - if (key.equals(keyValue)) { - final Preference connectionPref = this.findPreference(key); - final String value = sharedPreferences.getString(key, values[0]); - String humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } - - connectionPref.setSummary(humanValue); - return; - } - - // Wind - values = this.getResources().getStringArray(R.array.weather_preferences_wind); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_wind_human_value); - keyValue = this.getString(R.string.weather_preferences_wind_key); - if (key.equals(keyValue)) { - final Preference connectionPref = this.findPreference(key); - final String value = sharedPreferences.getString(key, values[0]); - String humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } - - connectionPref.setSummary(humanValue); - return; - } - - // Pressure - values = this.getResources().getStringArray(R.array.weather_preferences_pressure); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_pressure_human_value); - keyValue = this.getString(R.string.weather_preferences_pressure_key); - if (key.equals(keyValue)) { - final Preference connectionPref = this.findPreference(key); - final String value = sharedPreferences.getString(key, values[0]); - String humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } - - connectionPref.setSummary(humanValue); - return; - } - - // Forecast days number - values = this.getResources().getStringArray(R.array.weather_preferences_day_forecast); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_day_forecast_human_value); - keyValue = this.getActivity().getString( - R.string.weather_preferences_day_forecast_key); - if (key.equals(keyValue)) { - final Preference connectionPref = this.findPreference(key); - final String value = sharedPreferences.getString(key, values[0]); - String humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } - connectionPref.setSummary(humanValue); - return; - } - - // Refresh interval - values = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval_human_value); - keyValue = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_refresh_interval_key); - if (key.equals(keyValue)) { - final Preference connectionPref = this.findPreference(key); - final String value = sharedPreferences.getString(key, values[0]); - String humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } else if (value.equals(values[3])) { - humanValue = humanValues[3]; - } else if (value.equals(values[4])) { - humanValue = humanValues[4]; - } else if (value.equals(values[5])) { - humanValue = humanValues[5]; - } else if (value.equals(values[6])) { - humanValue = humanValues[6]; - } - connectionPref.setSummary(humanValue); - return; - } - - // Notification switch - values = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate); - keyValue = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_notifications_switch_key); - if (key.equals(keyValue)) { - final SwitchPreference preference = (SwitchPreference)this.findPreference(key); - if (preference.isChecked()) - { - keyValue = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_update_time_rate_key); - final String value = sharedPreferences.getString(keyValue, values[0]); - this.updateNotification(value); - } else { - this.cancelNotification(); - } - } - // Update Time Rate - values = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate_human_value); - keyValue = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_update_time_rate_key); - if (key.equals(keyValue)) { - final Preference connectionPref = this.findPreference(key); - final String value = sharedPreferences.getString(key, values[0]); - String humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } else if (value.equals(values[3])) { - humanValue = humanValues[3]; - } else if (value.equals(values[4])) { - humanValue = humanValues[4]; - } - - this.updateNotification(value); - connectionPref.setSummary(humanValue); - return; - } - - // Temperature units - values = this.getResources().getStringArray(R.array.weather_preferences_temperature); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_temperature_human_value); - keyValue = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_notifications_temperature_key); - if (key.equals(keyValue)) { - final Preference connectionPref = this.findPreference(key); - final String value = sharedPreferences.getString(key, values[0]); - String humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } - - connectionPref.setSummary(humanValue); - return; - } - } - - private void updateNotification(final String updateTimeRate) { - final String[] values = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate); - long chosenInterval = 0; - if (updateTimeRate.equals(values[0])) { - chosenInterval = AlarmManager.INTERVAL_FIFTEEN_MINUTES; - } else if (updateTimeRate.equals(values[1])) { - chosenInterval = AlarmManager.INTERVAL_HALF_HOUR; - } else if (updateTimeRate.equals(values[2])) { - chosenInterval = AlarmManager.INTERVAL_HOUR; - } else if (updateTimeRate.equals(values[3])) { - chosenInterval = AlarmManager.INTERVAL_HALF_DAY; - } else if (updateTimeRate.equals(values[4])) { - chosenInterval = AlarmManager.INTERVAL_DAY; - } - - final AlarmManager alarmMgr = - (AlarmManager) this.getActivity().getApplicationContext().getSystemService(Context.ALARM_SERVICE); - // TODO: better use some string instead of .class? In case I change the service class - // this could be a problem (I guess) - final Intent serviceIntent = - new Intent(this.getActivity().getApplicationContext(), NotificationIntentService.class); - final PendingIntent alarmIntent = - PendingIntent.getService( - this.getActivity().getApplicationContext(), - 0, - serviceIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - if (chosenInterval != 0) { - alarmMgr.setInexactRepeating( - AlarmManager.ELAPSED_REALTIME, - SystemClock.elapsedRealtime(), - chosenInterval, - alarmIntent); - } - } - - private void cancelNotification() { - final AlarmManager alarmMgr = - (AlarmManager) this.getActivity().getApplicationContext().getSystemService(Context.ALARM_SERVICE); - final Intent serviceIntent = - new Intent(this.getActivity().getApplicationContext(), NotificationIntentService.class); - final PendingIntent alarmIntent = - PendingIntent.getService( - this.getActivity().getApplicationContext(), - 0, - serviceIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - alarmMgr.cancel(alarmIntent); - } -} diff --git a/app/src/main/java/com/weather/information/fragment/specific/SpecificFragment.java b/app/src/main/java/com/weather/information/fragment/specific/SpecificFragment.java deleted file mode 100644 index 54c81e3..0000000 --- a/app/src/main/java/com/weather/information/fragment/specific/SpecificFragment.java +++ /dev/null @@ -1,353 +0,0 @@ -package com.weather.information.fragment.specific; - -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; - -import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import com.weather.information.R; -import com.weather.information.model.forecastweather.Forecast; -import com.weather.information.service.IconsList; -import com.weather.information.service.PermanentStorage; - - -public class SpecificFragment extends Fragment { - private int mChosenDay; - - @Override - public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - final Bundle extras = this.getActivity().getIntent().getExtras(); - - if (extras != null) { - // handset layout - this.mChosenDay = extras.getInt("CHOSEN_DAY", 0); - } else { - // tablet layout - // Always 0 when tablet layout (by default shows the first day) - this.mChosenDay = 0; - } - } - - @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); - - if (savedInstanceState != null) { - // Restore UI state - final Forecast forecast = (Forecast) savedInstanceState.getSerializable("Forecast"); - - if (forecast != null) { - final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); - store.saveForecast(forecast); - } - - this.mChosenDay = savedInstanceState.getInt("mChosenDay"); - } - - this.setHasOptionsMenu(false); - } - - @Override - public void onSaveInstanceState(final Bundle savedInstanceState) { - - // Save UI state - final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); - final Forecast forecast = store.getForecast(); - - if (forecast != null) { - savedInstanceState.putSerializable("Forecast", forecast); - } - - savedInstanceState.putInt("mChosenDay", this.mChosenDay); - - super.onSaveInstanceState(savedInstanceState); - } - - /** - * This method is used by tablet layout. - * - * @param chosenDay - */ - public void updateUIByChosenDay(final int chosenDay) { - final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); - final Forecast forecast = store.getForecast(); - - if (forecast != null) { - this.updateUI(forecast, chosenDay); - } - } - - private interface UnitsConversor { - - public double doConversion(final double value); - } - - private void updateUI(final Forecast forecastWeatherData, final int chosenDay) { - - final SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(this.getActivity()); - - // TODO: repeating the same code in Overview, Specific and Current!!! - // 1. Update units of measurement. - // 1.1 Temperature - String tempSymbol; - UnitsConversor tempUnitsConversor; - String keyPreference = this.getResources().getString( - R.string.weather_preferences_temperature_key); - String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); - String unitsPreferenceValue = sharedPreferences.getString( - keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); - if (unitsPreferenceValue.equals(values[0])) { - tempSymbol = values[0]; - tempUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return value - 273.15; - } - - }; - } else if (unitsPreferenceValue.equals(values[1])) { - tempSymbol = values[1]; - tempUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return (value * 1.8) - 459.67; - } - - }; - } else { - tempSymbol = values[2]; - tempUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return value; - } - - }; - } - - // 1.2 Wind - String windSymbol; - UnitsConversor windUnitsConversor; - keyPreference = this.getResources().getString(R.string.weather_preferences_wind_key); - values = this.getResources().getStringArray(R.array.weather_preferences_wind); - unitsPreferenceValue = sharedPreferences.getString( - keyPreference, this.getString(R.string.weather_preferences_wind_meters)); - if (unitsPreferenceValue.equals(values[0])) { - windSymbol = values[0]; - windUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(double value) { - return value; - } - }; - } else { - windSymbol = values[1]; - windUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(double value) { - return value * 2.237; - } - }; - } - - // 1.3 Pressure - String pressureSymbol; - UnitsConversor pressureUnitsConversor; - keyPreference = this.getResources().getString(R.string.weather_preferences_pressure_key); - values = this.getResources().getStringArray(R.array.weather_preferences_pressure); - unitsPreferenceValue = sharedPreferences.getString( - keyPreference, this.getString(R.string.weather_preferences_pressure_pascal)); - if (unitsPreferenceValue.equals(values[0])) { - pressureSymbol = values[0]; - pressureUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(double value) { - return value; - } - }; - } else { - pressureSymbol = values[1]; - pressureUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(double value) { - return value / 113.25d; - } - }; - } - - - // 2. Formatters - final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); - tempFormatter.applyPattern("#####.#####"); - - - // 3. Prepare data for UI. - final com.weather.information.model.forecastweather.List forecast = forecastWeatherData - .getList().get((chosenDay)); - - final SimpleDateFormat dayFormatter = new SimpleDateFormat("EEEE - MMM d", Locale.US); - final Calendar calendar = Calendar.getInstance(); - final Long forecastUNIXDate = (Long) forecast.getDt(); - calendar.setTimeInMillis(forecastUNIXDate * 1000L); - final Date date = calendar.getTime(); - - String tempMax = ""; - if (forecast.getTemp().getMax() != null) { - double conversion = (Double) forecast.getTemp().getMax(); - conversion = tempUnitsConversor.doConversion(conversion); - tempMax = tempFormatter.format(conversion) + tempSymbol; - } - String tempMin = ""; - if (forecast.getTemp().getMin() != null) { - double conversion = (Double) forecast.getTemp().getMin(); - conversion = tempUnitsConversor.doConversion(conversion); - tempMin = tempFormatter.format(conversion) + tempSymbol; - } - Bitmap picture; - if ((forecast.getWeather().size() > 0) && (forecast.getWeather().get(0).getIcon() != null) - && (IconsList.getIcon(forecast.getWeather().get(0).getIcon()) != null)) { - final String icon = forecast.getWeather().get(0).getIcon(); - picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon) - .getResourceDrawable()); - } else { - picture = BitmapFactory.decodeResource(this.getResources(), - R.drawable.weather_severe_alert); - } - - String description = this.getString(R.string.text_field_description_when_error); - if (forecast.getWeather().size() > 0) { - description = forecast.getWeather().get(0).getDescription(); - } - - String humidityValue = ""; - if (forecast.getHumidity() != null) { - final double conversion = (Double) forecast.getHumidity(); - humidityValue = tempFormatter.format(conversion); - } - String pressureValue = ""; - if (forecast.getPressure() != null) { - double conversion = (Double) forecast.getPressure(); - conversion = pressureUnitsConversor.doConversion(conversion); - pressureValue = tempFormatter.format(conversion); - } - String windValue = ""; - if (forecast.getSpeed() != null) { - double conversion = (Double) forecast.getSpeed(); - conversion = windUnitsConversor.doConversion(conversion); - windValue = tempFormatter.format(conversion); - } - String rainValue = ""; - if (forecast.getRain() != null) { - final double conversion = (Double) forecast.getRain(); - rainValue = tempFormatter.format(conversion); - } - String cloudsValue = ""; - if (forecast.getRain() != null) { - final double conversion = (Double) forecast.getClouds(); - cloudsValue = tempFormatter.format(conversion); - } - - String tempDay = ""; - if (forecast.getTemp().getDay() != null) { - double conversion = (Double) forecast.getTemp().getDay(); - conversion = tempUnitsConversor.doConversion(conversion); - tempDay = tempFormatter.format(conversion) + tempSymbol; - } - String tempMorn = ""; - if (forecast.getTemp().getMorn() != null) { - double conversion = (Double) forecast.getTemp().getMorn(); - conversion = tempUnitsConversor.doConversion(conversion); - tempMorn = tempFormatter.format(conversion) + tempSymbol; - } - String tempEve = ""; - if (forecast.getTemp().getEve() != null) { - double conversion = (Double) forecast.getTemp().getEve(); - conversion = tempUnitsConversor.doConversion(conversion); - tempEve = tempFormatter.format(conversion) + tempSymbol; - } - String tempNight = ""; - if (forecast.getTemp().getNight() != null) { - double conversion = (Double) forecast.getTemp().getNight(); - conversion = tempUnitsConversor.doConversion(conversion); - tempNight = tempFormatter.format(conversion) + tempSymbol; - } - - - // 4. Update UI. - this.getActivity().getActionBar().setSubtitle(dayFormatter.format(date).toUpperCase()); - - final TextView tempMaxView = (TextView) getActivity().findViewById(R.id.weather_specific_temp_max); - tempMaxView.setText(tempMax); - final TextView tempMinView = (TextView) getActivity().findViewById(R.id.weather_specific_temp_min); - tempMinView.setText(tempMin); - final ImageView pictureView = (ImageView) getActivity().findViewById(R.id.weather_specific_picture); - pictureView.setImageBitmap(picture); - - final TextView descriptionView = (TextView) getActivity().findViewById(R.id.weather_specific_description); - descriptionView.setText(description); - - final TextView humidityValueView = (TextView) getActivity().findViewById(R.id.weather_specific_humidity_value); - humidityValueView.setText(humidityValue); - ((TextView) getActivity().findViewById(R.id.weather_specific_pressure_value)).setText(pressureValue); - ((TextView) getActivity().findViewById(R.id.weather_specific_pressure_units)).setText(pressureSymbol); - ((TextView) getActivity().findViewById(R.id.weather_specific_wind_value)).setText(windValue); - ((TextView) getActivity().findViewById(R.id.weather_specific_wind_units)).setText(windSymbol); - final TextView rainValueView = (TextView) getActivity().findViewById(R.id.weather_specific_rain_value); - rainValueView.setText(rainValue); - final TextView cloudsValueView = (TextView) getActivity().findViewById(R.id.weather_specific_clouds_value); - cloudsValueView.setText(cloudsValue); - - final TextView tempDayView = (TextView) getActivity().findViewById(R.id.weather_specific_day_temperature); - tempDayView.setText(tempDay); - final TextView tempMornView = (TextView) getActivity().findViewById(R.id.weather_specific_morn_temperature); - tempMornView.setText(tempMorn); - final TextView tempEveView = (TextView) getActivity().findViewById(R.id.weather_specific_eve_temperature); - tempEveView.setText(tempEve); - final TextView tempNightView = (TextView) getActivity().findViewById(R.id.weather_specific_night_temperature); - tempNightView.setText(tempNight); - } - - @Override - public void onResume() { - super.onResume(); - - final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); - final Forecast forecast = store.getForecast(); - - if (forecast != null) { - this.updateUI(forecast, this.mChosenDay); - } - } -} diff --git a/app/src/main/java/com/weather/information/httpclient/Consts.java b/app/src/main/java/com/weather/information/httpclient/Consts.java deleted file mode 100644 index 92795dc..0000000 --- a/app/src/main/java/com/weather/information/httpclient/Consts.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package com.weather.information.httpclient; - -import java.nio.charset.Charset; - -/** - * Commons constants. - * - * @since 4.2 - */ -public final class Consts { - - public static final int CR = 13; // - public static final int LF = 10; // - public static final int SP = 32; // - public static final int HT = 9; // - - public static final Charset UTF_8 = Charset.forName("UTF-8"); - public static final Charset ASCII = Charset.forName("US-ASCII"); - public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); - - private Consts() { - } - -} diff --git a/app/src/main/java/com/weather/information/httpclient/ContentType.java b/app/src/main/java/com/weather/information/httpclient/ContentType.java deleted file mode 100644 index c2224a7..0000000 --- a/app/src/main/java/com/weather/information/httpclient/ContentType.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package com.weather.information.httpclient; - -import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; -import java.util.Locale; - -import org.apache.http.Header; -import org.apache.http.HeaderElement; -import org.apache.http.HttpEntity; -import org.apache.http.NameValuePair; -import org.apache.http.ParseException; -import org.apache.http.message.BasicHeaderValueParser; - -/** - * Content type information consisting of a MIME type and an optional charset. - *

- * This class makes no attempts to verify validity of the MIME type. - * The input parameters of the {@link #create(String, String)} method, however, may not - * contain characters <">, <;>, <,> reserved by the HTTP specification. - * - * @since 4.2 - */ - -public final class ContentType { - - // constants - public static final ContentType APPLICATION_ATOM_XML = create( - "application/atom+xml", Consts.ISO_8859_1); - public static final ContentType APPLICATION_FORM_URLENCODED = create( - "application/x-www-form-urlencoded", Consts.ISO_8859_1); - public static final ContentType APPLICATION_JSON = create( - "application/json", Consts.UTF_8); - public static final ContentType APPLICATION_OCTET_STREAM = create( - "application/octet-stream", (Charset) null); - public static final ContentType APPLICATION_SVG_XML = create( - "application/svg+xml", Consts.ISO_8859_1); - public static final ContentType APPLICATION_XHTML_XML = create( - "application/xhtml+xml", Consts.ISO_8859_1); - public static final ContentType APPLICATION_XML = create( - "application/xml", Consts.ISO_8859_1); - public static final ContentType MULTIPART_FORM_DATA = create( - "multipart/form-data", Consts.ISO_8859_1); - public static final ContentType TEXT_HTML = create( - "text/html", Consts.ISO_8859_1); - public static final ContentType TEXT_PLAIN = create( - "text/plain", Consts.ISO_8859_1); - public static final ContentType TEXT_XML = create( - "text/xml", Consts.ISO_8859_1); - public static final ContentType WILDCARD = create( - "*/*", (Charset) null); - - // defaults - public static final ContentType DEFAULT_TEXT = TEXT_PLAIN; - public static final ContentType DEFAULT_BINARY = APPLICATION_OCTET_STREAM; - - private final String mimeType; - private final Charset charset; - - /** - * Given a MIME type and a character set, constructs a ContentType. - * @param mimeType The MIME type to use for the ContentType header. - * @param charset The optional character set to use with the ContentType header. - * @throws UnsupportedCharsetException - * If no support for the named charset is available in this Java virtual machine - */ - ContentType(final String mimeType, final Charset charset) { - this.mimeType = mimeType; - this.charset = charset; - } - - public String getMimeType() { - return this.mimeType; - } - - public Charset getCharset() { - return this.charset; - } - - /** - * Converts a ContentType to a string which can be used as a ContentType header. - * If a charset is provided by the ContentType, it will be included in the string. - */ - @Override - public String toString() { - final StringBuilder buf = new StringBuilder(); - buf.append(this.mimeType); - if (this.charset != null) { - buf.append("; charset="); - buf.append(this.charset); - } - return buf.toString(); - } - - private static boolean valid(final String s) { - for (int i = 0; i < s.length(); i++) { - final char ch = s.charAt(i); - if ((ch == '"') || (ch == ',') || (ch == ';')) { - return false; - } - } - return true; - } - - /** - * Creates a new instance of {@link ContentType}. - * - * @param mimeType MIME type. It may not be null or empty. It may not contain - * characters <">, <;>, <,> reserved by the HTTP specification. - * @param charset charset. - * @return content type - */ - public static ContentType create(final String mimeType, final Charset charset) { - if (mimeType == null) { - throw new IllegalArgumentException("MIME type may not be null"); - } - final String type = mimeType.trim().toLowerCase(Locale.US); - if (type.length() == 0) { - throw new IllegalArgumentException("MIME type may not be empty"); - } - if (!valid(type)) { - throw new IllegalArgumentException("MIME type may not contain reserved characters"); - } - return new ContentType(type, charset); - } - - /** - * Creates a new instance of {@link ContentType} without a charset. - * - * @param mimeType MIME type. It may not be null or empty. It may not contain - * characters <">, <;>, <,> reserved by the HTTP specification. - * @return content type - */ - public static ContentType create(final String mimeType) { - return new ContentType(mimeType, (Charset) null); - } - - /** - * Creates a new instance of {@link ContentType}. - * - * @param mimeType MIME type. It may not be null or empty. It may not contain - * characters <">, <;>, <,> reserved by the HTTP specification. - * @param charset charset. It may not contain characters <">, <;>, <,> reserved by the HTTP - * specification. This parameter is optional. - * @return content type - */ - public static ContentType create( - final String mimeType, final String charset) throws UnsupportedCharsetException { - return create(mimeType, charset != null ? Charset.forName(charset) : null); - } - - private static ContentType create(final HeaderElement helem) { - final String mimeType = helem.getName(); - String charset = null; - final NameValuePair param = helem.getParameterByName("charset"); - if (param != null) { - charset = param.getValue(); - } - return create(mimeType, charset); - } - - /** - * Parses textual representation of Content-Type value. - * - * @param s text - * @return content type - * @throws ParseException if the given text does not represent a valid - * Content-Type value. - */ - public static ContentType parse( - final String s) throws ParseException, UnsupportedCharsetException { - if (s == null) { - throw new IllegalArgumentException("Content type may not be null"); - } - final HeaderElement[] elements = BasicHeaderValueParser.parseElements(s, null); - if (elements.length > 0) { - return create(elements[0]); - } else { - throw new ParseException("Invalid content type: " + s); - } - } - - /** - * Extracts Content-Type value from {@link HttpEntity} exactly as - * specified by the Content-Type header of the entity. Returns null - * if not specified. - * - * @param entity HTTP entity - * @return content type - * @throws ParseException if the given text does not represent a valid - * Content-Type value. - */ - public static ContentType get( - final HttpEntity entity) throws ParseException, UnsupportedCharsetException { - if (entity == null) { - return null; - } - final Header header = entity.getContentType(); - if (header != null) { - final HeaderElement[] elements = header.getElements(); - if (elements.length > 0) { - return create(elements[0]); - } - } - return null; - } - - /** - * Extracts Content-Type value from {@link HttpEntity} or returns default value - * if not explicitly specified. - * - * @param entity HTTP entity - * @return content type - * @throws ParseException if the given text does not represent a valid - * Content-Type value. - */ - public static ContentType getOrDefault(final HttpEntity entity) throws ParseException { - final ContentType contentType = get(entity); - return contentType != null ? contentType : DEFAULT_TEXT; - } - -} diff --git a/app/src/main/java/com/weather/information/httpclient/CustomHTTPClient.java b/app/src/main/java/com/weather/information/httpclient/CustomHTTPClient.java deleted file mode 100644 index 0a1b3f7..0000000 --- a/app/src/main/java/com/weather/information/httpclient/CustomHTTPClient.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.weather.information.httpclient; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; -import java.net.URL; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpGet; - -import android.net.http.AndroidHttpClient; - -public class CustomHTTPClient { - private final AndroidHttpClient httpClient; - - public CustomHTTPClient(final AndroidHttpClient httpClient) { - this.httpClient = httpClient; - } - - public String retrieveDataAsString(final URL url) - throws URISyntaxException, ClientProtocolException, IOException { - - final ResponseHandler handler = new ResponseHandler() { - @Override - public String handleResponse( - final HttpResponse response) - throws UnsupportedEncodingException, IOException { - - if (response != null) { - final HttpEntity entity = response.getEntity(); - if (entity != null) { - try { - final ContentType contentType = ContentType.getOrDefault(entity); - final ByteArrayOutputStream buffer = CustomHTTPClient.this - .sortResponse(response); - return new String(buffer.toByteArray(), contentType.getCharset()); - } finally { - entity.consumeContent(); - } - } - - throw new IOException("There is no entity"); - } - - throw new IOException("There is no response"); - } - }; - - final HttpGet httpGet = new HttpGet(); - httpGet.setURI(url.toURI()); - - return this.httpClient.execute(httpGet, handler); - } - - public ByteArrayOutputStream retrieveRawData(final URL url) - throws URISyntaxException, ClientProtocolException, IOException { - final ResponseHandler handler = new ResponseHandler() { - - @Override - public ByteArrayOutputStream handleResponse( - final HttpResponse response) - throws UnsupportedEncodingException, IOException { - - if (response != null) { - final HttpEntity entity = response.getEntity(); - if (entity != null) { - try { - return CustomHTTPClient.this.sortResponse(response); - } finally { - entity.consumeContent(); - } - } - - throw new IOException("There is no entity"); - } - - throw new IOException("There is no response"); - } - }; - - final HttpGet httpGet = new HttpGet(); - httpGet.setURI(url.toURI()); - - return this.httpClient.execute(httpGet, handler); - } - - public void close() { - this.httpClient.close(); - } - - private ByteArrayOutputStream sortResponse(final HttpResponse httpResponse) throws IOException { - - if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - throw new IOException("Unexpected response code: " - + httpResponse.getStatusLine().getStatusCode()); - } - - final HttpEntity entity = httpResponse.getEntity(); - final InputStream inputStream = entity.getContent(); - try { - return this.readInputStream(inputStream); - } finally { - inputStream.close(); - } - - } - - private ByteArrayOutputStream readInputStream (final InputStream inputStream) throws IOException { - final ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); - final int bufferSize = 1024; - final byte[] buffer = new byte[bufferSize]; - - int len = 0; - while ((len = inputStream.read(buffer)) != -1) { - byteBuffer.write(buffer, 0, len); - } - - return byteBuffer; - } -} diff --git a/app/src/main/java/com/weather/information/model/DatabaseQueries.java b/app/src/main/java/com/weather/information/model/DatabaseQueries.java deleted file mode 100644 index 41bf3b3..0000000 --- a/app/src/main/java/com/weather/information/model/DatabaseQueries.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.weather.information.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/app/src/main/java/com/weather/information/model/WeatherLocation.java b/app/src/main/java/com/weather/information/model/WeatherLocation.java deleted file mode 100644 index 5e46cc7..0000000 --- a/app/src/main/java/com/weather/information/model/WeatherLocation.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.weather.information.model; - -import java.io.Serializable; -import java.util.Date; - - -public class WeatherLocation implements Serializable { - 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; - private boolean isNew; - - public WeatherLocation setId(int id) { - this.id = id; - return this; - } - - public WeatherLocation setCity(String city) { - this.city = city; - return this; - } - - public WeatherLocation setCountry(String country) { - this.country = country; - return this; - } - - public WeatherLocation setIsSelected(boolean isSelected) { - this.isSelected = isSelected; - return this; - } - - public WeatherLocation setLatitude(double latitude) { - this.latitude = latitude; - return this; - } - - public WeatherLocation setLongitude(double longitude) { - this.longitude = longitude; - return this; - } - - public WeatherLocation setLastCurrentUIUpdate(Date lastCurrentUIUpdate) { - this.lastCurrentUIUpdate = lastCurrentUIUpdate; - return this; - } - - public WeatherLocation setLastForecastUIUpdate(Date lastForecastUIUpdate) { - this.lastForecastUIUpdate = lastForecastUIUpdate; - return this; - } - - public WeatherLocation setIsNew(final boolean isNew) { - this.isNew = isNew; - 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; - } - - public double getLongitude() { - return this.longitude; - } - - public Date getLastCurrentUIUpdate() { - return this.lastCurrentUIUpdate; - } - - public Date getLastForecastUIUpdate() { - return this.lastForecastUIUpdate; - } - - public boolean getIsNew() { - return this.isNew; - } -} diff --git a/app/src/main/java/com/weather/information/model/WeatherLocationContract.java b/app/src/main/java/com/weather/information/model/WeatherLocationContract.java deleted file mode 100644 index cea6086..0000000 --- a/app/src/main/java/com/weather/information/model/WeatherLocationContract.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.weather.information.model; - -import android.provider.BaseColumns; - -public class WeatherLocationContract { - - // This class can't be instantiated - private WeatherLocationContract() {} - - public static final class WeatherLocation implements BaseColumns { - - // This class can't be instantiated - private WeatherLocation() {} - - public static final String TABLE_NAME = "locations"; - - public static final String COLUMN_NAME_IS_SELECTED = "isSelected"; - - public static final String COLUMN_NAME_LATITUDE = "latitude"; - - public static final String COLUMN_NAME_LONGITUDE = "longitude"; - - public static final String COLUMN_NAME_COUNTRY = "country"; - - public static final String COLUMN_NAME_CITY = "city"; - - public static final String COLUMN_NAME_LAST_FORECAST_UI_UPDATE = "lastForecastUpdate"; - - public static final String COLUMN_NAME_LAST_CURRENT_UI_UPDATE = "lastCurrentUpdate"; - - public static final String COLUMN_NAME_IS_NEW = "isNew"; - } - -} diff --git a/app/src/main/java/com/weather/information/model/WeatherLocationDbHelper.java b/app/src/main/java/com/weather/information/model/WeatherLocationDbHelper.java deleted file mode 100644 index 69e10f5..0000000 --- a/app/src/main/java/com/weather/information/model/WeatherLocationDbHelper.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.weather.information.model; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.util.Log; - -public class WeatherLocationDbHelper extends SQLiteOpenHelper { - private static final String TAG = "LocationDbHelper"; - public static final int DATABASE_VERSION = 1; - public static final String DATABASE_NAME = "Location.db"; - - public WeatherLocationDbHelper(final Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(final SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + WeatherLocationContract.WeatherLocation.TABLE_NAME + " (" - + WeatherLocationContract.WeatherLocation._ID + " INTEGER PRIMARY KEY, " - + WeatherLocationContract.WeatherLocation.COLUMN_NAME_CITY + " TEXT" + " NOT NULL, " - + WeatherLocationContract.WeatherLocation.COLUMN_NAME_COUNTRY + " TEXT" + " NOT NULL, " - + WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED + " INTEGER" + " NOT NULL, " - + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE + " INTEGER, " - + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE + " INTEGER, " - + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE + " REAL" + " NOT NULL, " - + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE + " REAL" + " NOT NULL, " - + WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_NEW + " INTEGER" + " NOT NULL " - + ");"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w(TAG, "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will destroy all old data"); - - // Kills the table and existing data - db.execSQL("DROP TABLE IF EXISTS " + WeatherLocationContract.WeatherLocation.TABLE_NAME); - - // Recreates the database with a new version - onCreate(db); - } - -} diff --git a/app/src/main/java/com/weather/information/model/WeatherLocationDbQueries.java b/app/src/main/java/com/weather/information/model/WeatherLocationDbQueries.java deleted file mode 100644 index 8cf2cd7..0000000 --- a/app/src/main/java/com/weather/information/model/WeatherLocationDbQueries.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.weather.information.model; - -import java.util.Date; - -import android.content.ContentValues; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; - -public class WeatherLocationDbQueries { - private final SQLiteOpenHelper mDbHelper; - - public interface DoQuery { - - public WeatherLocation doQuery(final Cursor cursor); - } - - public WeatherLocationDbQueries(final SQLiteOpenHelper dbHelper) { - this.mDbHelper = dbHelper; - } - - public WeatherLocation queryDataBase() { - final String selection = WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED + " = ?"; - final String[] selectionArgs = { "1" }; - final String[] projection = { - WeatherLocationContract.WeatherLocation._ID, - WeatherLocationContract.WeatherLocation.COLUMN_NAME_CITY, - WeatherLocationContract.WeatherLocation.COLUMN_NAME_COUNTRY, - WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED, - WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE, - WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE, - WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE, - WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE, - WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_NEW - }; - - - final WeatherLocationDbQueries.DoQuery doQuery = new WeatherLocationDbQueries.DoQuery() { - - @Override - public WeatherLocation doQuery(final Cursor cursor) { - final int id = cursor.getInt(cursor.getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation._ID)); - final String city = cursor.getString(cursor. - getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_CITY)); - final String country = cursor.getString(cursor. - getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_COUNTRY)); - final boolean isSelected = (cursor.getInt(cursor - .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED)) != 0); - Date lastCurrentUIUpdate = null; - if (!cursor.isNull(cursor - .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE))) { - final long javaTime = cursor.getLong(cursor - .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE)); - lastCurrentUIUpdate = new Date(javaTime); - } - Date lasForecastUIUpdate = null; - if (!cursor.isNull(cursor - .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE))) { - final long javaTime = cursor.getLong(cursor - .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE)); - lasForecastUIUpdate = new Date(javaTime); - } - final double latitude = cursor.getDouble(cursor. - getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE)); - final double longitude = cursor.getDouble(cursor. - getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE)); - final boolean isNew = (cursor.getInt(cursor - .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_NEW)) != 0); - - - return new WeatherLocation() - .setId(id) - .setCity(city) - .setCountry(country) - .setIsSelected(isSelected) - .setLastCurrentUIUpdate(lastCurrentUIUpdate) - .setLastForecastUIUpdate(lasForecastUIUpdate) - .setLatitude(latitude) - .setLongitude(longitude) - .setIsNew(isNew); - } - }; - - return this.queryDataBase( - 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) { - values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE, javaTime.getTime()); - } - javaTime = weatherLocation.getLastForecastUIUpdate(); - if (javaTime != null) { - values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE, javaTime.getTime()); - } - values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE, weatherLocation.getLatitude()); - values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE, weatherLocation.getLongitude()); - values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_NEW, weatherLocation.getIsNew()); - - 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()); - Date javaTime = weatherLocation.getLastCurrentUIUpdate(); - if (javaTime != null) { - values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE, javaTime.getTime()); - } else { - values.putNull(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE); - } - javaTime = weatherLocation.getLastForecastUIUpdate(); - if (javaTime != null) { - values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE, javaTime.getTime()); - } else { - 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()); - values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_NEW, weatherLocation.getIsNew()); - - 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, - final String selection, final DoQuery doQuery) { - final SQLiteDatabase db = this.mDbHelper.getReadableDatabase(); - try { - final Cursor cursor = db.query(table, projection, selection, selectionArgs, null, null, null); - try { - if (!cursor.moveToFirst()) { - return null; - } - else { - return doQuery.doQuery(cursor); - } - } finally { - cursor.close(); - } - } finally { - db.close(); - } - } - - // 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.getWritableDatabase(); - try { - return db.update(table, values, selection, selectionArgs); - } finally { - db.close(); - } - } - -} diff --git a/app/src/main/java/com/weather/information/model/currentweather/Clouds.java b/app/src/main/java/com/weather/information/model/currentweather/Clouds.java deleted file mode 100644 index c53cf04..0000000 --- a/app/src/main/java/com/weather/information/model/currentweather/Clouds.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.weather.information.model.currentweather; - -import java.io.Serializable; - -public class Clouds implements Serializable { - private static final long serialVersionUID = 3034435739326030899L; - private Number all; - - public Number getAll(){ - return this.all; - } - public void setAll(final Number all){ - this.all = all; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Clouds [all=").append(this.all).append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/currentweather/Coord.java b/app/src/main/java/com/weather/information/model/currentweather/Coord.java deleted file mode 100644 index 649b937..0000000 --- a/app/src/main/java/com/weather/information/model/currentweather/Coord.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.weather.information.model.currentweather; - -import java.io.Serializable; - -public class Coord implements Serializable { - private static final long serialVersionUID = 7151637605146377486L; - private Number lat; - private Number lon; - - public Number getLat(){ - return this.lat; - } - public void setLat(final Number lat){ - this.lat = lat; - } - public Number getLon(){ - return this.lon; - } - public void setLon(final Number lon){ - this.lon = lon; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Coord [lat=").append(this.lat).append(", lon=").append(this.lon) - .append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/currentweather/Current.java b/app/src/main/java/com/weather/information/model/currentweather/Current.java deleted file mode 100644 index de76a75..0000000 --- a/app/src/main/java/com/weather/information/model/currentweather/Current.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.weather.information.model.currentweather; - -import java.io.Serializable; -import java.util.Date; -import java.util.List; - -/** - * Auto generated by: http://jsongen.byingtondesign.com/ - * (with my own modifications) - * - */ -public class Current implements Serializable { - private static final long serialVersionUID = -730690341739860818L; - private String base; - private Clouds clouds; - private Number cod; - private Coord coord; - private Number dt; - private Number id; - private Main main; - private String name; - private Rain rain; - private Snow snow; - private Sys sys; - private List weather; - private Wind wind; - private byte[] iconData; - private Date date; - - public String getBase(){ - return this.base; - } - public void setBase(final String base){ - this.base = base; - } - public Clouds getClouds(){ - return this.clouds; - } - public void setClouds(final Clouds clouds){ - this.clouds = clouds; - } - - public Number getCod() { - return this.cod; - } - - public void setCod(final Number cod) { - this.cod = cod; - } - public Coord getCoord(){ - return this.coord; - } - public void setCoord(final Coord coord){ - this.coord = coord; - } - public Number getDt(){ - return this.dt; - } - public void setDt(final Number dt){ - this.dt = dt; - } - public Number getId(){ - return this.id; - } - public void setId(final Number id){ - this.id = id; - } - public Main getMain(){ - return this.main; - } - public void setMain(final Main main){ - this.main = main; - } - public String getName(){ - return this.name; - } - public void setName(final String name){ - this.name = name; - } - public Rain getRain(){ - return this.rain; - } - public void setRain(final Rain rain){ - this.rain = rain; - } - public Snow getSnow() { - return this.snow; - } - public void setSnow(final Snow snow) { - this.snow = snow; - } - public Sys getSys(){ - return this.sys; - } - public void setSys(final Sys sys){ - this.sys = sys; - } - public List getWeather(){ - return this.weather; - } - public void setWeather(final List weather){ - this.weather = weather; - } - public Wind getWind(){ - return this.wind; - } - public void setWind(final Wind wind){ - this.wind = wind; - } - - public byte[] getIconData() { - return this.iconData; - } - - public void setIconData(final byte[] iconData) { - this.iconData = iconData; - } - - public Date getDate() { - return this.date; - } - - public void setDate(final Date date) { - this.date = date; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Current [base=").append(this.base).append(", clouds=") - .append(this.clouds).append(", cod=").append(this.cod).append(", coord=") - .append(this.coord).append(", dt=").append(this.dt).append(", id=").append(this.id) - .append(", main=").append(this.main).append(", name=").append(this.name) - .append(", rain=").append(this.rain).append(", snow=").append(this.snow) - .append(", sys=").append(this.sys).append(", weather=").append(this.weather) - .append(", wind=").append(this.wind).append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/currentweather/Main.java b/app/src/main/java/com/weather/information/model/currentweather/Main.java deleted file mode 100644 index 5f755c9..0000000 --- a/app/src/main/java/com/weather/information/model/currentweather/Main.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.weather.information.model.currentweather; - -import java.io.Serializable; - -public class Main implements Serializable { - private static final long serialVersionUID = -6000879164436289447L; - private Number grnd_level; - private Number humidity; - private Number pressure; - private Number sea_level; - private Number temp; - private Number temp_max; - private Number temp_min; - - public Number getGrnd_level() { - return this.grnd_level; - } - - public void setGrnd_level(final Number grnd_level) { - this.grnd_level = grnd_level; - } - - public Number getHumidity(){ - return this.humidity; - } - public void setHumidity(final Number humidity){ - this.humidity = humidity; - } - public Number getPressure(){ - return this.pressure; - } - public void setPressure(final Number pressure){ - this.pressure = pressure; - } - - public Number getSea_level() { - return this.sea_level; - } - - public void setSea_level(final Number sea_level) { - this.sea_level = sea_level; - } - - public Number getTemp(){ - return this.temp; - } - public void setTemp(final Number temp){ - this.temp = temp; - } - public Number getTemp_max(){ - return this.temp_max; - } - public void setTemp_max(final Number temp_max){ - this.temp_max = temp_max; - } - public Number getTemp_min(){ - return this.temp_min; - } - public void setTemp_min(final Number temp_min){ - this.temp_min = temp_min; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Main [grnd_level=").append(this.grnd_level).append(", humidity=") - .append(this.humidity).append(", pressure=").append(this.pressure) - .append(", sea_level=").append(this.sea_level).append(", temp=").append(this.temp) - .append(", temp_max=").append(this.temp_max).append(", temp_min=") - .append(this.temp_min).append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/currentweather/Rain.java b/app/src/main/java/com/weather/information/model/currentweather/Rain.java deleted file mode 100644 index be82dfe..0000000 --- a/app/src/main/java/com/weather/information/model/currentweather/Rain.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.weather.information.model.currentweather; - -import java.io.Serializable; - -public class Rain implements Serializable { - private static final long serialVersionUID = 1318464783605029435L; - private Number three; - - public Number get3h(){ - return this.three; - } - - public void set3h(final Number threeh) { - this.three = threeh; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Rain [three=").append(this.three).append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/currentweather/Snow.java b/app/src/main/java/com/weather/information/model/currentweather/Snow.java deleted file mode 100644 index 9e97ae0..0000000 --- a/app/src/main/java/com/weather/information/model/currentweather/Snow.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.weather.information.model.currentweather; - -import java.io.Serializable; - -public class Snow implements Serializable { - private static final long serialVersionUID = 6769716772818311879L; - private Number three; - - public Number get3h() { - return this.three; - } - - public void set3h(final Number threeh) { - this.three = threeh; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Snow [three=").append(this.three).append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/currentweather/Sys.java b/app/src/main/java/com/weather/information/model/currentweather/Sys.java deleted file mode 100644 index 893be4f..0000000 --- a/app/src/main/java/com/weather/information/model/currentweather/Sys.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.weather.information.model.currentweather; - -import java.io.Serializable; - - -public class Sys implements Serializable { - private static final long serialVersionUID = 5333083785731053139L; - private String country; - private Number message; - private Number sunrise; - private Number sunset; - - public String getCountry(){ - return this.country; - } - public void setCountry(final String country){ - this.country = country; - } - public Number getMessage(){ - return this.message; - } - public void setMessage(final Number message){ - this.message = message; - } - public Number getSunrise(){ - return this.sunrise; - } - public void setSunrise(final Number sunrise){ - this.sunrise = sunrise; - } - public Number getSunset(){ - return this.sunset; - } - public void setSunset(final Number sunset){ - this.sunset = sunset; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Sys [country=").append(this.country).append(", message=") - .append(this.message).append(", sunrise=").append(this.sunrise).append(", sunset=") - .append(this.sunset).append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/currentweather/Weather.java b/app/src/main/java/com/weather/information/model/currentweather/Weather.java deleted file mode 100644 index 725fe30..0000000 --- a/app/src/main/java/com/weather/information/model/currentweather/Weather.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.weather.information.model.currentweather; - -import java.io.Serializable; - -public class Weather implements Serializable { - private static final long serialVersionUID = -34336548786316655L; - private String description; - private String icon; - private Number id; - private String main; - - public String getDescription(){ - return this.description; - } - public void setDescription(final String description){ - this.description = description; - } - public String getIcon(){ - return this.icon; - } - public void setIcon(final String icon){ - this.icon = icon; - } - public Number getId(){ - return this.id; - } - public void setId(final Number id){ - this.id = id; - } - public String getMain(){ - return this.main; - } - public void setMain(final String main){ - this.main = main; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Weather [description=").append(this.description).append(", icon=") - .append(this.icon).append(", id=").append(this.id).append(", main=") - .append(this.main).append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/currentweather/Wind.java b/app/src/main/java/com/weather/information/model/currentweather/Wind.java deleted file mode 100644 index 746554a..0000000 --- a/app/src/main/java/com/weather/information/model/currentweather/Wind.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.weather.information.model.currentweather; - -import java.io.Serializable; - -public class Wind implements Serializable { - private static final long serialVersionUID = 5495842422633674631L; - private Number deg; - private Number speed; - - public Number getDeg(){ - return this.deg; - } - public void setDeg(final Number deg){ - this.deg = deg; - } - public Number getSpeed(){ - return this.speed; - } - public void setSpeed(final Number speed){ - this.speed = speed; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Wind [deg=").append(this.deg).append(", speed=").append(this.speed) - .append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/forecastweather/City.java b/app/src/main/java/com/weather/information/model/forecastweather/City.java deleted file mode 100644 index 5460fc7..0000000 --- a/app/src/main/java/com/weather/information/model/forecastweather/City.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.weather.information.model.forecastweather; - -import java.io.Serializable; - - -public class City implements Serializable { - private static final long serialVersionUID = 3079687975077030704L; - private Coord coord; - private String country; - private Number id; - private String name; - private Number population; - - public Coord getCoord(){ - return this.coord; - } - public void setCoord(final Coord coord){ - this.coord = coord; - } - public String getCountry(){ - return this.country; - } - public void setCountry(final String country){ - this.country = country; - } - public Number getId(){ - return this.id; - } - public void setId(final Number id){ - this.id = id; - } - public String getName(){ - return this.name; - } - public void setName(final String name){ - this.name = name; - } - public Number getPopulation(){ - return this.population; - } - public void setPopulation(final Number population){ - this.population = population; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("City [coord=").append(this.coord).append(", country=").append(this.country) - .append(", id=").append(this.id).append(", name=").append(this.name) - .append(", population=").append(this.population).append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/forecastweather/Coord.java b/app/src/main/java/com/weather/information/model/forecastweather/Coord.java deleted file mode 100644 index 13e71b9..0000000 --- a/app/src/main/java/com/weather/information/model/forecastweather/Coord.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.weather.information.model.forecastweather; - -import java.io.Serializable; - -public class Coord implements Serializable { - private static final long serialVersionUID = 8069257976701986700L; - private Number lat; - private Number lon; - - public Number getLat(){ - return this.lat; - } - public void setLat(final Number lat){ - this.lat = lat; - } - public Number getLon(){ - return this.lon; - } - public void setLon(final Number lon){ - this.lon = lon; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Coord [lat=").append(this.lat).append(", lon=").append(this.lon) - .append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/forecastweather/Forecast.java b/app/src/main/java/com/weather/information/model/forecastweather/Forecast.java deleted file mode 100644 index 995113d..0000000 --- a/app/src/main/java/com/weather/information/model/forecastweather/Forecast.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.weather.information.model.forecastweather; - -import java.io.Serializable; -import java.util.List; - -/** - * Auto generated by: http://jsongen.byingtondesign.com/ - * (with my own modifications) - * - */ -public class Forecast implements Serializable { - private static final long serialVersionUID = 5095443678019686190L; - private City city; - private Number cnt; - private Number cod; - private List list; - private Number message; - - public City getCity(){ - return this.city; - } - public void setCity(final City city){ - this.city = city; - } - public Number getCnt(){ - return this.cnt; - } - public void setCnt(final Number cnt){ - this.cnt = cnt; - } - - public Number getCod() { - return this.cod; - } - - public void setCod(final Number cod) { - this.cod = cod; - } - - public List getList() { - return this.list; - } - - public void setList(final List list) { - this.list = list; - } - public Number getMessage(){ - return this.message; - } - public void setMessage(final Number message){ - this.message = message; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Forecast [city=").append(this.city).append(", cnt=") - .append(this.cnt).append(", cod=").append(this.cod).append(", list=") - .append(this.list).append(", message=").append(this.message).append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/forecastweather/List.java b/app/src/main/java/com/weather/information/model/forecastweather/List.java deleted file mode 100644 index c25cccf..0000000 --- a/app/src/main/java/com/weather/information/model/forecastweather/List.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.weather.information.model.forecastweather; - -import java.io.Serializable; - - -public class List implements Serializable { - private static final long serialVersionUID = 838468273188666785L; - private Number clouds; - private Number deg; - private Number dt; - private Number humidity; - private Number pressure; - private Number rain; - private Number snow; - private Number speed; - private Temp temp; - private java.util.List weather; - - public Number getClouds(){ - return this.clouds; - } - public void setClouds(final Number clouds){ - this.clouds = clouds; - } - public Number getDeg(){ - return this.deg; - } - public void setDeg(final Number deg){ - this.deg = deg; - } - public Number getDt(){ - return this.dt; - } - public void setDt(final Number dt){ - this.dt = dt; - } - public Number getHumidity(){ - return this.humidity; - } - public void setHumidity(final Number humidity){ - this.humidity = humidity; - } - public Number getPressure(){ - return this.pressure; - } - public void setPressure(final Number pressure){ - this.pressure = pressure; - } - public Number getRain(){ - return this.rain; - } - public void setRain(final Number rain){ - this.rain = rain; - } - public Number getSnow() { - return this.snow; - } - public void setSnow(final Number snow) { - this.snow = snow; - } - public Number getSpeed(){ - return this.speed; - } - public void setSpeed(final Number speed){ - this.speed = speed; - } - public Temp getTemp(){ - return this.temp; - } - public void setTemp(final Temp temp){ - this.temp = temp; - } - - public java.util.List getWeather() { - return this.weather; - } - - public void setWeather(final java.util.List weather) { - this.weather = weather; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("List [clouds=").append(this.clouds).append(", deg=").append(this.deg) - .append(", dt=").append(this.dt).append(", humidity=").append(this.humidity) - .append(", pressure=").append(this.pressure).append(", rain=").append(this.rain) - .append(", snow=").append(this.snow).append(", speed=").append(this.speed) - .append(", temp=").append(this.temp).append(", weather=").append(this.weather) - .append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/forecastweather/Temp.java b/app/src/main/java/com/weather/information/model/forecastweather/Temp.java deleted file mode 100644 index e7f361e..0000000 --- a/app/src/main/java/com/weather/information/model/forecastweather/Temp.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.weather.information.model.forecastweather; - -import java.io.Serializable; - -public class Temp implements Serializable { - private static final long serialVersionUID = -7614799035018271127L; - private Number day; - private Number eve; - private Number max; - private Number min; - private Number morn; - private Number night; - - public Number getDay(){ - return this.day; - } - public void setDay(final Number day){ - this.day = day; - } - public Number getEve(){ - return this.eve; - } - public void setEve(final Number eve){ - this.eve = eve; - } - public Number getMax(){ - return this.max; - } - public void setMax(final Number max){ - this.max = max; - } - public Number getMin(){ - return this.min; - } - public void setMin(final Number min){ - this.min = min; - } - public Number getMorn(){ - return this.morn; - } - public void setMorn(final Number morn){ - this.morn = morn; - } - public Number getNight(){ - return this.night; - } - public void setNight(final Number night){ - this.night = night; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Temp [day=").append(this.day).append(", eve=").append(this.eve) - .append(", max=").append(this.max).append(", min=").append(this.min) - .append(", morn=").append(this.morn).append(", night=").append(this.night) - .append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/model/forecastweather/Weather.java b/app/src/main/java/com/weather/information/model/forecastweather/Weather.java deleted file mode 100644 index b18354c..0000000 --- a/app/src/main/java/com/weather/information/model/forecastweather/Weather.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.weather.information.model.forecastweather; - -import java.io.Serializable; - -public class Weather implements Serializable { - private static final long serialVersionUID = -5066357704517363241L; - private String description; - private String icon; - private Number id; - private String main; - - public String getDescription(){ - return this.description; - } - public void setDescription(final String description){ - this.description = description; - } - public String getIcon(){ - return this.icon; - } - public void setIcon(final String icon){ - this.icon = icon; - } - public Number getId(){ - return this.id; - } - public void setId(final Number id){ - this.id = id; - } - public String getMain(){ - return this.main; - } - public void setMain(final String main){ - this.main = main; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Weather [description=").append(this.description).append(", icon=") - .append(this.icon).append(", id=").append(this.id).append(", main=") - .append(this.main).append("]"); - return builder.toString(); - } -} diff --git a/app/src/main/java/com/weather/information/notification/NotificationIntentService.java b/app/src/main/java/com/weather/information/notification/NotificationIntentService.java deleted file mode 100644 index b926149..0000000 --- a/app/src/main/java/com/weather/information/notification/NotificationIntentService.java +++ /dev/null @@ -1,232 +0,0 @@ -package com.weather.information.notification; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.Locale; - -import org.apache.http.client.ClientProtocolException; - -import android.app.IntentService; -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Intent; -import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.http.AndroidHttpClient; -import android.preference.PreferenceManager; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.NotificationManagerCompat; -import android.support.v4.app.TaskStackBuilder; -import android.util.Log; -import android.widget.RemoteViews; - -import com.fasterxml.jackson.core.JsonParseException; -import com.weather.information.R; -import com.weather.information.activity.WeatherTabsActivity; -import com.weather.information.httpclient.CustomHTTPClient; -import com.weather.information.model.DatabaseQueries; -import com.weather.information.model.WeatherLocation; -import com.weather.information.model.currentweather.Current; -import com.weather.information.parser.JPOSWeatherParser; -import com.weather.information.service.IconsList; -import com.weather.information.service.ServiceParser; - - -public class NotificationIntentService extends IntentService { - private static final String TAG = "NotificationIntentService"; - - - public NotificationIntentService() { - super("NIS-Thread"); - } - - @Override - protected void onHandleIntent(final Intent intent) { - final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext()); - final WeatherLocation weatherLocation = query.queryDataBase(); - - if (weatherLocation != null) { - final ServiceParser weatherService = new ServiceParser(new JPOSWeatherParser()); - final CustomHTTPClient HTTPClient = new CustomHTTPClient( - AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")); - - Current current = null; - try { - current = this.doInBackgroundThrowable(weatherLocation, HTTPClient, weatherService); - - } catch (final JsonParseException e) { - Log.e(TAG, "doInBackground exception: ", e); - } catch (final ClientProtocolException e) { - Log.e(TAG, "doInBackground exception: ", e); - } catch (final MalformedURLException e) { - Log.e(TAG, "doInBackground exception: ", e); - } catch (final URISyntaxException e) { - Log.e(TAG, "doInBackground exception: ", e); - } catch (final IOException e) { - // logger infrastructure swallows UnknownHostException :/ - Log.e(TAG, "doInBackground exception: " + e.getMessage(), e); - } finally { - HTTPClient.close(); - } - - if (current != null) { - this.showNotification(current, weatherLocation); - } - } - } - - private Current doInBackgroundThrowable(final WeatherLocation weatherLocation, - final CustomHTTPClient HTTPClient, final ServiceParser weatherService) - throws ClientProtocolException, MalformedURLException, URISyntaxException, - JsonParseException, IOException { - - final String APIVersion = this.getResources().getString(R.string.api_version); - - final String urlAPI = this.getResources().getString(R.string.uri_api_weather_today); - final String url = weatherService.createURIAPICurrent(urlAPI, APIVersion, - weatherLocation.getLatitude(), weatherLocation.getLongitude()); - final String urlWithoutCache = url.concat("&time=" + System.currentTimeMillis()); - final String jsonData = HTTPClient.retrieveDataAsString(new URL(urlWithoutCache)); - - return weatherService.retrieveCurrentFromJPOS(jsonData); - } - - private interface UnitsConversor { - - public double doConversion(final double value); - } - - private void showNotification(final Current current, final WeatherLocation weatherLocation) { - final SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(this.getApplicationContext()); - - // TODO: repeating the same code in Overview, Specific and Current!!! - // 1. Update units of measurement. - // 1.1 Temperature - String tempSymbol; - UnitsConversor tempUnitsConversor; - final String keyPreference = this.getApplicationContext().getString(R.string.weather_preferences_notifications_temperature_key); - final String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); - final String unitsPreferenceValue = sharedPreferences.getString( - keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); - if (unitsPreferenceValue.equals(values[0])) { - tempSymbol = values[0]; - tempUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return value - 273.15; - } - - }; - } else if (unitsPreferenceValue.equals(values[1])) { - tempSymbol = values[1]; - tempUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return (value * 1.8) - 459.67; - } - - }; - } else { - tempSymbol = values[2]; - tempUnitsConversor = new UnitsConversor(){ - - @Override - public double doConversion(final double value) { - return value; - } - - }; - } - - - // 2. Formatters - final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); - tempFormatter.applyPattern("#####.#####"); - - - // 3. Prepare data for RemoteViews. - String tempMax = ""; - if (current.getMain().getTemp_max() != null) { - double conversion = (Double) current.getMain().getTemp_max(); - conversion = tempUnitsConversor.doConversion(conversion); - tempMax = tempFormatter.format(conversion) + tempSymbol; - } - String tempMin = ""; - if (current.getMain().getTemp_min() != null) { - double conversion = (Double) current.getMain().getTemp_min(); - conversion = tempUnitsConversor.doConversion(conversion); - tempMin = tempFormatter.format(conversion) + tempSymbol; - } - Bitmap picture; - if ((current.getWeather().size() > 0) - && (current.getWeather().get(0).getIcon() != null) - && (IconsList.getIcon(current.getWeather().get(0).getIcon()) != null)) { - final String icon = current.getWeather().get(0).getIcon(); - picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon) - .getResourceDrawable()); - } else { - picture = BitmapFactory.decodeResource(this.getResources(), - R.drawable.weather_severe_alert); - } - final String city = weatherLocation.getCity(); - final String country = weatherLocation.getCountry(); - - // 4. Insert data in RemoteViews. - final RemoteViews remoteView = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.notification); - remoteView.setImageViewBitmap(R.id.weather_notification_image, picture); - remoteView.setTextViewText(R.id.weather_notification_temperature_max, tempMax); - remoteView.setTextViewText(R.id.weather_notification_temperature_min, tempMin); - remoteView.setTextViewText(R.id.weather_notification_city, city); - remoteView.setTextViewText(R.id.weather_notification_country, country); - - // 5. Activity launcher. - final Intent resultIntent = new Intent(this.getApplicationContext(), WeatherTabsActivity.class); - // The PendingIntent to launch our activity if the user selects this notification -// final PendingIntent contentIntent = PendingIntent.getActivity( -// this.getApplicationContext(), 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT); - // The stack builder object will contain an artificial back stack for the started Activity. - // This ensures that navigating backward from the Activity leads out of - // your application to the Home screen. - final TaskStackBuilder stackBuilder = TaskStackBuilder.create(this.getApplicationContext()); - // Adds the back stack for the Intent (but not the Intent itself) - stackBuilder.addParentStack(WeatherTabsActivity.class); - // Adds the Intent that starts the Activity to the top of the stack - stackBuilder.addNextIntent(resultIntent); - final PendingIntent resultPendingIntent = - stackBuilder.getPendingIntent( - 0, - PendingIntent.FLAG_UPDATE_CURRENT - ); - - final NotificationManagerCompat notificationManager = - NotificationManagerCompat.from(this.getApplicationContext()); - - - // 6. Create notification. - final NotificationCompat.Builder notificationBuilder = - new NotificationCompat.Builder(this.getApplicationContext()) - .setContent(remoteView) - .setSmallIcon(R.drawable.ic_launcher) - .setAutoCancel(true) - .setLocalOnly(true) - .setWhen(System.currentTimeMillis()) - .setContentIntent(resultPendingIntent) - .setPriority(NotificationCompat.PRIORITY_DEFAULT); - - final Notification notification = notificationBuilder.build(); - notification.flags |= Notification.FLAG_AUTO_CANCEL; - - // Send the notification. - // Sets an ID for the notification, so it can be updated (just in case) - int notifyID = 1; - notificationManager.notify(notifyID, notification); - } -} diff --git a/app/src/main/java/com/weather/information/parser/IJPOSParser.java b/app/src/main/java/com/weather/information/parser/IJPOSParser.java deleted file mode 100644 index 8afe433..0000000 --- a/app/src/main/java/com/weather/information/parser/IJPOSParser.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.weather.information.parser; - -import com.fasterxml.jackson.core.JsonParseException; -import com.weather.information.model.currentweather.Current; -import com.weather.information.model.forecastweather.Forecast; - -import java.io.IOException; - - -public interface IJPOSParser { - - public Current retrieveCurrenFromJPOS(final String jsonData) - throws JsonParseException, IOException; - - public Forecast retrieveForecastFromJPOS(final String jsonData) - throws JsonParseException, IOException; -} diff --git a/app/src/main/java/com/weather/information/parser/JPOSWeatherParser.java b/app/src/main/java/com/weather/information/parser/JPOSWeatherParser.java deleted file mode 100644 index 0506f94..0000000 --- a/app/src/main/java/com/weather/information/parser/JPOSWeatherParser.java +++ /dev/null @@ -1,405 +0,0 @@ -package com.weather.information.parser; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; -import com.weather.information.model.currentweather.Clouds; -import com.weather.information.model.currentweather.Current; -import com.weather.information.model.currentweather.Main; -import com.weather.information.model.currentweather.Rain; -import com.weather.information.model.currentweather.Snow; -import com.weather.information.model.currentweather.Sys; -import com.weather.information.model.currentweather.Wind; -import com.weather.information.model.forecastweather.City; -import com.weather.information.model.forecastweather.Forecast; -import com.weather.information.model.forecastweather.Temp; - -import java.io.IOException; -import java.util.ArrayList; - -public class JPOSWeatherParser implements IJPOSParser { - - @Override - public Current retrieveCurrenFromJPOS(final String jsonData) - throws JsonParseException, IOException { - final JsonFactory f = new JsonFactory(); - - final Current currentWeatherData = new Current(); - currentWeatherData.setClouds(new Clouds()); - currentWeatherData.setCoord(new com.weather.information.model.currentweather.Coord()); - currentWeatherData.setMain(new Main()); - currentWeatherData.setRain(new Rain()); - currentWeatherData.setSys(new Sys()); - currentWeatherData.setSnow(new Snow()); - currentWeatherData - .setWeather(new ArrayList()); - currentWeatherData.setWind(new Wind()); - final JsonParser jParser = f.createParser(jsonData); - - this.getCurrentWeatherData(currentWeatherData, jParser); - - return currentWeatherData; - } - - @Override - public Forecast retrieveForecastFromJPOS(final String jsonData) - throws JsonParseException, IOException { - final JsonFactory f = new JsonFactory(); - - final Forecast forecastWeatherData = new Forecast(); - forecastWeatherData - .setList(new ArrayList(15)); - final City city = new City(); - city.setCoord(new com.weather.information.model.forecastweather.Coord()); - forecastWeatherData.setCity(city); - final JsonParser jParser = f.createParser(jsonData); - - this.getForecastWeatherData(forecastWeatherData, jParser); - - return forecastWeatherData; - } - - private void getCurrentWeatherData(final Current currentWeatherData, - final JsonParser jParser) throws JsonParseException, IOException { - if (jParser.nextToken() == JsonToken.START_OBJECT) { - - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String fieldname = jParser.getCurrentName(); - final JsonToken nextToken = jParser.nextToken(); - if (nextToken == JsonToken.START_OBJECT) { - this.getCurrentWeatherDataObjects(currentWeatherData, jParser, fieldname); - } - if (nextToken == JsonToken.START_ARRAY) { - JsonToken tokenNext = jParser.nextToken(); - while (tokenNext != JsonToken.END_ARRAY) { - if (tokenNext == JsonToken.START_OBJECT) { - this.getCurrentWeatherDataObjects(currentWeatherData, jParser, fieldname); - } - tokenNext = jParser.nextToken(); - } - } - if ((nextToken == JsonToken.VALUE_NUMBER_INT) - || (nextToken == JsonToken.VALUE_STRING)) { - this.getCurrentWeatherDataObjects(currentWeatherData, jParser, fieldname); - } - } - } - } - - private void getCurrentWeatherDataObjects(final Current currentWeatherData, - final JsonParser jParser, final String fieldname) throws JsonParseException, - IOException { - if ("coord".equals(fieldname)) { - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - if ("lon".equals(namefield)) { - currentWeatherData.getCoord().setLon(jParser.getDoubleValue()); - } - if ("lat".equals(namefield)) { - currentWeatherData.getCoord().setLat(jParser.getDoubleValue()); - } - } - } - if ("sys".equals(fieldname)) { - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - if ("message".equals(namefield)) { - currentWeatherData.getSys().setMessage(jParser.getDoubleValue()); - } - if ("country".equals(namefield)) { - currentWeatherData.getSys().setCountry(jParser.getValueAsString()); - } - if ("sunrise".equals(namefield)) { - currentWeatherData.getSys().setSunrise(jParser.getValueAsLong()); - } - if ("sunset".equals(namefield)) { - currentWeatherData.getSys().setSunset(jParser.getValueAsLong()); - } - } - } - if ("weather".equals(fieldname)) { - final com.weather.information.model.currentweather.Weather weather = new com.weather.information.model.currentweather.Weather(); - currentWeatherData.getWeather().add(weather); - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - if ("id".equals(namefield)) { - weather.setId(jParser.getIntValue()); - } - if ("main".equals(namefield)) { - weather.setMain(jParser.getText()); - } - if ("description".equals(namefield)) { - weather.setDescription(jParser.getText()); - } - if ("icon".equals(namefield)) { - weather.setIcon(jParser.getText()); - } - - } - } - if ("base".equals(fieldname)) { - currentWeatherData.setBase(jParser.getText()); - } - if ("main".equals(fieldname)) { - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - if ("temp".equals(namefield)) { - currentWeatherData.getMain().setTemp(jParser.getDoubleValue()); - } - if ("temp_min".equals(namefield)) { - currentWeatherData.getMain().setTemp_min(jParser.getDoubleValue()); - } - if ("temp_max".equals(namefield)) { - currentWeatherData.getMain().setTemp_max(jParser.getDoubleValue()); - } - if ("pressure".equals(namefield)) { - currentWeatherData.getMain().setPressure(jParser.getDoubleValue()); - } - if ("sea_level".equals(namefield)) { - currentWeatherData.getMain().setSea_level(jParser.getDoubleValue()); - } - if ("grnd_level".equals(namefield)) { - currentWeatherData.getMain().setGrnd_level(jParser.getDoubleValue()); - } - if ("humidity".equals(namefield)) { - currentWeatherData.getMain().setHumidity(jParser.getDoubleValue()); - } - } - } - if ("wind".equals(fieldname)) { - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - if ("speed".equals(namefield)) { - currentWeatherData.getWind().setSpeed(jParser.getDoubleValue()); - } - if ("deg".equals(namefield)) { - currentWeatherData.getWind().setDeg(jParser.getDoubleValue()); - } - } - } - if ("clouds".equals(fieldname)) { - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - if ("all".equals(namefield)) { - currentWeatherData.getClouds().setAll(jParser.getDoubleValue()); - } - } - } - if ("dt".equals(fieldname)) { - currentWeatherData.setDt(jParser.getLongValue()); - } - if ("rain".equals(fieldname)) { - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - if ("3h".equals(namefield)) { - currentWeatherData.getRain().set3h(jParser.getDoubleValue()); - } - } - } - if ("snow".equals(fieldname)) { - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - if ("3h".equals(namefield)) { - currentWeatherData.getSnow().set3h(jParser.getDoubleValue()); - } - } - } - if ("id".equals(fieldname)) { - currentWeatherData.setId(jParser.getLongValue()); - } - if ("name".equals(fieldname)) { - currentWeatherData.setName(jParser.getText()); - } - if ("cod".equals(fieldname)) { - currentWeatherData.setCod(jParser.getIntValue()); - } - } - - private void getForecastWeatherData(final Forecast forecastWeatherData, - final JsonParser jParser) throws JsonParseException, IOException { - if (jParser.nextToken() == JsonToken.START_OBJECT) { - - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String fieldname = jParser.getCurrentName(); - final JsonToken nextToken = jParser.nextToken(); - if (nextToken == JsonToken.START_OBJECT) { - this.getForecastWeatherDataObjects(forecastWeatherData, jParser, fieldname); - } - if (nextToken == JsonToken.START_ARRAY) { - JsonToken tokenNext = jParser.nextToken(); - while (tokenNext != JsonToken.END_ARRAY) { - if (tokenNext == JsonToken.START_OBJECT) { - this.getForecastWeatherDataObjects(forecastWeatherData, jParser, fieldname); - } - tokenNext = jParser.nextToken(); - } - } - if ((nextToken == JsonToken.VALUE_NUMBER_INT) - || (nextToken == JsonToken.VALUE_STRING)) { - this.getForecastWeatherDataObjects(forecastWeatherData, jParser, fieldname); - } - } - } - } - - private void getForecastWeatherDataObjects(final Forecast forecastWeatherData, - final JsonParser jParser, final String fieldname) throws JsonParseException, - IOException { - - if ("cod".equals(fieldname)) { - final String stringCod = jParser.getText(); - forecastWeatherData.setCod(Long.valueOf(stringCod)); - } - if ("message".equals(fieldname)) { - forecastWeatherData.setMessage(jParser.getDoubleValue()); - } - if ("city".equals(fieldname)) { - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - final JsonToken nextToken = jParser.nextToken(); // move to - // value - if ("id".equals(namefield)) { - forecastWeatherData.getCity().setId(jParser.getLongValue()); - } - if ("name".equals(namefield)) { - forecastWeatherData.getCity().setName(jParser.getText()); - } - if ("coord".equals(namefield)) { - if (nextToken == JsonToken.START_OBJECT) { - this.getForecastWeatherDataObjects(forecastWeatherData, jParser, namefield); - } - } - if ("country".equals(namefield)) { - forecastWeatherData.getCity().setCountry(jParser.getText()); - } - if ("population".equals(namefield)) { - forecastWeatherData.getCity().setPopulation(jParser.getLongValue()); - } - } - } - if ("cnt".equals(fieldname)) { - forecastWeatherData.setCnt(jParser.getIntValue()); - } - if ("coord".equals(fieldname)) { - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - if ("lon".equals(namefield)) { - forecastWeatherData.getCity().getCoord().setLon(jParser.getDoubleValue()); - } - if ("lat".equals(namefield)) { - forecastWeatherData.getCity().getCoord().setLat(jParser.getDoubleValue()); - } - } - } - if ("list".equals(fieldname)) { - final com.weather.information.model.forecastweather.List list = new com.weather.information.model.forecastweather.List(); - list.setTemp(new Temp()); - list.setWeather(new ArrayList()); - forecastWeatherData.getList().add(list); - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - final JsonToken nextToken = jParser.nextToken(); // move to - // value - if ("dt".equals(namefield)) { - list.setDt(jParser.getLongValue()); - } - if ("temp".equals(namefield)) { - if (nextToken == JsonToken.START_OBJECT) { - this.getForecastWeatherDataObjects(forecastWeatherData, jParser, namefield); - } - } - if ("pressure".equals(namefield)) { - list.setPressure(jParser.getDoubleValue()); - } - if ("humidity".equals(namefield)) { - list.setHumidity(jParser.getDoubleValue()); - } - if ("weather".equals(namefield)) { - if (nextToken == JsonToken.START_ARRAY) { - JsonToken tokenNext = jParser.nextToken(); - while (tokenNext != JsonToken.END_ARRAY) { - if (tokenNext == JsonToken.START_OBJECT) { - this.getForecastWeatherDataObjects(forecastWeatherData, jParser, - namefield); - } - tokenNext = jParser.nextToken(); - } - } - } - if ("speed".equals(namefield)) { - list.setSpeed(jParser.getDoubleValue()); - } - if ("deg".equals(namefield)) { - list.setDeg(jParser.getDoubleValue()); - } - if ("clouds".equals(namefield)) { - list.setClouds(jParser.getDoubleValue()); - } - if ("rain".equals(namefield)) { - list.setRain(jParser.getDoubleValue()); - } - } - } - if ("temp".equals(fieldname)) { - final com.weather.information.model.forecastweather.List list = forecastWeatherData - .getList().get( - (forecastWeatherData.getList().size() - 1)); - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - if ("day".equals(namefield)) { - list.getTemp().setDay(jParser.getDoubleValue()); - } - if ("min".equals(namefield)) { - list.getTemp().setMin(jParser.getDoubleValue()); - } - if ("max".equals(namefield)) { - list.getTemp().setMax(jParser.getDoubleValue()); - } - if ("night".equals(namefield)) { - list.getTemp().setNight(jParser.getDoubleValue()); - } - if ("eve".equals(namefield)) { - list.getTemp().setEve(jParser.getDoubleValue()); - } - if ("morn".equals(namefield)) { - list.getTemp().setMorn(jParser.getDoubleValue()); - } - } - } - if ("weather".equals(fieldname)) { - final com.weather.information.model.forecastweather.List list = forecastWeatherData - .getList().get( - (forecastWeatherData.getList().size() - 1)); - final com.weather.information.model.forecastweather.Weather weather = new com.weather.information.model.forecastweather.Weather(); - while (jParser.nextToken() != JsonToken.END_OBJECT) { - final String namefield = jParser.getCurrentName(); - jParser.nextToken(); // move to value - - if ("id".equals(namefield)) { - weather.setId(jParser.getIntValue()); - } - if ("main".equals(namefield)) { - weather.setMain(jParser.getText()); - } - if ("description".equals(namefield)) { - weather.setDescription(jParser.getText()); - } - if ("icon".equals(namefield)) { - weather.setIcon(jParser.getText()); - } - } - list.getWeather().add(weather); - } - } -} diff --git a/app/src/main/java/com/weather/information/service/IconsList.java b/app/src/main/java/com/weather/information/service/IconsList.java deleted file mode 100644 index db2406a..0000000 --- a/app/src/main/java/com/weather/information/service/IconsList.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.weather.information.service; - -import com.weather.information.R; - -import java.util.HashMap; -import java.util.Map; - -public enum IconsList { - ICON_01d("01d") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_clear; - } - }, - // TODO: I am sometimes receiving this code, there is no documentation about it on the - // openweathermap site.... But it exists!!! Some day, try to find out more information about it. - // see: http://openweathermap.org/img/w/01dd.png - ICON_01dd("01dd") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_clear; - } - }, - ICON_01n("01n") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_clear_night; - } - }, - ICON_02d("02d") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_few_clouds; - } - }, - ICON_02n("02n") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_few_clouds_night; - } - }, - ICON_03d("03d") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_few_clouds; - } - }, - ICON_03n("03n") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_few_clouds; - } - }, - ICON_04d("04d") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_overcast; - } - }, - ICON_04n("04n") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_overcast; - } - }, - ICON_09d("09d") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_showers; - } - }, - ICON_09n("09n") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_showers; - } - }, - ICON_10d("10d") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_showers_scattered; - } - }, - ICON_10n("10n") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_showers_scattered; - } - }, - ICON_11d("11d") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_storm; - } - }, - ICON_11n("11n") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_storm; - } - }, - ICON_13d("13d") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_snow; - } - }, - ICON_13n("13n") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_snow; - } - }, - ICON_50d("50d") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_fog; - } - }, - ICON_50n("50n") { - @Override - public int getResourceDrawable() { - return R.drawable.weather_fog; - } - }; - - private final String icon; - // Map with every enum constant. Class variable initializer. JLS§12.4.2 - // Executed in textual order. - private static final Map codeMap = new HashMap(); - - // Static initializer. JLS§12.4.2 Executed in textual order. - static { - for (final IconsList code : IconsList.values()) { - codeMap.put(code.getIcon(), code); - } - } - - private IconsList(final String icon) { - this.icon = icon; - } - - public static final IconsList getIcon(final String icon) { - return codeMap.get(icon); - } - - private String getIcon() { - return this.icon; - } - - public abstract int getResourceDrawable(); -} diff --git a/app/src/main/java/com/weather/information/service/PermanentStorage.java b/app/src/main/java/com/weather/information/service/PermanentStorage.java deleted file mode 100644 index 9df970e..0000000 --- a/app/src/main/java/com/weather/information/service/PermanentStorage.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.weather.information.service; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.StreamCorruptedException; -import java.text.MessageFormat; - -import android.content.Context; -import android.util.Log; - -import com.weather.information.model.currentweather.Current; -import com.weather.information.model.forecastweather.Forecast; - - -public class PermanentStorage { - private static final String TAG = "PermanentStorage"; - private static final String CURRENT_DATA_FILE = "current.file"; - private static final String FORECAST_DATA_FILE = "forecast.file"; - private static final String WIDGET_CURRENT_DATA_FILE = "current.{0}.file"; - private final Context context; - - public PermanentStorage(final Context context) { - this.context = context; - } - - public void saveCurrent(final Current current) { - - try { - this.saveObject(CURRENT_DATA_FILE, current); - } catch (FileNotFoundException e) { - Log.e(TAG, "saveCurrent exception: ", e); - } catch (IOException e) { - Log.e(TAG, "saveCurrent exception: ", e); - } - } - - public Current getCurrent() { - - try { - return (Current) this.getObject(CURRENT_DATA_FILE); - } catch (final StreamCorruptedException e) { - Log.e(TAG, "getCurrent exception: ", e); - } catch (final FileNotFoundException e) { - Log.e(TAG, "getCurrent exception: ", e); - } catch (final IOException e) { - Log.e(TAG, "getCurrent exception: ", e); - } catch (final ClassNotFoundException e) { - Log.e(TAG, "getCurrent exception: ", e); - } - - return null; - } - - public void saveWidgetCurrentData(final Current current, final int appWidgetId) { - - final String fileName = MessageFormat.format(WIDGET_CURRENT_DATA_FILE, appWidgetId); - try { - this.saveObject(fileName, current); - } catch (FileNotFoundException e) { - Log.e(TAG, "saveWidgetCurrentData exception: ", e); - } catch (IOException e) { - Log.e(TAG, "saveWidgetCurrentData exception: ", e); - } - } - - public Current getWidgetCurrentData(final int appWidgetId) { - - final String fileName = MessageFormat.format(WIDGET_CURRENT_DATA_FILE, appWidgetId); - try { - return (Current) this.getObject(fileName); - } catch (final StreamCorruptedException e) { - Log.e(TAG, "getWidgetCurrentData exception: ", e); - } catch (final FileNotFoundException e) { - Log.e(TAG, "getWidgetCurrentData exception: ", e); - } catch (final IOException e) { - Log.e(TAG, "getWidgetCurrentData exception: ", e); - } catch (final ClassNotFoundException e) { - Log.e(TAG, "getWidgetCurrentData exception: ", e); - } - - return null; - } - - public void removeWidgetCurrentData(final int appWidgetId) { - - final String fileName = MessageFormat.format(WIDGET_CURRENT_DATA_FILE, appWidgetId); - - try { - this.removeFile(fileName); - } catch (final IOException e) { - Log.e(TAG, "removeWidgetCurrentData exception: ", e); - } - } - - public void saveForecast(final Forecast forecast) { - - try { - this.saveObject(FORECAST_DATA_FILE, forecast); - } catch (FileNotFoundException e) { - Log.e(TAG, "saveForecast exception: ", e); - } catch (IOException e) { - Log.e(TAG, "saveForecast exception: ", e); - } - } - - public Forecast getForecast() { - - try { - return (Forecast) this.getObject(FORECAST_DATA_FILE); - } catch (final StreamCorruptedException e) { - Log.e(TAG, "getForecast exception: ", e); - } catch (final FileNotFoundException e) { - Log.e(TAG, "getForecast exception: ", e); - } catch (final IOException e) { - Log.e(TAG, "getForecast exception: ", e); - } catch (final ClassNotFoundException e) { - Log.e(TAG, "getForecast exception: ", e); - } - - return null; - } - - private void saveObject(final String fileName, final Object objectToStore) - throws FileNotFoundException, IOException { - final String temporaryFileName = fileName.concat(".tmp"); - - final FileOutputStream tmpPersistFile = this.context.openFileOutput( - temporaryFileName, Context.MODE_PRIVATE); - try { - final ObjectOutputStream oos = new ObjectOutputStream(tmpPersistFile); - try { - oos.writeObject(objectToStore); - - // Don't fear the fsync! - // http://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/ - tmpPersistFile.flush(); - tmpPersistFile.getFD().sync(); - } finally { - oos.close(); - } - } finally { - tmpPersistFile.close(); - } - - this.renameFile(temporaryFileName, fileName); - } - - private Object getObject(final String fileName) throws StreamCorruptedException, FileNotFoundException, - IOException, ClassNotFoundException { - final InputStream persistFile = this.context.openFileInput(fileName); - try { - final ObjectInputStream ois = new ObjectInputStream(persistFile); - try { - return ois.readObject(); - } finally { - ois.close(); - } - } finally { - persistFile.close(); - } - } - - private void renameFile(final String fromFileName, final String toFileName) throws IOException { - final File filesDir = this.context.getFilesDir(); - final File fromFile = new File(filesDir, fromFileName); - final File toFile = new File(filesDir, toFileName); - if (!fromFile.renameTo(toFile)) { - if (!fromFile.delete()) { - throw new IOException("PermanentStorage, delete file error"); - } - throw new IOException("PermanentStorage, rename file error"); - } - } - - private void removeFile(final String fileName) throws IOException { - final File filesDir = this.context.getFilesDir(); - final File file = new File(filesDir, fileName); - - if (!file.delete()) { - throw new IOException("PermanentStorage, remove file error"); - } - } -} - diff --git a/app/src/main/java/com/weather/information/service/ServiceParser.java b/app/src/main/java/com/weather/information/service/ServiceParser.java deleted file mode 100644 index b3dba8d..0000000 --- a/app/src/main/java/com/weather/information/service/ServiceParser.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.weather.information.service; - -import com.fasterxml.jackson.core.JsonParseException; -import com.weather.information.model.currentweather.Current; -import com.weather.information.model.forecastweather.Forecast; -import com.weather.information.parser.IJPOSParser; - -import java.io.IOException; -import java.text.MessageFormat; -import java.util.Locale; - - -public class ServiceParser { - private final IJPOSParser JPOSParser; - - public ServiceParser(final IJPOSParser JPOSWeatherParser) { - this.JPOSParser = JPOSWeatherParser; - } - - public Current retrieveCurrentFromJPOS(final String jsonData) - throws JsonParseException, IOException { - return this.JPOSParser.retrieveCurrenFromJPOS(jsonData); - } - - public Forecast retrieveForecastFromJPOS(final String jsonData) - throws JsonParseException, IOException { - return this.JPOSParser.retrieveForecastFromJPOS(jsonData); - } - - public String createURIAPIForecast(final String urlAPI, final String APIVersion, - final double latitude, final double longitude, final String resultsNumber) { - - final MessageFormat formatURIAPI = new MessageFormat(urlAPI, Locale.US); - final Object[] values = new Object[4]; - values[0] = APIVersion; - values[1] = latitude; - values[2] = longitude; - values[3] = resultsNumber; - - return formatURIAPI.format(values); - } - - public String createURIAPICurrent(final String urlAPI, final String APIVersion, - final double latitude, final double longitude) { - - final MessageFormat formatURIAPI = new MessageFormat(urlAPI, Locale.US); - final Object[] values = new Object[3]; - values[0] = APIVersion; - values[1] = latitude; - values[2] = longitude; - - return formatURIAPI.format(values); - } - - public String createURIAPIicon(final String icon, final String urlAPI) { - - final MessageFormat formatURIAPI = new MessageFormat(urlAPI, Locale.US); - final Object[] values = new Object[1]; - values[0] = icon; - - return formatURIAPI.format(values); - } - -} diff --git a/app/src/main/java/com/weather/information/widget/WidgetConfigure.java b/app/src/main/java/com/weather/information/widget/WidgetConfigure.java deleted file mode 100644 index d639e07..0000000 --- a/app/src/main/java/com/weather/information/widget/WidgetConfigure.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.weather.information.widget; - -import android.app.ActionBar; -import android.app.Activity; -import android.appwidget.AppWidgetManager; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.view.View; -import android.widget.CompoundButton; -import android.widget.Spinner; -import android.widget.Switch; - -import com.weather.information.R; - -public class WidgetConfigure extends Activity { - private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; - - @Override - public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Find the widget id from the intent. - final Intent intent = getIntent(); - final Bundle extras = intent.getExtras(); - boolean isActionFromUser = false; - - if (extras != null) { - mAppWidgetId = extras.getInt( - AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); - - isActionFromUser = extras.getBoolean("actionFromUser", false); - } - - // If they gave us an intent without the widget id, just bail. - if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { - this.finish(); - } - - if (!isActionFromUser) { - // Set the result to CANCELED. This will cause the widget host to cancel - // out of the widget placement if they press the back button. - this.setResult(RESULT_CANCELED); - } - - // Set the view layout resource to use. - this.setContentView(R.layout.appwidget_configure); - - /******************* Show/hide country field *******************/ - String keyPreference = this.getApplicationContext().getString( - R.string.widget_preferences_country_switch_key); - String realKeyPreference = keyPreference + "_" + mAppWidgetId; - - // What was saved to permanent storage (or default values if it is the first time) - final boolean isShowCountry = this.getSharedPreferences("WIDGET_PREFERENCES", Context.MODE_PRIVATE) - .getBoolean(realKeyPreference, false); - - // What is shown on the screen - final Switch countrySwitch = (Switch) this.findViewById(R.id.weather_appwidget_configure_country); - countrySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){ - @Override - public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) { - if (isChecked) { - buttonView.setText(WidgetConfigure.this.getString(R.string.widget_preferences_country_switch_on_summary)); - } else { - buttonView.setText(WidgetConfigure.this.getString(R.string.widget_preferences_country_switch_off_summary)); - } - } - }); - if (isShowCountry) { - countrySwitch.setChecked(true); - countrySwitch.setText(this.getString(R.string.widget_preferences_country_switch_on_summary)); - } else { - countrySwitch.setChecked(false); - countrySwitch.setText(this.getString(R.string.widget_preferences_country_switch_off_summary)); - } - - /********************* Temperature units **********************/ - keyPreference = this.getApplicationContext().getString( - R.string.widget_preferences_temperature_units_key); - realKeyPreference = keyPreference + "_" + mAppWidgetId; - - // What was saved to permanent storage (or default values if it is the first time) - final int tempValue = this.getSharedPreferences("WIDGET_PREFERENCES", Context.MODE_PRIVATE).getInt(realKeyPreference, 0); - - // What is shown on the screen - final Spinner tempUnits = (Spinner) this.findViewById(R.id.weather_appwidget_configure_temperature_units); - tempUnits.setSelection(tempValue); - - /** - * android:saveEnabled - * Controls whether the saving of this view's state is enabled (that is, whether its onSaveInstanceState() method will be called). - * - * After onStart the onSaveInstanceState method will be called for every widget, so - * I do not need to do anything else to retrieve the UI's state after changing orientation. - * - * I do not know if this is a good pattern, it does not look like that. I guess, I should use - * on Resume instead of onCreate/onStart and implement my own onSaveInstanceState method. - * But I am tired... - */ - } - - @Override - public void onResume() { - super.onResume(); - - final ActionBar actionBar = this.getActionBar(); - actionBar.setTitle(this.getString(R.string.widget_preferences_action_settings)); - } - - - public void onClickRefresh(final View view) { - // Push widget update to surface - WidgetProvider.refreshAppWidget(this.getApplicationContext(), mAppWidgetId); - } - - public void onClickOk(final View view) { - // Save to permanent storage - final SharedPreferences.Editor prefs = this.getSharedPreferences( - "WIDGET_PREFERENCES", - Context.MODE_PRIVATE).edit(); - - /******************* Show/hide country field *******************/ - // What is shown on the screen - final Switch countrySwitch = (Switch) this.findViewById(R.id.weather_appwidget_configure_country); - String keyPreference = this.getApplicationContext().getString( - R.string.widget_preferences_country_switch_key); - String realKeyPreference = keyPreference + "_" + mAppWidgetId; - prefs.putBoolean(realKeyPreference, countrySwitch.isChecked()); - - /********************* Temperature units **********************/ - // What is shown on the screen - final Spinner tempUnits = (Spinner) this.findViewById(R.id.weather_appwidget_configure_temperature_units); - keyPreference = this.getApplicationContext().getString( - R.string.widget_preferences_temperature_units_key); - realKeyPreference = keyPreference + "_" + mAppWidgetId; - prefs.putInt(realKeyPreference, tempUnits.getSelectedItemPosition()); - - /****************** Saving to permanent storage ***************/ - prefs.commit(); - - // Push widget update to surface with newly set prefix - WidgetProvider.updateAppWidget(this.getApplicationContext(), mAppWidgetId); - - // Make sure we pass back the original appWidgetId - final Intent resultValue = new Intent(); - resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); - this.setResult(RESULT_OK, resultValue); - finish(); - } - - public static void deletePreference(final Context context, final int appWidgetId) { - final SharedPreferences.Editor prefs = context.getApplicationContext() - .getSharedPreferences("WIDGET_PREFERENCES", Context.MODE_PRIVATE).edit(); - - /******************* Show/hide country field *******************/ - String keyPreference = context.getApplicationContext().getString( - R.string.widget_preferences_country_switch_key); - String realKeyPreference = keyPreference + "_" + appWidgetId; - prefs.remove(realKeyPreference); - - /********************* Temperature units **********************/ - keyPreference = context.getApplicationContext().getString( - R.string.widget_preferences_temperature_units_key); - realKeyPreference = keyPreference + "_" + appWidgetId; - prefs.remove(realKeyPreference); - - /****************** Updating permanent storage ***************/ - prefs.commit(); - } -} diff --git a/app/src/main/java/com/weather/information/widget/WidgetProvider.java b/app/src/main/java/com/weather/information/widget/WidgetProvider.java deleted file mode 100644 index c51d38f..0000000 --- a/app/src/main/java/com/weather/information/widget/WidgetProvider.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.weather.information.widget; - - -import android.appwidget.AppWidgetManager; -import android.appwidget.AppWidgetProvider; -import android.appwidget.AppWidgetProviderInfo; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; - -import com.weather.information.widget.service.WidgetIntentService; - -public class WidgetProvider extends AppWidgetProvider { - - @Override - public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) { - // For each widget that needs an update, get the text that we should display: - // - Create a RemoteViews object for it - // - Set the text in the RemoteViews object - // - Tell the AppWidgetManager to show that views object for the widget. - final int N = appWidgetIds.length; - for (int i=0; i 0) - && (current.getWeather().get(0).getIcon() != null) - && (IconsList.getIcon(current.getWeather().get(0).getIcon()) != null)) { - final String icon = current.getWeather().get(0).getIcon(); - picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon) - .getResourceDrawable()); - } else { - picture = BitmapFactory.decodeResource(this.getResources(), - R.drawable.weather_severe_alert); - } - final String city = weatherLocation.getCity(); - final String country = weatherLocation.getCountry(); - - // 5. Insert data in RemoteViews. - final RemoteViews remoteView = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.appwidget); - remoteView.setImageViewBitmap(R.id.weather_appwidget_image, picture); - remoteView.setTextViewText(R.id.weather_appwidget_temperature_max, tempMax); - remoteView.setTextViewText(R.id.weather_appwidget_temperature_min, tempMin); - remoteView.setTextViewText(R.id.weather_appwidget_city, city); - if (!isCountry) { - remoteView.setViewVisibility(R.id.weather_appwidget_country, View.GONE); - } else { - // TODO: It is as if Android had a view cache. If I did not set VISIBLE value, - // the country field would be gone forever... :/ - remoteView.setViewVisibility(R.id.weather_appwidget_country, View.VISIBLE); - remoteView.setTextViewText(R.id.weather_appwidget_country, country); - } - - - // 6. Activity launcher. - final Intent resultIntent = new Intent(this.getApplicationContext(), WidgetConfigure.class); - resultIntent.putExtra("actionFromUser", true); - resultIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); - // resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK ); - // From: http://stackoverflow.com/questions/4011178/multiple-instances-of-widget-only-updating-last-widget - final Uri data = Uri.withAppendedPath(Uri.parse("PAIN" + "://widget/id/") ,String.valueOf(appWidgetId)); - resultIntent.setData(data); - - final TaskStackBuilder stackBuilder = TaskStackBuilder.create(this.getApplicationContext()); - // Adds the back stack for the Intent (but not the Intent itself) - stackBuilder.addParentStack(WidgetConfigure.class); - // Adds the Intent that starts the Activity to the top of the stack - stackBuilder.addNextIntent(resultIntent); - final PendingIntent resultPendingIntent = - stackBuilder.getPendingIntent( - 0, - PendingIntent.FLAG_UPDATE_CURRENT - ); - remoteView.setOnClickPendingIntent(R.id.weather_appwidget, resultPendingIntent); -// final PendingIntent resultPendingIntent = PendingIntent.getActivity( -// this.getApplicationContext(), -// 0, -// resultIntent, -// PendingIntent.FLAG_UPDATE_CURRENT); -// remoteView.setOnClickPendingIntent(R.id.weather_appwidget, resultPendingIntent); - - return remoteView; - } - - private RemoteViews makeErrorView(final int appWidgetId) { - final RemoteViews remoteView = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.appwidget_error); - - // 6. Activity launcher. - final Intent resultIntent = new Intent(this.getApplicationContext(), WidgetConfigure.class); - resultIntent.putExtra("actionFromUser", true); - resultIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); -// resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK ); - // From: http://stackoverflow.com/questions/4011178/multiple-instances-of-widget-only-updating-last-widget - final Uri data = Uri.withAppendedPath(Uri.parse("PAIN" + "://widget/id/") ,String.valueOf(appWidgetId)); - resultIntent.setData(data); - - final TaskStackBuilder stackBuilder = TaskStackBuilder.create(this.getApplicationContext()); - // Adds the back stack for the Intent (but not the Intent itself) - stackBuilder.addParentStack(WidgetConfigure.class); - // Adds the Intent that starts the Activity to the top of the stack - stackBuilder.addNextIntent(resultIntent); - final PendingIntent resultPendingIntent = - stackBuilder.getPendingIntent( - 0, - PendingIntent.FLAG_UPDATE_CURRENT - ); - remoteView.setOnClickPendingIntent(R.id.weather_appwidget_error, resultPendingIntent); -// final PendingIntent resultPendingIntent = PendingIntent.getActivity( -// this.getApplicationContext(), -// 0, -// resultIntent, -// PendingIntent.FLAG_UPDATE_CURRENT); -// remoteView.setOnClickPendingIntent(R.id.weather_appwidget_error, resultPendingIntent); - - return remoteView; - } - - private void updateWidget(final RemoteViews remoteView, final int appWidgetId) { - - final AppWidgetManager manager = AppWidgetManager.getInstance(this.getApplicationContext()); - manager.updateAppWidget(appWidgetId, remoteView); - } - - private boolean isDataFresh(final Date lastUpdate) { - if (lastUpdate == null) { - return false; - } - - final Date currentTime = new Date(); - if (((currentTime.getTime() - lastUpdate.getTime())) < UPDATE_TIME_RATE) { - return true; - } - - return false; - } - -// private void updateWidgets(final RemoteViews remoteView) { -// -// final ComponentName widgets = new ComponentName(this.getApplicationContext(), WidgetProvider.class); -// final AppWidgetManager manager = AppWidgetManager.getInstance(this.getApplicationContext()); -// manager.updateAppWidget(widgets, remoteView); -// } -} diff --git a/app/src/main/java/name/gumartinm/weather/information/activity/AboutActivity.java b/app/src/main/java/name/gumartinm/weather/information/activity/AboutActivity.java new file mode 100644 index 0000000..d1597ff --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/activity/AboutActivity.java @@ -0,0 +1,50 @@ +package name.gumartinm.weather.information.activity; + +import android.app.ActionBar; +import android.app.Activity; +import android.content.ComponentName; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; + +import name.gumartinm.weather.information.R; + +public class AboutActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.weather_about); + } + + @Override + public void onResume() { + super.onResume(); + + final ActionBar actionBar = this.getActionBar(); + actionBar.setTitle(this.getString(R.string.weather_about_action)); + } + + public void onClickLegalInformation(final View view) { + final Intent intent = new Intent("name.gumartinm.weather.information.WEATHERINFO") + .setComponent(new ComponentName("name.gumartinm.weather.information", + "name.gumartinm.weather.information.activity.LicensesActivity")); + this.startActivity(intent); + } + + public void onClickSourceCode(final View view) { + final String url = this.getString(R.string.application_source_code_url); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + } + + public void onClickRemoteData(final View view) { + final String url = this.getString(R.string.openweahtermap_url); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + } + + public void onClickMyWeb(final View view) { + final String url = this.getString(R.string.my_url); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/activity/LicensesActivity.java b/app/src/main/java/name/gumartinm/weather/information/activity/LicensesActivity.java new file mode 100644 index 0000000..d929950 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/activity/LicensesActivity.java @@ -0,0 +1,75 @@ +package name.gumartinm.weather.information.activity; + +import android.app.ActionBar; +import android.app.Activity; +import android.os.Bundle; +import android.util.Log; +import android.webkit.WebView; + +import com.google.android.gms.common.GooglePlayServicesUtil; +import name.gumartinm.weather.information.R; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; + +public class LicensesActivity extends Activity { + private static final String TAG = "LicensesActivity"; + private WebView mWebView; + + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.weather_licenses); + + mWebView = (WebView) this.findViewById(R.id.weather_licenses); + } + + @Override + public void onResume() { + super.onResume(); + + final ActionBar actionBar = this.getActionBar(); + actionBar.setTitle(this.getString(R.string.weather_licenses_title)); + + final String googlePlayServices = GooglePlayServicesUtil.getOpenSourceSoftwareLicenseInfo(this.getApplicationContext()); + try { + final StringBuilder stringBuilder = this.loadData(); + stringBuilder.append(googlePlayServices).append("").append("").append(""); + mWebView.loadDataWithBaseURL(null, stringBuilder.toString(), "text/html", "UTF-8", null); + } catch (final UnsupportedEncodingException e) { + Log.e(TAG, "Load data error", e); + } catch (final IOException e) { + Log.e(TAG, "Load data error", e); + } + } + + private StringBuilder loadData() throws UnsupportedEncodingException, IOException { + final InputStream inputStream = this.getResources().openRawResource(R.raw.licenses); + try { + final InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8")); + try { + final BufferedReader reader = new BufferedReader(inputStreamReader); + try { + final StringBuilder stringBuilder = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + stringBuilder.append("\n"); + } + return stringBuilder; + } finally { + reader.close(); + } + } finally { + inputStreamReader.close(); + } + } finally { + inputStream.close(); + } + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/activity/MapActivity.java b/app/src/main/java/name/gumartinm/weather/information/activity/MapActivity.java new file mode 100644 index 0000000..11efcff --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/activity/MapActivity.java @@ -0,0 +1,399 @@ +package name.gumartinm.weather.information.activity; + +import android.app.ActionBar; +import android.content.Context; +import android.location.Criteria; +import android.location.Geocoder; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener; +import com.google.android.gms.maps.MapFragment; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.MarkerOptions; +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.fragment.map.MapButtonsFragment; +import name.gumartinm.weather.information.fragment.map.MapProgressFragment; +import name.gumartinm.weather.information.model.DatabaseQueries; +import name.gumartinm.weather.information.model.WeatherLocation; + + +public class MapActivity extends FragmentActivity implements + LocationListener, + MapProgressFragment.TaskCallbacks { + private static final String PROGRESS_FRAGMENT_TAG = "PROGRESS_FRAGMENT"; + private static final String BUTTONS_FRAGMENT_TAG = "BUTTONS_FRAGMENT"; + private WeatherLocation mRestoreUI; + + // Google Play Services Map + private GoogleMap mMap; + // TODO: read and store from different threads? Hopefully always from UI thread. + private Marker mMarker; + + private LocationManager mLocationManager; + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.setContentView(R.layout.weather_map); + + // Acquire a reference to the system Location Manager + this.mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); + + // Google Play Services Map + final MapFragment mapFragment = (MapFragment) this.getFragmentManager() + .findFragmentById(R.id.weather_map_fragment_map); + this.mMap = mapFragment.getMap(); + this.mMap.setMyLocationEnabled(false); + this.mMap.getUiSettings().setMyLocationButtonEnabled(false); + this.mMap.getUiSettings().setZoomControlsEnabled(true); + this.mMap.getUiSettings().setCompassEnabled(true); + this.mMap.setOnMapLongClickListener(new MapActivityOnMapLongClickListener(this)); + } + + @Override + protected void onRestoreInstanceState(final Bundle savedInstanceState) { + // Instead of restoring the state during onCreate() you may choose to + // implement onRestoreInstanceState(), which the system calls after the + // onStart() method. The system calls onRestoreInstanceState() only if + // there is a saved state to restore, so you do not need to check whether + // the Bundle is null: + super.onRestoreInstanceState(savedInstanceState); + + // Restore UI state + this.mRestoreUI = (WeatherLocation) savedInstanceState.getSerializable("WeatherLocation"); + } + + @Override + public void onResume() { + super.onResume(); + + final ActionBar actionBar = this.getActionBar(); + actionBar.setTitle(this.getString(R.string.weather_map_mark_location)); + + WeatherLocation weatherLocation; + if (this.mRestoreUI != null) { + // Restore UI state + weatherLocation = this.mRestoreUI; + // just once + this.mRestoreUI = null; + } else if (this.mMarker != null ) { + 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 LatLng point = this.mMarker.getPosition(); + double latitude = point.latitude; + double longitude = point.longitude; + + weatherLocation = new WeatherLocation() + .setCity(cityString) + .setCountry(countryString) + .setLatitude(latitude) + .setLongitude(longitude); + } else { + final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext()); + weatherLocation = query.queryDataBase(); + } + + if (weatherLocation != null) { + this.updateUI(weatherLocation); + } + } + + /** + * I am not using fragment transactions in the right way. But I do not know other way for doing what I am doing. + * + * {@link http://stackoverflow.com/questions/16265733/failure-delivering-result-onactivityforresult} + */ + @Override + public void onPostResume() { + super.onPostResume(); + + final FragmentManager fm = getSupportFragmentManager(); + final Fragment progressFragment = fm.findFragmentByTag(PROGRESS_FRAGMENT_TAG); + if (progressFragment == null) { + this.addButtonsFragment(); + } else { + this.removeProgressFragment(); + final Bundle bundle = progressFragment.getArguments(); + double latitude = bundle.getDouble("latitude"); + double longitude = bundle.getDouble("longitude"); + this.addProgressFragment(latitude, longitude); + } + } + + @Override + public void onSaveInstanceState(final Bundle savedInstanceState) { + // Save UI state + // Save Google Maps Marker + if (this.mMarker != null) { + 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 LatLng point = this.mMarker.getPosition(); + double latitude = point.latitude; + double longitude = point.longitude; + + final WeatherLocation location = new WeatherLocation() + .setCity(cityString) + .setCountry(countryString) + .setLatitude(latitude) + .setLongitude(longitude); + savedInstanceState.putSerializable("WeatherLocation", location); + } + + super.onSaveInstanceState(savedInstanceState); + } + + @Override + public void onPause() { + super.onPause(); + + this.mLocationManager.removeUpdates(this); + } + + public void onClickSaveLocation(final View v) { + if (this.mMarker != null) { + final LatLng position = this.mMarker.getPosition(); + + 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 DatabaseQueries query = new DatabaseQueries(this.getApplicationContext()); + final WeatherLocation weatherLocation = query.queryDataBase(); + if (weatherLocation != null) { + weatherLocation + .setCity(cityString) + .setCountry(countryString) + .setLatitude(position.latitude) + .setLongitude(position.longitude) + .setLastCurrentUIUpdate(null) + .setLastForecastUIUpdate(null) + .setIsNew(true); + query.updateDataBase(weatherLocation); + } else { + final WeatherLocation location = new WeatherLocation() + .setCity(cityString) + .setCountry(countryString) + .setIsSelected(true) + .setLatitude(position.latitude) + .setLongitude(position.longitude) + .setIsNew(true); + query.insertIntoDataBase(location); + } + } + } + + public void onClickGetLocation(final View v) { + // TODO: Somehow I should show a progress dialog. + // If Google Play Services is available + if (this.mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { + // TODO: Hopefully there will be results even if location did not change... + final Criteria criteria = new Criteria(); + criteria.setAccuracy(Criteria.ACCURACY_FINE); + criteria.setAltitudeRequired(false); + criteria.setBearingAccuracy(Criteria.NO_REQUIREMENT); + criteria.setBearingRequired(false); + criteria.setCostAllowed(false); + criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); + criteria.setPowerRequirement(Criteria.POWER_MEDIUM); + criteria.setSpeedAccuracy(Criteria.NO_REQUIREMENT); + criteria.setSpeedRequired(false); + criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH); + + this.mLocationManager.requestSingleUpdate(criteria, this, null); + } else { + Toast.makeText(this, this.getString(R.string.weather_map_not_enabled_location), Toast.LENGTH_LONG).show(); + } + // Trying to use the synchronous calls. Problems: mGoogleApiClient read/store from different threads. + // new GetLocationTask(this).execute(); + } + + private void updateUI(final WeatherLocation weatherLocation) { + + final TextView city = (TextView) this.findViewById(R.id.weather_map_city); + final TextView country = (TextView) this.findViewById(R.id.weather_map_country); + city.setText(weatherLocation.getCity()); + country.setText(weatherLocation.getCountry()); + + final LatLng point = new LatLng(weatherLocation.getLatitude(), weatherLocation.getLongitude()); + if (this.mMarker != null) { + // Just one marker on map + this.mMarker.remove(); + } + this.mMarker = this.mMap.addMarker(new MarkerOptions().position(point).draggable(true)); + this.mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(point, 5)); + this.mMap.animateCamera(CameraUpdateFactory.zoomIn()); + this.mMap.animateCamera(CameraUpdateFactory.zoomTo(8), 2000, null); + } + + private class MapActivityOnMapLongClickListener implements OnMapLongClickListener { + // Store the context passed to the AsyncTask when the system instantiates it. + private final Context localContext; + + private MapActivityOnMapLongClickListener(final Context context) { + this.localContext = context; + } + + @Override + public void onMapLongClick(final LatLng point) { + final MapActivity activity = (MapActivity) this.localContext; + activity.getAddressAndUpdateUI(point.latitude, point.longitude); + } + + } + + /** + * Getting the address of the current location, using reverse geocoding only works if + * a geocoding service is available. + * + */ + private void getAddressAndUpdateUI(final double latitude, final double longitude) { + // In Gingerbread and later, use Geocoder.isPresent() to see if a geocoder is available. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && Geocoder.isPresent()) { + this.removeButtonsFragment(); + this.removeProgressFragment(); + this.addProgressFragment(latitude, longitude); + } else { + this.removeProgressFragment(); + this.addButtonsFragment(); + // No geocoder is present. Issue an error message. + Toast.makeText(this, this.getString(R.string.weather_map_no_geocoder_available), Toast.LENGTH_LONG).show(); + + // 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() + .setLatitude(latitude) + .setLongitude(longitude) + .setCity(city) + .setCountry(country); + + updateUI(weatherLocation); + } + } + + /***************************************************************************************************** + * + * MapProgressFragment.TaskCallbacks + * + *****************************************************************************************************/ + @Override + public void onPostExecute(WeatherLocation weatherLocation) { + + this.updateUI(weatherLocation); + this.removeProgressFragment(); + + this.addButtonsFragment(); + } + + /***************************************************************************************************** + * + * MapProgressFragment + * I am not using fragment transactions in the right way. But I do not know other way for doing what I am doing. + * Android sucks. + * + * "Avoid performing transactions inside asynchronous callback methods." :( + * see: http://stackoverflow.com/questions/16265733/failure-delivering-result-onactivityforresult + * see: http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html + * How do you do what I am doing in a different way without using fragments? + *****************************************************************************************************/ + + private void addProgressFragment(final double latitude, final double longitude) { + final Fragment progressFragment = new MapProgressFragment(); + progressFragment.setRetainInstance(true); + final Bundle args = new Bundle(); + args.putDouble("latitude", latitude); + args.putDouble("longitude", longitude); + progressFragment.setArguments(args); + + final FragmentManager fm = this.getSupportFragmentManager(); + final FragmentTransaction fragmentTransaction = fm.beginTransaction(); + fragmentTransaction.setCustomAnimations(R.anim.weather_map_enter_progress, R.anim.weather_map_exit_progress); + fragmentTransaction.add(R.id.weather_map_buttons_container, progressFragment, PROGRESS_FRAGMENT_TAG).commit(); + fm.executePendingTransactions(); + } + + private void removeProgressFragment() { + final FragmentManager fm = this.getSupportFragmentManager(); + final Fragment progressFragment = fm.findFragmentByTag(PROGRESS_FRAGMENT_TAG); + if (progressFragment != null) { + final FragmentTransaction fragmentTransaction = fm.beginTransaction(); + fragmentTransaction.remove(progressFragment).commit(); + fm.executePendingTransactions(); + } + } + + private void addButtonsFragment() { + final FragmentManager fm = this.getSupportFragmentManager(); + Fragment buttonsFragment = fm.findFragmentByTag(BUTTONS_FRAGMENT_TAG); + if (buttonsFragment == null) { + buttonsFragment = new MapButtonsFragment(); + buttonsFragment.setRetainInstance(true); + final FragmentTransaction fragmentTransaction = fm.beginTransaction(); + fragmentTransaction.setCustomAnimations(R.anim.weather_map_enter_progress, R.anim.weather_map_exit_progress); + fragmentTransaction.add(R.id.weather_map_buttons_container, buttonsFragment, BUTTONS_FRAGMENT_TAG).commit(); + fm.executePendingTransactions(); + } + + if (this.mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { + final Button getLocationButton = (Button) this.findViewById(R.id.weather_map_button_getlocation); + getLocationButton.setEnabled(true); + } + } + + private void removeButtonsFragment() { + final FragmentManager fm = this.getSupportFragmentManager(); + final Fragment buttonsFragment = fm.findFragmentByTag(BUTTONS_FRAGMENT_TAG); + if (buttonsFragment != null) { + final FragmentTransaction fragmentTransaction = fm.beginTransaction(); + fragmentTransaction.remove(buttonsFragment).commit(); + fm.executePendingTransactions(); + } + } + + /***************************************************************************************************** + * + * android.location.LocationListener + * + *****************************************************************************************************/ + + @Override + public void onLocationChanged(final Location location) { + // It was called from onClickGetLocation (UI thread) This method will run in the same thread (the UI thread) + // so, I do no think there should be any problem. + + // Display the current location in the UI + // TODO: May location not be null? + this.getAddressAndUpdateUI(location.getLatitude(), location.getLongitude()); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) {} + + @Override + public void onProviderEnabled(String provider) {} + + @Override + public void onProviderDisabled(String provider) {} +} diff --git a/app/src/main/java/name/gumartinm/weather/information/activity/SpecificActivity.java b/app/src/main/java/name/gumartinm/weather/information/activity/SpecificActivity.java new file mode 100644 index 0000000..0f5211c --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/activity/SpecificActivity.java @@ -0,0 +1,46 @@ +package name.gumartinm.weather.information.activity; + +import android.app.ActionBar; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; + +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.model.DatabaseQueries; +import name.gumartinm.weather.information.model.WeatherLocation; + +import java.text.MessageFormat; +import java.util.Locale; + +public class SpecificActivity extends FragmentActivity { + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.setContentView(R.layout.weather_specific); + + final ActionBar actionBar = this.getActionBar(); + + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); + actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE); + actionBar.setDisplayHomeAsUpEnabled(true); + + } + + @Override + public void onResume() { + super.onResume(); + + // 1. Update title. + final DatabaseQueries query = new DatabaseQueries(this); + final WeatherLocation weatherLocation = query.queryDataBase(); + if (weatherLocation != null) { + final ActionBar actionBar = this.getActionBar(); + final String[] array = new String[2]; + array[0] = weatherLocation.getCity(); + array[1] = weatherLocation.getCountry(); + final MessageFormat message = new MessageFormat("{0},{1}", Locale.US); + final String cityCountry = message.format(array); + actionBar.setTitle(cityCountry); + } + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/activity/WeatherInformationPreferencesActivity.java b/app/src/main/java/name/gumartinm/weather/information/activity/WeatherInformationPreferencesActivity.java new file mode 100644 index 0000000..7a8f8f5 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/activity/WeatherInformationPreferencesActivity.java @@ -0,0 +1,29 @@ +package name.gumartinm.weather.information.activity; + +import android.app.ActionBar; +import android.app.Activity; +import android.os.Bundle; + +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.fragment.preferences.WeatherInformationPreferencesFragment; + +public class WeatherInformationPreferencesActivity extends Activity { + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + this.getFragmentManager() + .beginTransaction() + .replace(android.R.id.content, + new WeatherInformationPreferencesFragment()).commit(); + } + + @Override + public void onResume() { + super.onResume(); + + final ActionBar actionBar = this.getActionBar(); + actionBar.setTitle(this.getString(R.string.weather_preferences_action_settings)); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/activity/WeatherTabsActivity.java b/app/src/main/java/name/gumartinm/weather/information/activity/WeatherTabsActivity.java new file mode 100644 index 0000000..91b8c4c --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/activity/WeatherTabsActivity.java @@ -0,0 +1,194 @@ +package name.gumartinm.weather.information.activity; + +import android.app.ActionBar; +import android.app.ActionBar.Tab; +import android.app.FragmentTransaction; +import android.content.ComponentName; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.Menu; +import android.view.MenuItem; + +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.fragment.current.CurrentFragment; +import name.gumartinm.weather.information.fragment.overview.OverviewFragment; +import name.gumartinm.weather.information.model.DatabaseQueries; +import name.gumartinm.weather.information.model.WeatherLocation; + +import java.text.MessageFormat; +import java.util.Locale; + + +public class WeatherTabsActivity extends FragmentActivity { + private static final int NUM_ITEMS = 2; + private ViewPager mPager; + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.setContentView(R.layout.fragment_pager); + + this.mPager = (ViewPager)this.findViewById(R.id.pager); + this.mPager.setAdapter(new TabsAdapter(this.getSupportFragmentManager())); + + + this.mPager.setOnPageChangeListener( + new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(final int position) { + WeatherTabsActivity.this.getActionBar().setSelectedNavigationItem(position); + } + }); + + + final ActionBar actionBar = this.getActionBar(); + + PreferenceManager.setDefaultValues(this, R.xml.weather_preferences, false); + + // Specify that tabs should be displayed in the action bar. + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE); + actionBar.setDisplayHomeAsUpEnabled(true); + + // Create a tab listener that is called when the user changes tabs. + final ActionBar.TabListener tabListener = new ActionBar.TabListener() { + + @Override + public void onTabSelected(final Tab tab, final FragmentTransaction ft) { + WeatherTabsActivity.this.mPager.setCurrentItem(tab.getPosition()); + + } + + @Override + public void onTabUnselected(final Tab tab, final FragmentTransaction ft) { + + } + + @Override + public void onTabReselected(final Tab tab, final FragmentTransaction ft) { + + } + + }; + + actionBar.addTab(actionBar.newTab().setText("CURRENTLY").setTabListener(tabListener)); + actionBar.addTab(actionBar.newTab().setText("FORECAST").setTabListener(tabListener)); + } + + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + + this.getMenuInflater().inflate(R.menu.weather_main_menu, menu); + + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + super.onOptionsItemSelected(item); + + Intent intent; + final int itemId = item.getItemId(); + if (itemId == R.id.weather_menu_settings) { + intent = new Intent("name.gumartinm.weather.information.WEATHERINFO") + .setComponent(new ComponentName("name.gumartinm.weather.information", + "name.gumartinm.weather.information.activity.WeatherInformationPreferencesActivity")); + this.startActivity(intent); + return true; + } else if (itemId == R.id.weather_menu_map) { + intent = new Intent("name.gumartinm.weather.information.WEATHERINFO"). + setComponent(new ComponentName("name.gumartinm.weather.information", + "name.gumartinm.weather.information.activity.MapActivity")); + this.startActivity(intent); + return true; + } else if (itemId == R.id.weather_menu_about) { + intent = new Intent("name.gumartinm.weather.information.WEATHERINFO"). + setComponent(new ComponentName("name.gumartinm.weather.information", + "name.gumartinm.weather.information.activity.AboutActivity")); + this.startActivity(intent); + return true; + } else { + } + + // TODO: calling again super method? + return super.onOptionsItemSelected(item); + } + + @Override + protected void onRestoreInstanceState(final Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + } + + + @Override + public void onResume() { + super.onResume(); + + final ActionBar actionBar = this.getActionBar(); + + // 1. Update title. + final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext()); + final WeatherLocation weatherLocation = query.queryDataBase(); + if (weatherLocation != null) { + final String[] array = new String[2]; + array[0] = weatherLocation.getCity(); + array[1] = weatherLocation.getCountry(); + final MessageFormat message = new MessageFormat("{0},{1}", Locale.US); + final String cityCountry = message.format(array); + actionBar.setTitle(cityCountry); + } else { + actionBar.setTitle(this.getString(R.string.text_field_no_chosen_location)); + } + + // 2. Update forecast tab text. + final SharedPreferences sharedPreferences = PreferenceManager + .getDefaultSharedPreferences(this); + final String keyPreference = this.getString(R.string.weather_preferences_day_forecast_key); + final String value = sharedPreferences.getString(keyPreference, ""); + String humanValue = ""; + if (value.equals("5")) { + humanValue = "5 DAY FORECAST"; + } else if (value.equals("10")) { + humanValue = "10 DAY FORECAST"; + } else if (value.equals("14")) { + humanValue = "14 DAY FORECAST"; + } + actionBar.getTabAt(1).setText(humanValue); + } + + @Override + public void onSaveInstanceState(final Bundle savedInstanceState) { + super.onSaveInstanceState(savedInstanceState); + } + + private class TabsAdapter extends FragmentPagerAdapter { + public TabsAdapter(final FragmentManager fm) { + super(fm); + } + + @Override + public int getCount() { + return NUM_ITEMS; + } + + @Override + public Fragment getItem(final int position) { + if (position == 0) { + return new CurrentFragment(); + } else { + return new OverviewFragment(); + } + + } + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/boot/WeatherInformationBootReceiver.java b/app/src/main/java/name/gumartinm/weather/information/boot/WeatherInformationBootReceiver.java new file mode 100644 index 0000000..56d622c --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/boot/WeatherInformationBootReceiver.java @@ -0,0 +1,60 @@ +package name.gumartinm.weather.information.boot; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.SystemClock; +import android.preference.PreferenceManager; + +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.notification.NotificationIntentService; + +public class WeatherInformationBootReceiver extends BroadcastReceiver { + + @Override + public void onReceive(final Context context, final Intent intent) { + + if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { + + // Update Time Rate + final SharedPreferences sharedPreferences = PreferenceManager + .getDefaultSharedPreferences(context); + final String keyPreference = context + .getString(R.string.weather_preferences_update_time_rate_key); + final String updateTimeRate = sharedPreferences.getString(keyPreference, ""); + long chosenInterval = 0; + if (updateTimeRate.equals("900")) { + chosenInterval = AlarmManager.INTERVAL_FIFTEEN_MINUTES; + } else if (updateTimeRate.equals("1800")) { + chosenInterval = AlarmManager.INTERVAL_HALF_HOUR; + } else if (updateTimeRate.equals("3600")) { + chosenInterval = AlarmManager.INTERVAL_HOUR; + } else if (updateTimeRate.equals("43200")) { + chosenInterval = AlarmManager.INTERVAL_HALF_DAY; + } else if (updateTimeRate.equals("86400")) { + chosenInterval = AlarmManager.INTERVAL_DAY; + } + + if (chosenInterval != 0) { + final AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + // TODO: better use some string instead of .class? In case I change the service class + // this could be a problem (I guess) + final Intent serviceIntent = new Intent(context, NotificationIntentService.class); + final PendingIntent alarmIntent = PendingIntent.getService( + context, + 0, + serviceIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + alarmMgr.setInexactRepeating( + AlarmManager.ELAPSED_REALTIME, + SystemClock.elapsedRealtime() + chosenInterval, + chosenInterval, + alarmIntent); + } + } + } + +} diff --git a/app/src/main/java/name/gumartinm/weather/information/fragment/ErrorDialogFragment.java b/app/src/main/java/name/gumartinm/weather/information/fragment/ErrorDialogFragment.java new file mode 100644 index 0000000..af1a7d1 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/fragment/ErrorDialogFragment.java @@ -0,0 +1,45 @@ +package name.gumartinm.weather.information.fragment; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; + +public class ErrorDialogFragment extends DialogFragment { + + public static ErrorDialogFragment newInstance(final int title) { + final ErrorDialogFragment frag = new ErrorDialogFragment(); + final Bundle args = new Bundle(); + + args.putInt("title", title); + frag.setArguments(args); + + return frag; + } + + @Override + public Dialog onCreateDialog(final Bundle savedInstanceState) { + final int title = this.getArguments().getInt("title"); + + return new AlertDialog.Builder(this.getActivity()) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(title) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, + final int whichButton) { + + } + }).create(); + } + + @Override + public void onDestroyView() { + if (getDialog() != null && getRetainInstance()) { + getDialog().setDismissMessage(null); + } + super.onDestroyView(); + } +} \ No newline at end of file diff --git a/app/src/main/java/name/gumartinm/weather/information/fragment/current/CurrentFragment.java b/app/src/main/java/name/gumartinm/weather/information/fragment/current/CurrentFragment.java new file mode 100644 index 0000000..0ede8d1 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/fragment/current/CurrentFragment.java @@ -0,0 +1,523 @@ +package name.gumartinm.weather.information.fragment.current; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import org.apache.http.client.ClientProtocolException; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.http.AndroidHttpClient; +import android.os.AsyncTask; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; +import android.support.v4.content.LocalBroadcastManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.fasterxml.jackson.core.JsonParseException; +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.httpclient.CustomHTTPClient; +import name.gumartinm.weather.information.model.DatabaseQueries; +import name.gumartinm.weather.information.model.WeatherLocation; +import name.gumartinm.weather.information.model.currentweather.Current; +import name.gumartinm.weather.information.parser.JPOSWeatherParser; +import name.gumartinm.weather.information.service.IconsList; +import name.gumartinm.weather.information.service.PermanentStorage; +import name.gumartinm.weather.information.service.ServiceParser; +import name.gumartinm.weather.information.widget.WidgetProvider; + +public class CurrentFragment extends Fragment { + private static final String TAG = "CurrentFragment"; + private BroadcastReceiver mReceiver; + + @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_current_fragment, container, false); + } + + @Override + public void onActivityCreated(final Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + if (savedInstanceState != null) { + // Restore UI state + final Current current = (Current) savedInstanceState.getSerializable("Current"); + + if (current != null) { + final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); + store.saveCurrent(current); + } + } + + this.setHasOptionsMenu(false); + + this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE); + this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.VISIBLE); + this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE); + } + + @Override + public void onResume() { + super.onResume(); + + + this.mReceiver = new BroadcastReceiver() { + + @Override + public void onReceive(final Context context, final Intent intent) { + final String action = intent.getAction(); + if (action.equals("name.gumartinm.weather.information.UPDATECURRENT")) { + final Current currentRemote = (Current) intent.getSerializableExtra("current"); + + if (currentRemote != null) { + + // 1. Check conditions. They must be the same as the ones that triggered the AsyncTask. + final DatabaseQueries query = new DatabaseQueries(context.getApplicationContext()); + final WeatherLocation weatherLocation = query.queryDataBase(); + final PermanentStorage store = new PermanentStorage(context.getApplicationContext()); + final Current current = store.getCurrent(); + + if (current == null || !CurrentFragment.this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) { + // 2. Update UI. + CurrentFragment.this.updateUI(currentRemote); + + // 3. Update current data. + store.saveCurrent(currentRemote); + + // 4. Update location data. + weatherLocation.setLastCurrentUIUpdate(new Date()); + query.updateDataBase(weatherLocation); + } + + } else { + // Empty UI and show error message + CurrentFragment.this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE); + CurrentFragment.this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.GONE); + CurrentFragment.this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.VISIBLE); + } + } + } + }; + + // Register receiver + final IntentFilter filter = new IntentFilter(); + filter.addAction("name.gumartinm.weather.information.UPDATECURRENT"); + LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()) + .registerReceiver(this.mReceiver, filter); + + // Empty UI + this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE); + + final DatabaseQueries query = new DatabaseQueries(this.getActivity().getApplicationContext()); + final WeatherLocation weatherLocation = query.queryDataBase(); + if (weatherLocation == null) { + // Nothing to do. + // Show error message + final ProgressBar progress = (ProgressBar) getActivity().findViewById(R.id.weather_current_progressbar); + progress.setVisibility(View.GONE); + final TextView errorMessage = (TextView) getActivity().findViewById(R.id.weather_current_error_message); + errorMessage.setVisibility(View.VISIBLE); + return; + } + + // If is new location update widgets. + if (weatherLocation.getIsNew()) { + WidgetProvider.refreshAllAppWidgets(this.getActivity().getApplicationContext()); + // Update location data. + weatherLocation.setIsNew(false); + query.updateDataBase(weatherLocation); + } + + + final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); + final Current current = store.getCurrent(); + + if (current != null && this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) { + this.updateUI(current); + } else { + // Load remote data (aynchronous) + // Gets the data from the web. + this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.VISIBLE); + this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE); + final CurrentTask task = new CurrentTask( + this.getActivity().getApplicationContext(), + new CustomHTTPClient(AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")), + new ServiceParser(new JPOSWeatherParser())); + + task.execute(weatherLocation.getLatitude(), weatherLocation.getLongitude()); + } + } + + @Override + public void onSaveInstanceState(final Bundle savedInstanceState) { + + // Save UI state + final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); + final Current current = store.getCurrent(); + + if (current != null) { + savedInstanceState.putSerializable("Current", current); + } + + super.onSaveInstanceState(savedInstanceState); + } + + @Override + public void onPause() { + LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()).unregisterReceiver(this.mReceiver); + + super.onPause(); + } + + private interface UnitsConversor { + + public double doConversion(final double value); + } + + private void updateUI(final Current current) { + + final SharedPreferences sharedPreferences = PreferenceManager + .getDefaultSharedPreferences(this.getActivity().getApplicationContext()); + + // TODO: repeating the same code in Overview, Specific and Current!!! + // 1. Update units of measurement. + // 1.1 Temperature + String tempSymbol; + UnitsConversor tempUnitsConversor; + String keyPreference = this.getResources().getString(R.string.weather_preferences_temperature_key); + String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); + String unitsPreferenceValue = sharedPreferences.getString( + keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); + if (unitsPreferenceValue.equals(values[0])) { + tempSymbol = values[0]; + tempUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return value - 273.15; + } + + }; + } else if (unitsPreferenceValue.equals(values[1])) { + tempSymbol = values[1]; + tempUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return (value * 1.8) - 459.67; + } + + }; + } else { + tempSymbol = values[2]; + tempUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return value; + } + + }; + } + + // 1.2 Wind + String windSymbol; + UnitsConversor windUnitsConversor; + keyPreference = this.getResources().getString(R.string.weather_preferences_wind_key); + values = this.getResources().getStringArray(R.array.weather_preferences_wind); + unitsPreferenceValue = sharedPreferences.getString( + keyPreference, this.getString(R.string.weather_preferences_wind_meters)); + if (unitsPreferenceValue.equals(values[0])) { + windSymbol = values[0]; + windUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(double value) { + return value; + } + }; + } else { + windSymbol = values[1]; + windUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(double value) { + return value * 2.237; + } + }; + } + + // 1.3 Pressure + String pressureSymbol; + UnitsConversor pressureUnitsConversor; + keyPreference = this.getResources().getString(R.string.weather_preferences_pressure_key); + values = this.getResources().getStringArray(R.array.weather_preferences_pressure); + unitsPreferenceValue = sharedPreferences.getString( + keyPreference, this.getString(R.string.weather_preferences_pressure_pascal)); + if (unitsPreferenceValue.equals(values[0])) { + pressureSymbol = values[0]; + pressureUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(double value) { + return value; + } + }; + } else { + pressureSymbol = values[1]; + pressureUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(double value) { + return value / 113.25d; + } + }; + } + + + // 2. Formatters + final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); + tempFormatter.applyPattern("#####.#####"); + final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.US); + + + // 3. Prepare data for UI. + String tempMax = ""; + if (current.getMain().getTemp_max() != null) { + double conversion = (Double) current.getMain().getTemp_max(); + conversion = tempUnitsConversor.doConversion(conversion); + tempMax = tempFormatter.format(conversion) + tempSymbol; + } + String tempMin = ""; + if (current.getMain().getTemp_min() != null) { + double conversion = (Double) current.getMain().getTemp_min(); + conversion = tempUnitsConversor.doConversion(conversion); + tempMin = tempFormatter.format(conversion) + tempSymbol; + } + Bitmap picture; + if ((current.getWeather().size() > 0) + && (current.getWeather().get(0).getIcon() != null) + && (IconsList.getIcon(current.getWeather().get(0).getIcon()) != null)) { + final String icon = current.getWeather().get(0).getIcon(); + picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon) + .getResourceDrawable()); + } else { + picture = BitmapFactory.decodeResource(this.getResources(), + R.drawable.weather_severe_alert); + } + + String description = this.getString(R.string.text_field_description_when_error); + if (current.getWeather().size() > 0) { + description = current.getWeather().get(0).getDescription(); + } + + String humidityValue = ""; + if ((current.getMain() != null) + && (current.getMain().getHumidity() != null)) { + final double conversion = (Double) current.getMain().getHumidity(); + humidityValue = tempFormatter.format(conversion); + } + String pressureValue = ""; + if ((current.getMain() != null) + && (current.getMain().getPressure() != null)) { + double conversion = (Double) current.getMain().getPressure(); + conversion = pressureUnitsConversor.doConversion(conversion); + pressureValue = tempFormatter.format(conversion); + } + String windValue = ""; + if ((current.getWind() != null) + && (current.getWind().getSpeed() != null)) { + double conversion = (Double) current.getWind().getSpeed(); + conversion = windUnitsConversor.doConversion(conversion); + windValue = tempFormatter.format(conversion); + } + String rainValue = ""; + if ((current.getRain() != null) + && (current.getRain().get3h() != null)) { + final double conversion = (Double) current.getRain().get3h(); + rainValue = tempFormatter.format(conversion); + } + String cloudsValue = ""; + if ((current.getClouds() != null) + && (current.getClouds().getAll() != null)) { + final double conversion = (Double) current.getClouds().getAll(); + cloudsValue = tempFormatter.format(conversion); + } + String snowValue = ""; + if ((current.getSnow() != null) + && (current.getSnow().get3h() != null)) { + final double conversion = (Double) current.getSnow().get3h(); + snowValue = tempFormatter.format(conversion); + } + String feelsLike = ""; + if (current.getMain().getTemp() != null) { + double conversion = (Double) current.getMain().getTemp(); + conversion = tempUnitsConversor.doConversion(conversion); + feelsLike = tempFormatter.format(conversion); + } + String sunRiseTime = ""; + if (current.getSys().getSunrise() != null) { + final long unixTime = (Long) current.getSys().getSunrise(); + final Date unixDate = new Date(unixTime * 1000L); + sunRiseTime = dateFormat.format(unixDate); + } + String sunSetTime = ""; + if (current.getSys().getSunset() != null) { + final long unixTime = (Long) current.getSys().getSunset(); + final Date unixDate = new Date(unixTime * 1000L); + sunSetTime = dateFormat.format(unixDate); + } + + + // 4. Update UI. + final TextView tempMaxView = (TextView) getActivity().findViewById(R.id.weather_current_temp_max); + tempMaxView.setText(tempMax); + final TextView tempMinView = (TextView) getActivity().findViewById(R.id.weather_current_temp_min); + tempMinView.setText(tempMin); + final ImageView pictureView = (ImageView) getActivity().findViewById(R.id.weather_current_picture); + pictureView.setImageBitmap(picture); + + final TextView descriptionView = (TextView) getActivity().findViewById(R.id.weather_current_description); + descriptionView.setText(description); + + ((TextView) getActivity().findViewById(R.id.weather_current_humidity_value)).setText(humidityValue); + ((TextView) getActivity().findViewById(R.id.weather_current_humidity_units)).setText( + this.getActivity().getApplicationContext().getString(R.string.text_units_percent)); + + ((TextView) getActivity().findViewById(R.id.weather_current_pressure_value)).setText(pressureValue); + ((TextView) getActivity().findViewById(R.id.weather_current_pressure_units)).setText(pressureSymbol); + + ((TextView) getActivity().findViewById(R.id.weather_current_wind_value)).setText(windValue); + ((TextView) getActivity().findViewById(R.id.weather_current_wind_units)).setText(windSymbol); + + ((TextView) getActivity().findViewById(R.id.weather_current_rain_value)).setText(rainValue); + ((TextView) getActivity().findViewById(R.id.weather_current_rain_units)).setText( + this.getActivity().getApplicationContext().getString(R.string.text_units_mm3h)); + + ((TextView) getActivity().findViewById(R.id.weather_current_clouds_value)).setText(cloudsValue); + ((TextView) getActivity().findViewById(R.id.weather_current_clouds_units)).setText( + this.getActivity().getApplicationContext().getString(R.string.text_units_percent)); + + ((TextView) getActivity().findViewById(R.id.weather_current_snow_value)).setText(snowValue); + ((TextView) getActivity().findViewById(R.id.weather_current_snow_units)).setText( + this.getActivity().getApplicationContext().getString(R.string.text_units_mm3h)); + + ((TextView) getActivity().findViewById(R.id.weather_current_feelslike_value)).setText(feelsLike); + ((TextView) getActivity().findViewById(R.id.weather_current_feelslike_units)).setText(tempSymbol); + + ((TextView) getActivity().findViewById(R.id.weather_current_sunrise_value)).setText(sunRiseTime); + + ((TextView) getActivity().findViewById(R.id.weather_current_sunset_value)).setText(sunSetTime); + + this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.VISIBLE); + this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.GONE); + this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE); + } + + private boolean isDataFresh(final Date lastUpdate) { + if (lastUpdate == null) { + return false; + } + + final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences( + this.getActivity().getApplicationContext()); + final String keyPreference = this.getString(R.string.weather_preferences_refresh_interval_key); + final String refresh = sharedPreferences.getString( + keyPreference, + this.getResources().getStringArray(R.array.weather_preferences_refresh_interval)[0]); + final Date currentTime = new Date(); + if (((currentTime.getTime() - lastUpdate.getTime())) < Long.valueOf(refresh)) { + return true; + } + + return false; + } + + private class CurrentTask extends AsyncTask { + // Store the context passed to the AsyncTask when the system instantiates it. + private final Context localContext; + final CustomHTTPClient HTTPClient; + final ServiceParser weatherService; + + public CurrentTask(final Context context, final CustomHTTPClient HTTPClient, + final ServiceParser weatherService) { + this.localContext = context; + this.HTTPClient = HTTPClient; + this.weatherService = weatherService; + } + + @Override + protected Current doInBackground(final Object... params) { + final double latitude = (Double) params[0]; + final double longitude = (Double) params[1]; + + Current current = null; + try { + current = this.doInBackgroundThrowable(latitude, longitude); + } catch (final JsonParseException e) { + Log.e(TAG, "CurrentTask doInBackground exception: ", e); + } catch (final ClientProtocolException e) { + Log.e(TAG, "CurrentTask doInBackground exception: ", e); + } catch (final MalformedURLException e) { + Log.e(TAG, "CurrentTask doInBackground exception: ", e); + } catch (final URISyntaxException e) { + Log.e(TAG, "CurrentTask doInBackground exception: ", e); + } catch (final IOException e) { + // logger infrastructure swallows UnknownHostException :/ + Log.e(TAG, "CurrentTask doInBackground exception: " + e.getMessage(), e); + } finally { + HTTPClient.close(); + } + + return current; + } + + private Current doInBackgroundThrowable(final double latitude, final double longitude) + throws URISyntaxException, ClientProtocolException, JsonParseException, IOException { + + final String APIVersion = localContext.getResources().getString(R.string.api_version); + final String urlAPI = localContext.getResources().getString(R.string.uri_api_weather_today); + final String url = weatherService.createURIAPICurrent(urlAPI, APIVersion, latitude, longitude); + final String urlWithoutCache = url.concat("&time=" + System.currentTimeMillis()); + final String jsonData = HTTPClient.retrieveDataAsString(new URL(urlWithoutCache)); + + return weatherService.retrieveCurrentFromJPOS(jsonData); + } + + @Override + protected void onPostExecute(final Current current) { + + // Call updateUI on the UI thread. + final Intent currentData = new Intent("name.gumartinm.weather.information.UPDATECURRENT"); + currentData.putExtra("current", current); + LocalBroadcastManager.getInstance(this.localContext).sendBroadcastSync(currentData); + } + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/fragment/map/MapButtonsFragment.java b/app/src/main/java/name/gumartinm/weather/information/fragment/map/MapButtonsFragment.java new file mode 100644 index 0000000..1c6134d --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/fragment/map/MapButtonsFragment.java @@ -0,0 +1,32 @@ +package name.gumartinm.weather.information.fragment.map; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import name.gumartinm.weather.information.R; + +public class MapButtonsFragment extends Fragment { + + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, + final Bundle savedInstanceState) { + + // Inflate the layout for this fragment + return inflater.inflate(R.layout.weather_map_buttons, container, false); + } + + /** + * This method will only be called once when the retained + * Fragment is first created. + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Retain this fragment across configuration changes. + this.setRetainInstance(true); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/fragment/map/MapProgressFragment.java b/app/src/main/java/name/gumartinm/weather/information/fragment/map/MapProgressFragment.java new file mode 100644 index 0000000..264e9fd --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/fragment/map/MapProgressFragment.java @@ -0,0 +1,164 @@ +package name.gumartinm.weather.information.fragment.map; + +import java.io.IOException; +import java.util.List; +import java.util.Locale; + +import android.app.Activity; +import android.content.Context; +import android.location.Address; +import android.location.Geocoder; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.model.WeatherLocation; + +/** + * {@link http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html} + * + */ +public class MapProgressFragment extends Fragment { + + /** + * + * Callback interface through which the fragment will report the + * task's progress and results back to the Activity. + */ + public static interface TaskCallbacks { + void onPostExecute(final WeatherLocation weatherLocation); + } + + private TaskCallbacks mCallbacks; + + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, + final Bundle savedInstanceState) { + + // Inflate the layout for this fragment + return inflater.inflate(R.layout.weather_map_progress, container, false); + } + + /** + * This method will only be called once when the retained + * Fragment is first created. + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Retain this fragment across configuration changes. + this.setRetainInstance(true); + + final Bundle bundle = this.getArguments(); + double latitude = bundle.getDouble("latitude"); + double longitude = bundle.getDouble("longitude"); + + // Create and execute the background task. + new GetAddressTask(this.getActivity().getApplicationContext()).execute(latitude, longitude); + } + + /** + * Hold a reference to the parent Activity so we can report the + * task's current progress and results. The Android framework + * will pass us a reference to the newly created Activity after + * each configuration change. + */ + @Override + public void onAttach(final Activity activity) { + super.onAttach(activity); + mCallbacks = (TaskCallbacks) activity; + } + + /** + * Set the callback to null so we don't accidentally leak the + * Activity instance. + */ +// @Override +// public void onDetach() { +// super.onDetach(); +// mCallbacks = null; +// } + + /** + * I am not using onDetach because there are problems when my activity goes to background. + * + * {@link http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html} + */ + @Override + public void onPause() { + super.onPause(); + mCallbacks = null; + } + + private class GetAddressTask extends AsyncTask { + private static final String TAG = "GetAddressTask"; + // Store the context passed to the AsyncTask when the system instantiates it. + private final Context localContext; + + private GetAddressTask(final Context context) { + this.localContext = context; + } + + @Override + protected WeatherLocation doInBackground(final Object... params) { + final double latitude = (Double) params[0]; + final double longitude = (Double) params[1]; + + WeatherLocation weatherLocation = this.doDefaultLocation(latitude, longitude); + try { + weatherLocation = this.getLocation(latitude, longitude); + } catch (final Throwable e) { // Hopefully nothing goes wrong because of catching Throwable. + Log.e(TAG, "GetAddressTask doInBackground exception: ", e); + } + + return weatherLocation; + } + + @Override + protected void onPostExecute(final WeatherLocation weatherLocation) { + + // Call updateUI on the UI thread. + if (mCallbacks != null) { + mCallbacks.onPostExecute(weatherLocation); + } + } + + private WeatherLocation getLocation(final double latitude, final double longitude) throws IOException { + // TODO: i18n Locale.getDefault() + final Geocoder geocoder = new Geocoder(this.localContext, Locale.US); + final List

addresses = geocoder.getFromLocation(latitude, longitude, 1); + + // Default values + WeatherLocation weatherLocation = this.doDefaultLocation(latitude, longitude); + + if (addresses != null && addresses.size() > 0) { + if (addresses.get(0).getLocality() != null) { + weatherLocation.setCity(addresses.get(0).getLocality()); + } + if(addresses.get(0).getCountryName() != null) { + weatherLocation.setCountry(addresses.get(0).getCountryName()); + } + } + + return weatherLocation; + } + + private WeatherLocation doDefaultLocation(final double latitude, final double longitude) { + // Default values + String city = this.localContext.getString(R.string.city_not_found); + String country = this.localContext.getString(R.string.country_not_found); + + return new WeatherLocation() + .setLatitude(latitude) + .setLongitude(longitude) + .setCity(city) + .setCountry(country); + } + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/fragment/overview/OverviewAdapter.java b/app/src/main/java/name/gumartinm/weather/information/fragment/overview/OverviewAdapter.java new file mode 100644 index 0000000..90d2e5b --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/fragment/overview/OverviewAdapter.java @@ -0,0 +1,109 @@ +package name.gumartinm.weather.information.fragment.overview; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import name.gumartinm.weather.information.R; + +public class OverviewAdapter extends ArrayAdapter { + private final int resource; + + public OverviewAdapter(final Context context, final int resource) { + super(context, 0); + + this.resource = resource; + } + + @Override + public View getView(final int position, final View convertView, + final ViewGroup parent) { + + // We need to get the best view (re-used if possible) and then + // retrieve its corresponding ViewHolder, which optimizes lookup + // efficiency + final View view = this.getWorkingView(convertView); + final ViewHolder viewHolder = this.getViewHolder(view); + final OverviewEntry entry = this.getItem(position); + + + // Setting date + viewHolder.dateNameView.setText(entry.getDateName()); + viewHolder.dateNumberView.setText(entry.getDateNumber()); + + // Setting temperature max/min + viewHolder.temperatureMaxView.setText(entry.getMaxTemp()); + viewHolder.temperatureMinView.setText(entry.getMinTemp()); + + // Set image view + viewHolder.pictureView.setImageBitmap(entry.getPicture()); + + + return view; + } + + private View getWorkingView(final View convertView) { + // The workingView is basically just the convertView re-used if possible + // or inflated new if not possible + View workingView = null; + + if(null == convertView) { + final Context context = this.getContext(); + final LayoutInflater inflater = (LayoutInflater)context.getSystemService + (Context.LAYOUT_INFLATER_SERVICE); + + workingView = inflater.inflate(this.resource, null); + } else { + workingView = convertView; + } + + return workingView; + } + + private ViewHolder getViewHolder(final View workingView) { + // The viewHolder allows us to avoid re-looking up view references + // Since views are recycled, these references will never change + final Object tag = workingView.getTag(); + ViewHolder viewHolder = null; + + + if((null == tag) || !(tag instanceof ViewHolder)) { + viewHolder = new ViewHolder(); + + viewHolder.dateNameView = (TextView) workingView + .findViewById(R.id.weather_main_entry_date_name); + viewHolder.dateNumberView = (TextView) workingView + .findViewById(R.id.weather_main_entry_date_number); + viewHolder.temperatureMaxView = (TextView) workingView + .findViewById(R.id.weather_main_entry_temperature_max); + viewHolder.temperatureMinView = (TextView) workingView + .findViewById(R.id.weather_main_entry_temperature_min); + viewHolder.pictureView = (ImageView) workingView + .findViewById(R.id.weather_main_entry_image); + + workingView.setTag(viewHolder); + + } else { + viewHolder = (ViewHolder) tag; + } + + return viewHolder; + } + + /** + * ViewHolder allows us to avoid re-looking up view references + * Since views are recycled, these references will never change + */ + private static class ViewHolder { + public TextView dateNameView; + public TextView dateNumberView; + public TextView temperatureMaxView; + public TextView temperatureMinView; + public ImageView pictureView; + } + +} diff --git a/app/src/main/java/name/gumartinm/weather/information/fragment/overview/OverviewEntry.java b/app/src/main/java/name/gumartinm/weather/information/fragment/overview/OverviewEntry.java new file mode 100644 index 0000000..2f4eca1 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/fragment/overview/OverviewEntry.java @@ -0,0 +1,41 @@ +package name.gumartinm.weather.information.fragment.overview; + +import android.graphics.Bitmap; + +public class OverviewEntry { + private final String dateName; + private final String dateNumber; + private final String maxTemp; + private final String minTemp; + private final Bitmap picture; + + public OverviewEntry(final String dateName, final String dateNumber, + final String maxTemp, final String minTemp, + final Bitmap picture) { + this.dateName = dateName; + this.dateNumber = dateNumber; + this.maxTemp = maxTemp; + this.minTemp = minTemp; + this.picture = picture; + } + + public String getDateName() { + return this.dateName; + } + + public String getDateNumber() { + return this.dateNumber; + } + + public String getMaxTemp() { + return this.maxTemp; + } + + public String getMinTemp() { + return this.minTemp; + } + + public Bitmap getPicture() { + return this.picture; + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/fragment/overview/OverviewFragment.java b/app/src/main/java/name/gumartinm/weather/information/fragment/overview/OverviewFragment.java new file mode 100644 index 0000000..382ce2b --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/fragment/overview/OverviewFragment.java @@ -0,0 +1,398 @@ +package name.gumartinm.weather.information.fragment.overview; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import org.apache.http.client.ClientProtocolException; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.http.AndroidHttpClient; +import android.os.AsyncTask; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v4.app.ListFragment; +import android.support.v4.content.LocalBroadcastManager; +import android.util.Log; +import android.view.View; +import android.widget.ListView; + +import com.fasterxml.jackson.core.JsonParseException; +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.fragment.specific.SpecificFragment; +import name.gumartinm.weather.information.httpclient.CustomHTTPClient; +import name.gumartinm.weather.information.model.DatabaseQueries; +import name.gumartinm.weather.information.model.WeatherLocation; +import name.gumartinm.weather.information.model.forecastweather.Forecast; +import name.gumartinm.weather.information.parser.JPOSWeatherParser; +import name.gumartinm.weather.information.service.IconsList; +import name.gumartinm.weather.information.service.PermanentStorage; +import name.gumartinm.weather.information.service.ServiceParser; + +public class OverviewFragment extends ListFragment { + private static final String TAG = "OverviewFragment"; + private BroadcastReceiver mReceiver; + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public void onActivityCreated(final Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + final ListView listWeatherView = this.getListView(); + listWeatherView.setChoiceMode(ListView.CHOICE_MODE_NONE); + + if (savedInstanceState != null) { + // Restore UI state + final Forecast forecast = (Forecast) savedInstanceState.getSerializable("Forecast"); + + if (forecast != null) { + final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); + store.saveForecast(forecast); + } + } + + this.setHasOptionsMenu(false); + + this.setEmptyText(this.getString(R.string.text_field_remote_error)); + this.setListShownNoAnimation(false); + } + + @Override + public void onResume() { + super.onResume(); + + this.mReceiver = new BroadcastReceiver() { + + @Override + public void onReceive(final Context context, final Intent intent) { + final String action = intent.getAction(); + if (action.equals("name.gumartinm.weather.information.UPDATEFORECAST")) { + final Forecast forecastRemote = (Forecast) intent.getSerializableExtra("forecast"); + + if (forecastRemote != null) { + + // 1. Check conditions. They must be the same as the ones that triggered the AsyncTask. + final DatabaseQueries query = new DatabaseQueries(context.getApplicationContext()); + final WeatherLocation weatherLocation = query.queryDataBase(); + final PermanentStorage store = new PermanentStorage(context.getApplicationContext()); + final Forecast forecast = store.getForecast(); + + if (forecast == null || !OverviewFragment.this.isDataFresh(weatherLocation.getLastForecastUIUpdate())) { + // 2. Update UI. + OverviewFragment.this.updateUI(forecastRemote); + + // 3. Update Data. + store.saveForecast(forecastRemote); + weatherLocation.setLastForecastUIUpdate(new Date()); + query.updateDataBase(weatherLocation); + + // 4. Show list. + OverviewFragment.this.setListShownNoAnimation(true); + } + + } else { + // Empty list and show error message (see setEmptyText in onCreate) + OverviewFragment.this.setListAdapter(null); + OverviewFragment.this.setListShownNoAnimation(true); + } + } + } + }; + + // Register receiver + final IntentFilter filter = new IntentFilter(); + filter.addAction("name.gumartinm.weather.information.UPDATEFORECAST"); + LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()) + .registerReceiver(this.mReceiver, filter); + + final DatabaseQueries query = new DatabaseQueries(this.getActivity().getApplicationContext()); + final WeatherLocation weatherLocation = query.queryDataBase(); + if (weatherLocation == null) { + // Nothing to do. + // Empty list and show error message (see setEmptyText in onCreate) + this.setListAdapter(null); + this.setListShownNoAnimation(true); + return; + } + + final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); + final Forecast forecast = store.getForecast(); + + if (forecast != null && this.isDataFresh(weatherLocation.getLastForecastUIUpdate())) { + this.updateUI(forecast); + } else { + // Load remote data (aynchronous) + // Gets the data from the web. + this.setListShownNoAnimation(false); + final OverviewTask task = new OverviewTask( + this.getActivity().getApplicationContext(), + new CustomHTTPClient(AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")), + new ServiceParser(new JPOSWeatherParser())); + + task.execute(weatherLocation.getLatitude(), weatherLocation.getLongitude()); + } + } + + @Override + public void onSaveInstanceState(final Bundle savedInstanceState) { + + // Save UI state + final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); + final Forecast forecast = store.getForecast(); + + if (forecast != null) { + savedInstanceState.putSerializable("Forecast", forecast); + } + + super.onSaveInstanceState(savedInstanceState); + } + + @Override + public void onPause() { + LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()).unregisterReceiver(this.mReceiver); + + super.onPause(); + } + + @Override + public void onListItemClick(final ListView l, final View v, final int position, final long id) { + final SpecificFragment fragment = (SpecificFragment) this + .getFragmentManager().findFragmentById(R.id.weather_specific_fragment); + if (fragment == null) { + // handset layout + final Intent intent = new Intent("name.gumartinm.weather.information.WEATHERINFO") + .setComponent(new ComponentName("name.gumartinm.weather.information", + "name.gumartinm.weather.information.activity.SpecificActivity")); + intent.putExtra("CHOSEN_DAY", (int) id); + OverviewFragment.this.getActivity().startActivity(intent); + } else { + // tablet layout + fragment.updateUIByChosenDay((int) id); + } + } + + private interface UnitsConversor { + + public double doConversion(final double value); + } + + private void updateUI(final Forecast forecastWeatherData) { + + final SharedPreferences sharedPreferences = PreferenceManager + .getDefaultSharedPreferences(this.getActivity().getApplicationContext()); + + // TODO: repeating the same code in Overview, Specific and Current!!! + // 1. Update units of measurement. + String symbol; + UnitsConversor unitsConversor; + String keyPreference = this.getResources().getString( + R.string.weather_preferences_temperature_key); + final String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); + final String unitsPreferenceValue = sharedPreferences.getString( + keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); + if (unitsPreferenceValue.equals(values[0])) { + symbol = values[0]; + unitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return value - 273.15; + } + + }; + } else if (unitsPreferenceValue.equals(values[1])) { + symbol = values[1]; + unitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return (value * 1.8) - 459.67; + } + + }; + } else { + symbol = values[2]; + unitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return value; + } + + }; + } + + + // 2. Update number day forecast. + keyPreference = this.getResources().getString(R.string.weather_preferences_day_forecast_key); + final String dayForecast = sharedPreferences.getString(keyPreference, "5"); + final int mDayForecast = Integer.valueOf(dayForecast); + + + // 3. Formatters + final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); + tempFormatter.applyPattern("#####.##"); + final SimpleDateFormat dayNameFormatter = new SimpleDateFormat("EEE", Locale.US); + final SimpleDateFormat monthAndDayNumberormatter = new SimpleDateFormat("MMM d", Locale.US); + + + // 4. Prepare data for UI. + final List entries = new ArrayList(); + final OverviewAdapter adapter = new OverviewAdapter(this.getActivity(), + R.layout.weather_main_entry_list); + final Calendar calendar = Calendar.getInstance(); + int count = mDayForecast; + for (final name.gumartinm.weather.information.model.forecastweather.List forecast : forecastWeatherData + .getList()) { + + Bitmap picture; + + if ((forecast.getWeather().size() > 0) && + (forecast.getWeather().get(0).getIcon() != null) && + (IconsList.getIcon(forecast.getWeather().get(0).getIcon()) != null)) { + final String icon = forecast.getWeather().get(0).getIcon(); + picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon) + .getResourceDrawable()); + } else { + picture = BitmapFactory.decodeResource(this.getResources(), + R.drawable.weather_severe_alert); + } + + final Long forecastUNIXDate = (Long) forecast.getDt(); + calendar.setTimeInMillis(forecastUNIXDate * 1000L); + final Date dayTime = calendar.getTime(); + final String dayTextName = dayNameFormatter.format(dayTime); + final String monthAndDayNumberText = monthAndDayNumberormatter.format(dayTime); + + Double maxTemp = null; + if (forecast.getTemp().getMax() != null) { + maxTemp = (Double) forecast.getTemp().getMax(); + maxTemp = unitsConversor.doConversion(maxTemp); + } + + Double minTemp = null; + if (forecast.getTemp().getMin() != null) { + minTemp = (Double) forecast.getTemp().getMin(); + minTemp = unitsConversor.doConversion(minTemp); + } + + if ((maxTemp != null) && (minTemp != null)) { + entries.add(new OverviewEntry(dayTextName, monthAndDayNumberText, + tempFormatter.format(maxTemp) + symbol, tempFormatter.format(minTemp) + symbol, + picture)); + } + + count = count - 1; + if (count == 0) { + break; + } + } + + + // 5. Update UI. + adapter.addAll(entries); + this.setListAdapter(adapter); + } + + private boolean isDataFresh(final Date lastUpdate) { + if (lastUpdate == null) { + return false; + } + + final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences( + this.getActivity().getApplicationContext()); + final String keyPreference = this.getString(R.string.weather_preferences_refresh_interval_key); + final String refresh = sharedPreferences.getString( + keyPreference, + this.getResources().getStringArray(R.array.weather_preferences_refresh_interval)[0]); + final Date currentTime = new Date(); + if (((currentTime.getTime() - lastUpdate.getTime())) < Long.valueOf(refresh)) { + return true; + } + + return false; + } + + private class OverviewTask extends AsyncTask { + // Store the context passed to the AsyncTask when the system instantiates it. + private final Context localContext; + private final CustomHTTPClient HTTPClient; + private final ServiceParser weatherService; + + public OverviewTask(final Context context, final CustomHTTPClient HTTPClient, + final ServiceParser weatherService) { + this.localContext = context; + this.HTTPClient = HTTPClient; + this.weatherService = weatherService; + } + + @Override + protected Forecast doInBackground(final Object... params) { + final double latitude = (Double) params[0]; + final double longitude = (Double) params[1]; + + Forecast forecast = null; + + try { + forecast = this.doInBackgroundThrowable(latitude, longitude); + } catch (final JsonParseException e) { + Log.e(TAG, "OverviewTask doInBackground exception: ", e); + } catch (final ClientProtocolException e) { + Log.e(TAG, "OverviewTask doInBackground exception: ", e); + } catch (final MalformedURLException e) { + Log.e(TAG, "OverviewTask doInBackground exception: ", e); + } catch (final URISyntaxException e) { + Log.e(TAG, "OverviewTask doInBackground exception: ", e); + } catch (final IOException e) { + // logger infrastructure swallows UnknownHostException :/ + Log.e(TAG, "OverviewTask doInBackground exception: " + e.getMessage(), e); + } finally { + HTTPClient.close(); + } + + return forecast; + } + + private Forecast doInBackgroundThrowable(final double latitude, final double longitude) + throws URISyntaxException, ClientProtocolException, JsonParseException, IOException { + + final String APIVersion = localContext.getResources().getString(R.string.api_version); + final String urlAPI = localContext.getResources().getString(R.string.uri_api_weather_forecast); + // TODO: number as resource + final String url = weatherService.createURIAPIForecast(urlAPI, APIVersion, latitude, longitude, "14"); + final String urlWithoutCache = url.concat("&time=" + System.currentTimeMillis()); + final String jsonData = HTTPClient.retrieveDataAsString(new URL(urlWithoutCache)); + + return weatherService.retrieveForecastFromJPOS(jsonData); + } + + @Override + protected void onPostExecute(final Forecast forecast) { + + // Call updateUI on the UI thread. + final Intent forecastData = new Intent("name.gumartinm.weather.information.UPDATEFORECAST"); + forecastData.putExtra("forecast", forecast); + LocalBroadcastManager.getInstance(this.localContext).sendBroadcastSync(forecastData); + } + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/fragment/preferences/WeatherInformationPreferencesFragment.java b/app/src/main/java/name/gumartinm/weather/information/fragment/preferences/WeatherInformationPreferencesFragment.java new file mode 100644 index 0000000..0e4b2de --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/fragment/preferences/WeatherInformationPreferencesFragment.java @@ -0,0 +1,397 @@ +package name.gumartinm.weather.information.fragment.preferences; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Bundle; +import android.os.SystemClock; +import android.preference.Preference; +import android.preference.PreferenceFragment; +import android.preference.SwitchPreference; + +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.notification.NotificationIntentService; + +public class WeatherInformationPreferencesFragment extends PreferenceFragment + implements OnSharedPreferenceChangeListener { + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Load the preferences from an XML resource + this.addPreferencesFromResource(R.xml.weather_preferences); + + + // Temperature units + String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); + String[] humanValues = this.getResources().getStringArray(R.array.weather_preferences_temperature_human_value); + String keyPreference = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_temperature_key); + Preference connectionPref = this.findPreference(keyPreference); + String value = this.getPreferenceManager().getSharedPreferences() + .getString(keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); + String humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } else if (value.equals(values[2])) { + humanValue = humanValues[2]; + } + connectionPref.setSummary(humanValue); + + // Wind + values = this.getResources().getStringArray(R.array.weather_preferences_wind); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_wind_human_value); + keyPreference = this.getString(R.string.weather_preferences_wind_key); + connectionPref = this.findPreference(keyPreference); + value = this.getPreferenceManager().getSharedPreferences() + .getString(keyPreference, this.getString(R.string.weather_preferences_wind_meters)); + humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } + connectionPref.setSummary(humanValue); + + // Pressure + values = this.getResources().getStringArray(R.array.weather_preferences_pressure); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_pressure_human_value); + keyPreference = this.getString(R.string.weather_preferences_pressure_key); + connectionPref = this.findPreference(keyPreference); + value = this.getPreferenceManager().getSharedPreferences() + .getString(keyPreference, this.getString(R.string.weather_preferences_pressure_pascal)); + humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } + connectionPref.setSummary(humanValue); + + // Forecast days number + values = this.getResources().getStringArray(R.array.weather_preferences_day_forecast); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_day_forecast_human_value); + keyPreference = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_day_forecast_key); + connectionPref = this.findPreference(keyPreference); + value = this.getPreferenceManager().getSharedPreferences().getString(keyPreference, values[0]); + humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } else if (value.equals(values[2])) { + humanValue = humanValues[2]; + } + connectionPref.setSummary(humanValue); + + // Refresh interval + values = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval_human_value); + keyPreference = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_refresh_interval_key); + connectionPref = this.findPreference(keyPreference); + value = this.getPreferenceManager().getSharedPreferences().getString(keyPreference, values[0]); + humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } else if (value.equals(values[2])) { + humanValue = humanValues[2]; + } else if (value.equals(values[3])) { + humanValue = humanValues[3]; + } else if (value.equals(values[4])) { + humanValue = humanValues[4]; + } else if (value.equals(values[5])) { + humanValue = humanValues[5]; + } else if (value.equals(values[6])) { + humanValue = humanValues[6]; + } + connectionPref.setSummary(humanValue); + + // Update Time Rate + values = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate_human_value); + keyPreference = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_update_time_rate_key); + connectionPref = this.findPreference(keyPreference); + value = this.getPreferenceManager().getSharedPreferences() + .getString(keyPreference, values[0]); + humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } else if (value.equals(values[2])) { + humanValue = humanValues[2]; + } else if (value.equals(values[3])) { + humanValue = humanValues[3]; + } else if (value.equals(values[4])) { + humanValue = humanValues[4]; + } + connectionPref.setSummary(humanValue); + + // Notifications temperature units + values = this.getResources().getStringArray(R.array.weather_preferences_temperature); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_temperature_human_value); + keyPreference = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_notifications_temperature_key); + connectionPref = this.findPreference(keyPreference); + value = this.getPreferenceManager().getSharedPreferences() + .getString(keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); + humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } else if (value.equals(values[2])) { + humanValue = humanValues[2]; + } + connectionPref.setSummary(humanValue); + } + + @Override + public void onResume() { + super.onResume(); + this.getPreferenceManager().getSharedPreferences() + .registerOnSharedPreferenceChangeListener(this); + + } + + @Override + public void onPause() { + super.onPause(); + this.getPreferenceManager().getSharedPreferences() + .unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onSharedPreferenceChanged( + final SharedPreferences sharedPreferences, final String key) { + + // Temperature units + String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); + String[] humanValues = this.getResources().getStringArray(R.array.weather_preferences_temperature_human_value); + String keyValue = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_temperature_key); + if (key.equals(keyValue)) { + final Preference connectionPref = this.findPreference(key); + final String value = sharedPreferences.getString(key, values[0]); + String humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } else if (value.equals(values[2])) { + humanValue = humanValues[2]; + } + + connectionPref.setSummary(humanValue); + return; + } + + // Wind + values = this.getResources().getStringArray(R.array.weather_preferences_wind); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_wind_human_value); + keyValue = this.getString(R.string.weather_preferences_wind_key); + if (key.equals(keyValue)) { + final Preference connectionPref = this.findPreference(key); + final String value = sharedPreferences.getString(key, values[0]); + String humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } + + connectionPref.setSummary(humanValue); + return; + } + + // Pressure + values = this.getResources().getStringArray(R.array.weather_preferences_pressure); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_pressure_human_value); + keyValue = this.getString(R.string.weather_preferences_pressure_key); + if (key.equals(keyValue)) { + final Preference connectionPref = this.findPreference(key); + final String value = sharedPreferences.getString(key, values[0]); + String humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } + + connectionPref.setSummary(humanValue); + return; + } + + // Forecast days number + values = this.getResources().getStringArray(R.array.weather_preferences_day_forecast); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_day_forecast_human_value); + keyValue = this.getActivity().getString( + R.string.weather_preferences_day_forecast_key); + if (key.equals(keyValue)) { + final Preference connectionPref = this.findPreference(key); + final String value = sharedPreferences.getString(key, values[0]); + String humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } else if (value.equals(values[2])) { + humanValue = humanValues[2]; + } + connectionPref.setSummary(humanValue); + return; + } + + // Refresh interval + values = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval_human_value); + keyValue = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_refresh_interval_key); + if (key.equals(keyValue)) { + final Preference connectionPref = this.findPreference(key); + final String value = sharedPreferences.getString(key, values[0]); + String humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } else if (value.equals(values[2])) { + humanValue = humanValues[2]; + } else if (value.equals(values[3])) { + humanValue = humanValues[3]; + } else if (value.equals(values[4])) { + humanValue = humanValues[4]; + } else if (value.equals(values[5])) { + humanValue = humanValues[5]; + } else if (value.equals(values[6])) { + humanValue = humanValues[6]; + } + connectionPref.setSummary(humanValue); + return; + } + + // Notification switch + values = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate); + keyValue = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_notifications_switch_key); + if (key.equals(keyValue)) { + final SwitchPreference preference = (SwitchPreference)this.findPreference(key); + if (preference.isChecked()) + { + keyValue = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_update_time_rate_key); + final String value = sharedPreferences.getString(keyValue, values[0]); + this.updateNotification(value); + } else { + this.cancelNotification(); + } + } + // Update Time Rate + values = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate_human_value); + keyValue = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_update_time_rate_key); + if (key.equals(keyValue)) { + final Preference connectionPref = this.findPreference(key); + final String value = sharedPreferences.getString(key, values[0]); + String humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } else if (value.equals(values[2])) { + humanValue = humanValues[2]; + } else if (value.equals(values[3])) { + humanValue = humanValues[3]; + } else if (value.equals(values[4])) { + humanValue = humanValues[4]; + } + + this.updateNotification(value); + connectionPref.setSummary(humanValue); + return; + } + + // Temperature units + values = this.getResources().getStringArray(R.array.weather_preferences_temperature); + humanValues = this.getResources().getStringArray(R.array.weather_preferences_temperature_human_value); + keyValue = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_notifications_temperature_key); + if (key.equals(keyValue)) { + final Preference connectionPref = this.findPreference(key); + final String value = sharedPreferences.getString(key, values[0]); + String humanValue = ""; + if (value.equals(values[0])) { + humanValue = humanValues[0]; + } else if (value.equals(values[1])) { + humanValue = humanValues[1]; + } else if (value.equals(values[2])) { + humanValue = humanValues[2]; + } + + connectionPref.setSummary(humanValue); + return; + } + } + + private void updateNotification(final String updateTimeRate) { + final String[] values = this.getResources().getStringArray(R.array.weather_preferences_update_time_rate); + long chosenInterval = 0; + if (updateTimeRate.equals(values[0])) { + chosenInterval = AlarmManager.INTERVAL_FIFTEEN_MINUTES; + } else if (updateTimeRate.equals(values[1])) { + chosenInterval = AlarmManager.INTERVAL_HALF_HOUR; + } else if (updateTimeRate.equals(values[2])) { + chosenInterval = AlarmManager.INTERVAL_HOUR; + } else if (updateTimeRate.equals(values[3])) { + chosenInterval = AlarmManager.INTERVAL_HALF_DAY; + } else if (updateTimeRate.equals(values[4])) { + chosenInterval = AlarmManager.INTERVAL_DAY; + } + + final AlarmManager alarmMgr = + (AlarmManager) this.getActivity().getApplicationContext().getSystemService(Context.ALARM_SERVICE); + // TODO: better use some string instead of .class? In case I change the service class + // this could be a problem (I guess) + final Intent serviceIntent = + new Intent(this.getActivity().getApplicationContext(), NotificationIntentService.class); + final PendingIntent alarmIntent = + PendingIntent.getService( + this.getActivity().getApplicationContext(), + 0, + serviceIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + if (chosenInterval != 0) { + alarmMgr.setInexactRepeating( + AlarmManager.ELAPSED_REALTIME, + SystemClock.elapsedRealtime(), + chosenInterval, + alarmIntent); + } + } + + private void cancelNotification() { + final AlarmManager alarmMgr = + (AlarmManager) this.getActivity().getApplicationContext().getSystemService(Context.ALARM_SERVICE); + final Intent serviceIntent = + new Intent(this.getActivity().getApplicationContext(), NotificationIntentService.class); + final PendingIntent alarmIntent = + PendingIntent.getService( + this.getActivity().getApplicationContext(), + 0, + serviceIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + alarmMgr.cancel(alarmIntent); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/fragment/specific/SpecificFragment.java b/app/src/main/java/name/gumartinm/weather/information/fragment/specific/SpecificFragment.java new file mode 100644 index 0000000..9cbe49f --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/fragment/specific/SpecificFragment.java @@ -0,0 +1,353 @@ +package name.gumartinm.weather.information.fragment.specific; + +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; + +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.model.forecastweather.Forecast; +import name.gumartinm.weather.information.service.IconsList; +import name.gumartinm.weather.information.service.PermanentStorage; + + +public class SpecificFragment extends Fragment { + private int mChosenDay; + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final Bundle extras = this.getActivity().getIntent().getExtras(); + + if (extras != null) { + // handset layout + this.mChosenDay = extras.getInt("CHOSEN_DAY", 0); + } else { + // tablet layout + // Always 0 when tablet layout (by default shows the first day) + this.mChosenDay = 0; + } + } + + @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); + + if (savedInstanceState != null) { + // Restore UI state + final Forecast forecast = (Forecast) savedInstanceState.getSerializable("Forecast"); + + if (forecast != null) { + final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); + store.saveForecast(forecast); + } + + this.mChosenDay = savedInstanceState.getInt("mChosenDay"); + } + + this.setHasOptionsMenu(false); + } + + @Override + public void onSaveInstanceState(final Bundle savedInstanceState) { + + // Save UI state + final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); + final Forecast forecast = store.getForecast(); + + if (forecast != null) { + savedInstanceState.putSerializable("Forecast", forecast); + } + + savedInstanceState.putInt("mChosenDay", this.mChosenDay); + + super.onSaveInstanceState(savedInstanceState); + } + + /** + * This method is used by tablet layout. + * + * @param chosenDay + */ + public void updateUIByChosenDay(final int chosenDay) { + final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); + final Forecast forecast = store.getForecast(); + + if (forecast != null) { + this.updateUI(forecast, chosenDay); + } + } + + private interface UnitsConversor { + + public double doConversion(final double value); + } + + private void updateUI(final Forecast forecastWeatherData, final int chosenDay) { + + final SharedPreferences sharedPreferences = PreferenceManager + .getDefaultSharedPreferences(this.getActivity()); + + // TODO: repeating the same code in Overview, Specific and Current!!! + // 1. Update units of measurement. + // 1.1 Temperature + String tempSymbol; + UnitsConversor tempUnitsConversor; + String keyPreference = this.getResources().getString( + R.string.weather_preferences_temperature_key); + String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); + String unitsPreferenceValue = sharedPreferences.getString( + keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); + if (unitsPreferenceValue.equals(values[0])) { + tempSymbol = values[0]; + tempUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return value - 273.15; + } + + }; + } else if (unitsPreferenceValue.equals(values[1])) { + tempSymbol = values[1]; + tempUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return (value * 1.8) - 459.67; + } + + }; + } else { + tempSymbol = values[2]; + tempUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return value; + } + + }; + } + + // 1.2 Wind + String windSymbol; + UnitsConversor windUnitsConversor; + keyPreference = this.getResources().getString(R.string.weather_preferences_wind_key); + values = this.getResources().getStringArray(R.array.weather_preferences_wind); + unitsPreferenceValue = sharedPreferences.getString( + keyPreference, this.getString(R.string.weather_preferences_wind_meters)); + if (unitsPreferenceValue.equals(values[0])) { + windSymbol = values[0]; + windUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(double value) { + return value; + } + }; + } else { + windSymbol = values[1]; + windUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(double value) { + return value * 2.237; + } + }; + } + + // 1.3 Pressure + String pressureSymbol; + UnitsConversor pressureUnitsConversor; + keyPreference = this.getResources().getString(R.string.weather_preferences_pressure_key); + values = this.getResources().getStringArray(R.array.weather_preferences_pressure); + unitsPreferenceValue = sharedPreferences.getString( + keyPreference, this.getString(R.string.weather_preferences_pressure_pascal)); + if (unitsPreferenceValue.equals(values[0])) { + pressureSymbol = values[0]; + pressureUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(double value) { + return value; + } + }; + } else { + pressureSymbol = values[1]; + pressureUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(double value) { + return value / 113.25d; + } + }; + } + + + // 2. Formatters + final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); + tempFormatter.applyPattern("#####.#####"); + + + // 3. Prepare data for UI. + final name.gumartinm.weather.information.model.forecastweather.List forecast = forecastWeatherData + .getList().get((chosenDay)); + + final SimpleDateFormat dayFormatter = new SimpleDateFormat("EEEE - MMM d", Locale.US); + final Calendar calendar = Calendar.getInstance(); + final Long forecastUNIXDate = (Long) forecast.getDt(); + calendar.setTimeInMillis(forecastUNIXDate * 1000L); + final Date date = calendar.getTime(); + + String tempMax = ""; + if (forecast.getTemp().getMax() != null) { + double conversion = (Double) forecast.getTemp().getMax(); + conversion = tempUnitsConversor.doConversion(conversion); + tempMax = tempFormatter.format(conversion) + tempSymbol; + } + String tempMin = ""; + if (forecast.getTemp().getMin() != null) { + double conversion = (Double) forecast.getTemp().getMin(); + conversion = tempUnitsConversor.doConversion(conversion); + tempMin = tempFormatter.format(conversion) + tempSymbol; + } + Bitmap picture; + if ((forecast.getWeather().size() > 0) && (forecast.getWeather().get(0).getIcon() != null) + && (IconsList.getIcon(forecast.getWeather().get(0).getIcon()) != null)) { + final String icon = forecast.getWeather().get(0).getIcon(); + picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon) + .getResourceDrawable()); + } else { + picture = BitmapFactory.decodeResource(this.getResources(), + R.drawable.weather_severe_alert); + } + + String description = this.getString(R.string.text_field_description_when_error); + if (forecast.getWeather().size() > 0) { + description = forecast.getWeather().get(0).getDescription(); + } + + String humidityValue = ""; + if (forecast.getHumidity() != null) { + final double conversion = (Double) forecast.getHumidity(); + humidityValue = tempFormatter.format(conversion); + } + String pressureValue = ""; + if (forecast.getPressure() != null) { + double conversion = (Double) forecast.getPressure(); + conversion = pressureUnitsConversor.doConversion(conversion); + pressureValue = tempFormatter.format(conversion); + } + String windValue = ""; + if (forecast.getSpeed() != null) { + double conversion = (Double) forecast.getSpeed(); + conversion = windUnitsConversor.doConversion(conversion); + windValue = tempFormatter.format(conversion); + } + String rainValue = ""; + if (forecast.getRain() != null) { + final double conversion = (Double) forecast.getRain(); + rainValue = tempFormatter.format(conversion); + } + String cloudsValue = ""; + if (forecast.getRain() != null) { + final double conversion = (Double) forecast.getClouds(); + cloudsValue = tempFormatter.format(conversion); + } + + String tempDay = ""; + if (forecast.getTemp().getDay() != null) { + double conversion = (Double) forecast.getTemp().getDay(); + conversion = tempUnitsConversor.doConversion(conversion); + tempDay = tempFormatter.format(conversion) + tempSymbol; + } + String tempMorn = ""; + if (forecast.getTemp().getMorn() != null) { + double conversion = (Double) forecast.getTemp().getMorn(); + conversion = tempUnitsConversor.doConversion(conversion); + tempMorn = tempFormatter.format(conversion) + tempSymbol; + } + String tempEve = ""; + if (forecast.getTemp().getEve() != null) { + double conversion = (Double) forecast.getTemp().getEve(); + conversion = tempUnitsConversor.doConversion(conversion); + tempEve = tempFormatter.format(conversion) + tempSymbol; + } + String tempNight = ""; + if (forecast.getTemp().getNight() != null) { + double conversion = (Double) forecast.getTemp().getNight(); + conversion = tempUnitsConversor.doConversion(conversion); + tempNight = tempFormatter.format(conversion) + tempSymbol; + } + + + // 4. Update UI. + this.getActivity().getActionBar().setSubtitle(dayFormatter.format(date).toUpperCase()); + + final TextView tempMaxView = (TextView) getActivity().findViewById(R.id.weather_specific_temp_max); + tempMaxView.setText(tempMax); + final TextView tempMinView = (TextView) getActivity().findViewById(R.id.weather_specific_temp_min); + tempMinView.setText(tempMin); + final ImageView pictureView = (ImageView) getActivity().findViewById(R.id.weather_specific_picture); + pictureView.setImageBitmap(picture); + + final TextView descriptionView = (TextView) getActivity().findViewById(R.id.weather_specific_description); + descriptionView.setText(description); + + final TextView humidityValueView = (TextView) getActivity().findViewById(R.id.weather_specific_humidity_value); + humidityValueView.setText(humidityValue); + ((TextView) getActivity().findViewById(R.id.weather_specific_pressure_value)).setText(pressureValue); + ((TextView) getActivity().findViewById(R.id.weather_specific_pressure_units)).setText(pressureSymbol); + ((TextView) getActivity().findViewById(R.id.weather_specific_wind_value)).setText(windValue); + ((TextView) getActivity().findViewById(R.id.weather_specific_wind_units)).setText(windSymbol); + final TextView rainValueView = (TextView) getActivity().findViewById(R.id.weather_specific_rain_value); + rainValueView.setText(rainValue); + final TextView cloudsValueView = (TextView) getActivity().findViewById(R.id.weather_specific_clouds_value); + cloudsValueView.setText(cloudsValue); + + final TextView tempDayView = (TextView) getActivity().findViewById(R.id.weather_specific_day_temperature); + tempDayView.setText(tempDay); + final TextView tempMornView = (TextView) getActivity().findViewById(R.id.weather_specific_morn_temperature); + tempMornView.setText(tempMorn); + final TextView tempEveView = (TextView) getActivity().findViewById(R.id.weather_specific_eve_temperature); + tempEveView.setText(tempEve); + final TextView tempNightView = (TextView) getActivity().findViewById(R.id.weather_specific_night_temperature); + tempNightView.setText(tempNight); + } + + @Override + public void onResume() { + super.onResume(); + + final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext()); + final Forecast forecast = store.getForecast(); + + if (forecast != null) { + this.updateUI(forecast, this.mChosenDay); + } + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/httpclient/Consts.java b/app/src/main/java/name/gumartinm/weather/information/httpclient/Consts.java new file mode 100644 index 0000000..5cea42a --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/httpclient/Consts.java @@ -0,0 +1,51 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package name.gumartinm.weather.information.httpclient; + +import java.nio.charset.Charset; + +/** + * Commons constants. + * + * @since 4.2 + */ +public final class Consts { + + public static final int CR = 13; // + public static final int LF = 10; // + public static final int SP = 32; // + public static final int HT = 9; // + + public static final Charset UTF_8 = Charset.forName("UTF-8"); + public static final Charset ASCII = Charset.forName("US-ASCII"); + public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); + + private Consts() { + } + +} diff --git a/app/src/main/java/name/gumartinm/weather/information/httpclient/ContentType.java b/app/src/main/java/name/gumartinm/weather/information/httpclient/ContentType.java new file mode 100644 index 0000000..27a8b3d --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/httpclient/ContentType.java @@ -0,0 +1,248 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package name.gumartinm.weather.information.httpclient; + +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.util.Locale; + +import org.apache.http.Header; +import org.apache.http.HeaderElement; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.ParseException; +import org.apache.http.message.BasicHeaderValueParser; + +/** + * Content type information consisting of a MIME type and an optional charset. + *

+ * This class makes no attempts to verify validity of the MIME type. + * The input parameters of the {@link #create(String, String)} method, however, may not + * contain characters <">, <;>, <,> reserved by the HTTP specification. + * + * @since 4.2 + */ + +public final class ContentType { + + // constants + public static final ContentType APPLICATION_ATOM_XML = create( + "application/atom+xml", Consts.ISO_8859_1); + public static final ContentType APPLICATION_FORM_URLENCODED = create( + "application/x-www-form-urlencoded", Consts.ISO_8859_1); + public static final ContentType APPLICATION_JSON = create( + "application/json", Consts.UTF_8); + public static final ContentType APPLICATION_OCTET_STREAM = create( + "application/octet-stream", (Charset) null); + public static final ContentType APPLICATION_SVG_XML = create( + "application/svg+xml", Consts.ISO_8859_1); + public static final ContentType APPLICATION_XHTML_XML = create( + "application/xhtml+xml", Consts.ISO_8859_1); + public static final ContentType APPLICATION_XML = create( + "application/xml", Consts.ISO_8859_1); + public static final ContentType MULTIPART_FORM_DATA = create( + "multipart/form-data", Consts.ISO_8859_1); + public static final ContentType TEXT_HTML = create( + "text/html", Consts.ISO_8859_1); + public static final ContentType TEXT_PLAIN = create( + "text/plain", Consts.ISO_8859_1); + public static final ContentType TEXT_XML = create( + "text/xml", Consts.ISO_8859_1); + public static final ContentType WILDCARD = create( + "*/*", (Charset) null); + + // defaults + public static final ContentType DEFAULT_TEXT = TEXT_PLAIN; + public static final ContentType DEFAULT_BINARY = APPLICATION_OCTET_STREAM; + + private final String mimeType; + private final Charset charset; + + /** + * Given a MIME type and a character set, constructs a ContentType. + * @param mimeType The MIME type to use for the ContentType header. + * @param charset The optional character set to use with the ContentType header. + * @throws UnsupportedCharsetException + * If no support for the named charset is available in this Java virtual machine + */ + ContentType(final String mimeType, final Charset charset) { + this.mimeType = mimeType; + this.charset = charset; + } + + public String getMimeType() { + return this.mimeType; + } + + public Charset getCharset() { + return this.charset; + } + + /** + * Converts a ContentType to a string which can be used as a ContentType header. + * If a charset is provided by the ContentType, it will be included in the string. + */ + @Override + public String toString() { + final StringBuilder buf = new StringBuilder(); + buf.append(this.mimeType); + if (this.charset != null) { + buf.append("; charset="); + buf.append(this.charset); + } + return buf.toString(); + } + + private static boolean valid(final String s) { + for (int i = 0; i < s.length(); i++) { + final char ch = s.charAt(i); + if ((ch == '"') || (ch == ',') || (ch == ';')) { + return false; + } + } + return true; + } + + /** + * Creates a new instance of {@link ContentType}. + * + * @param mimeType MIME type. It may not be null or empty. It may not contain + * characters <">, <;>, <,> reserved by the HTTP specification. + * @param charset charset. + * @return content type + */ + public static ContentType create(final String mimeType, final Charset charset) { + if (mimeType == null) { + throw new IllegalArgumentException("MIME type may not be null"); + } + final String type = mimeType.trim().toLowerCase(Locale.US); + if (type.length() == 0) { + throw new IllegalArgumentException("MIME type may not be empty"); + } + if (!valid(type)) { + throw new IllegalArgumentException("MIME type may not contain reserved characters"); + } + return new ContentType(type, charset); + } + + /** + * Creates a new instance of {@link ContentType} without a charset. + * + * @param mimeType MIME type. It may not be null or empty. It may not contain + * characters <">, <;>, <,> reserved by the HTTP specification. + * @return content type + */ + public static ContentType create(final String mimeType) { + return new ContentType(mimeType, (Charset) null); + } + + /** + * Creates a new instance of {@link ContentType}. + * + * @param mimeType MIME type. It may not be null or empty. It may not contain + * characters <">, <;>, <,> reserved by the HTTP specification. + * @param charset charset. It may not contain characters <">, <;>, <,> reserved by the HTTP + * specification. This parameter is optional. + * @return content type + */ + public static ContentType create( + final String mimeType, final String charset) throws UnsupportedCharsetException { + return create(mimeType, charset != null ? Charset.forName(charset) : null); + } + + private static ContentType create(final HeaderElement helem) { + final String mimeType = helem.getName(); + String charset = null; + final NameValuePair param = helem.getParameterByName("charset"); + if (param != null) { + charset = param.getValue(); + } + return create(mimeType, charset); + } + + /** + * Parses textual representation of Content-Type value. + * + * @param s text + * @return content type + * @throws ParseException if the given text does not represent a valid + * Content-Type value. + */ + public static ContentType parse( + final String s) throws ParseException, UnsupportedCharsetException { + if (s == null) { + throw new IllegalArgumentException("Content type may not be null"); + } + final HeaderElement[] elements = BasicHeaderValueParser.parseElements(s, null); + if (elements.length > 0) { + return create(elements[0]); + } else { + throw new ParseException("Invalid content type: " + s); + } + } + + /** + * Extracts Content-Type value from {@link HttpEntity} exactly as + * specified by the Content-Type header of the entity. Returns null + * if not specified. + * + * @param entity HTTP entity + * @return content type + * @throws ParseException if the given text does not represent a valid + * Content-Type value. + */ + public static ContentType get( + final HttpEntity entity) throws ParseException, UnsupportedCharsetException { + if (entity == null) { + return null; + } + final Header header = entity.getContentType(); + if (header != null) { + final HeaderElement[] elements = header.getElements(); + if (elements.length > 0) { + return create(elements[0]); + } + } + return null; + } + + /** + * Extracts Content-Type value from {@link HttpEntity} or returns default value + * if not explicitly specified. + * + * @param entity HTTP entity + * @return content type + * @throws ParseException if the given text does not represent a valid + * Content-Type value. + */ + public static ContentType getOrDefault(final HttpEntity entity) throws ParseException { + final ContentType contentType = get(entity); + return contentType != null ? contentType : DEFAULT_TEXT; + } + +} diff --git a/app/src/main/java/name/gumartinm/weather/information/httpclient/CustomHTTPClient.java b/app/src/main/java/name/gumartinm/weather/information/httpclient/CustomHTTPClient.java new file mode 100644 index 0000000..44c305b --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/httpclient/CustomHTTPClient.java @@ -0,0 +1,126 @@ +package name.gumartinm.weather.information.httpclient; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.net.URL; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; + +import android.net.http.AndroidHttpClient; + +public class CustomHTTPClient { + private final AndroidHttpClient httpClient; + + public CustomHTTPClient(final AndroidHttpClient httpClient) { + this.httpClient = httpClient; + } + + public String retrieveDataAsString(final URL url) + throws URISyntaxException, ClientProtocolException, IOException { + + final ResponseHandler handler = new ResponseHandler() { + @Override + public String handleResponse( + final HttpResponse response) + throws UnsupportedEncodingException, IOException { + + if (response != null) { + final HttpEntity entity = response.getEntity(); + if (entity != null) { + try { + final ContentType contentType = ContentType.getOrDefault(entity); + final ByteArrayOutputStream buffer = CustomHTTPClient.this + .sortResponse(response); + return new String(buffer.toByteArray(), contentType.getCharset()); + } finally { + entity.consumeContent(); + } + } + + throw new IOException("There is no entity"); + } + + throw new IOException("There is no response"); + } + }; + + final HttpGet httpGet = new HttpGet(); + httpGet.setURI(url.toURI()); + + return this.httpClient.execute(httpGet, handler); + } + + public ByteArrayOutputStream retrieveRawData(final URL url) + throws URISyntaxException, ClientProtocolException, IOException { + final ResponseHandler handler = new ResponseHandler() { + + @Override + public ByteArrayOutputStream handleResponse( + final HttpResponse response) + throws UnsupportedEncodingException, IOException { + + if (response != null) { + final HttpEntity entity = response.getEntity(); + if (entity != null) { + try { + return CustomHTTPClient.this.sortResponse(response); + } finally { + entity.consumeContent(); + } + } + + throw new IOException("There is no entity"); + } + + throw new IOException("There is no response"); + } + }; + + final HttpGet httpGet = new HttpGet(); + httpGet.setURI(url.toURI()); + + return this.httpClient.execute(httpGet, handler); + } + + public void close() { + this.httpClient.close(); + } + + private ByteArrayOutputStream sortResponse(final HttpResponse httpResponse) throws IOException { + + if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + throw new IOException("Unexpected response code: " + + httpResponse.getStatusLine().getStatusCode()); + } + + final HttpEntity entity = httpResponse.getEntity(); + final InputStream inputStream = entity.getContent(); + try { + return this.readInputStream(inputStream); + } finally { + inputStream.close(); + } + + } + + private ByteArrayOutputStream readInputStream (final InputStream inputStream) throws IOException { + final ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); + final int bufferSize = 1024; + final byte[] buffer = new byte[bufferSize]; + + int len = 0; + while ((len = inputStream.read(buffer)) != -1) { + byteBuffer.write(buffer, 0, len); + } + + return byteBuffer; + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/DatabaseQueries.java b/app/src/main/java/name/gumartinm/weather/information/model/DatabaseQueries.java new file mode 100644 index 0000000..77bc28a --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/DatabaseQueries.java @@ -0,0 +1,44 @@ +package name.gumartinm.weather.information.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/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocation.java b/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocation.java new file mode 100644 index 0000000..d1218f4 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocation.java @@ -0,0 +1,99 @@ +package name.gumartinm.weather.information.model; + +import java.io.Serializable; +import java.util.Date; + + +public class WeatherLocation implements Serializable { + 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; + private boolean isNew; + + public WeatherLocation setId(int id) { + this.id = id; + return this; + } + + public WeatherLocation setCity(String city) { + this.city = city; + return this; + } + + public WeatherLocation setCountry(String country) { + this.country = country; + return this; + } + + public WeatherLocation setIsSelected(boolean isSelected) { + this.isSelected = isSelected; + return this; + } + + public WeatherLocation setLatitude(double latitude) { + this.latitude = latitude; + return this; + } + + public WeatherLocation setLongitude(double longitude) { + this.longitude = longitude; + return this; + } + + public WeatherLocation setLastCurrentUIUpdate(Date lastCurrentUIUpdate) { + this.lastCurrentUIUpdate = lastCurrentUIUpdate; + return this; + } + + public WeatherLocation setLastForecastUIUpdate(Date lastForecastUIUpdate) { + this.lastForecastUIUpdate = lastForecastUIUpdate; + return this; + } + + public WeatherLocation setIsNew(final boolean isNew) { + this.isNew = isNew; + 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; + } + + public double getLongitude() { + return this.longitude; + } + + public Date getLastCurrentUIUpdate() { + return this.lastCurrentUIUpdate; + } + + public Date getLastForecastUIUpdate() { + return this.lastForecastUIUpdate; + } + + public boolean getIsNew() { + return this.isNew; + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocationContract.java b/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocationContract.java new file mode 100644 index 0000000..25a04e9 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocationContract.java @@ -0,0 +1,34 @@ +package name.gumartinm.weather.information.model; + +import android.provider.BaseColumns; + +public class WeatherLocationContract { + + // This class can't be instantiated + private WeatherLocationContract() {} + + public static final class WeatherLocation implements BaseColumns { + + // This class can't be instantiated + private WeatherLocation() {} + + public static final String TABLE_NAME = "locations"; + + public static final String COLUMN_NAME_IS_SELECTED = "isSelected"; + + public static final String COLUMN_NAME_LATITUDE = "latitude"; + + public static final String COLUMN_NAME_LONGITUDE = "longitude"; + + public static final String COLUMN_NAME_COUNTRY = "country"; + + public static final String COLUMN_NAME_CITY = "city"; + + public static final String COLUMN_NAME_LAST_FORECAST_UI_UPDATE = "lastForecastUpdate"; + + public static final String COLUMN_NAME_LAST_CURRENT_UI_UPDATE = "lastCurrentUpdate"; + + public static final String COLUMN_NAME_IS_NEW = "isNew"; + } + +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocationDbHelper.java b/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocationDbHelper.java new file mode 100644 index 0000000..299423f --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocationDbHelper.java @@ -0,0 +1,44 @@ +package name.gumartinm.weather.information.model; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +public class WeatherLocationDbHelper extends SQLiteOpenHelper { + private static final String TAG = "LocationDbHelper"; + public static final int DATABASE_VERSION = 1; + public static final String DATABASE_NAME = "Location.db"; + + public WeatherLocationDbHelper(final Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(final SQLiteDatabase db) { + db.execSQL("CREATE TABLE " + WeatherLocationContract.WeatherLocation.TABLE_NAME + " (" + + WeatherLocationContract.WeatherLocation._ID + " INTEGER PRIMARY KEY, " + + WeatherLocationContract.WeatherLocation.COLUMN_NAME_CITY + " TEXT" + " NOT NULL, " + + WeatherLocationContract.WeatherLocation.COLUMN_NAME_COUNTRY + " TEXT" + " NOT NULL, " + + WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED + " INTEGER" + " NOT NULL, " + + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE + " INTEGER, " + + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE + " INTEGER, " + + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE + " REAL" + " NOT NULL, " + + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE + " REAL" + " NOT NULL, " + + WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_NEW + " INTEGER" + " NOT NULL " + + ");"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + + newVersion + ", which will destroy all old data"); + + // Kills the table and existing data + db.execSQL("DROP TABLE IF EXISTS " + WeatherLocationContract.WeatherLocation.TABLE_NAME); + + // Recreates the database with a new version + onCreate(db); + } + +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocationDbQueries.java b/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocationDbQueries.java new file mode 100644 index 0000000..d4e8622 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/WeatherLocationDbQueries.java @@ -0,0 +1,180 @@ +package name.gumartinm.weather.information.model; + +import java.util.Date; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +public class WeatherLocationDbQueries { + private final SQLiteOpenHelper mDbHelper; + + public interface DoQuery { + + public WeatherLocation doQuery(final Cursor cursor); + } + + public WeatherLocationDbQueries(final SQLiteOpenHelper dbHelper) { + this.mDbHelper = dbHelper; + } + + public WeatherLocation queryDataBase() { + final String selection = WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED + " = ?"; + final String[] selectionArgs = { "1" }; + final String[] projection = { + WeatherLocationContract.WeatherLocation._ID, + WeatherLocationContract.WeatherLocation.COLUMN_NAME_CITY, + WeatherLocationContract.WeatherLocation.COLUMN_NAME_COUNTRY, + WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED, + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE, + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE, + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE, + WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE, + WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_NEW + }; + + + final WeatherLocationDbQueries.DoQuery doQuery = new WeatherLocationDbQueries.DoQuery() { + + @Override + public WeatherLocation doQuery(final Cursor cursor) { + final int id = cursor.getInt(cursor.getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation._ID)); + final String city = cursor.getString(cursor. + getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_CITY)); + final String country = cursor.getString(cursor. + getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_COUNTRY)); + final boolean isSelected = (cursor.getInt(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_SELECTED)) != 0); + Date lastCurrentUIUpdate = null; + if (!cursor.isNull(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE))) { + final long javaTime = cursor.getLong(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE)); + lastCurrentUIUpdate = new Date(javaTime); + } + Date lasForecastUIUpdate = null; + if (!cursor.isNull(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE))) { + final long javaTime = cursor.getLong(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE)); + lasForecastUIUpdate = new Date(javaTime); + } + final double latitude = cursor.getDouble(cursor. + getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE)); + final double longitude = cursor.getDouble(cursor. + getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE)); + final boolean isNew = (cursor.getInt(cursor + .getColumnIndexOrThrow(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_NEW)) != 0); + + + return new WeatherLocation() + .setId(id) + .setCity(city) + .setCountry(country) + .setIsSelected(isSelected) + .setLastCurrentUIUpdate(lastCurrentUIUpdate) + .setLastForecastUIUpdate(lasForecastUIUpdate) + .setLatitude(latitude) + .setLongitude(longitude) + .setIsNew(isNew); + } + }; + + return this.queryDataBase( + 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) { + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE, javaTime.getTime()); + } + javaTime = weatherLocation.getLastForecastUIUpdate(); + if (javaTime != null) { + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE, javaTime.getTime()); + } + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LATITUDE, weatherLocation.getLatitude()); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LONGITUDE, weatherLocation.getLongitude()); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_NEW, weatherLocation.getIsNew()); + + 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()); + Date javaTime = weatherLocation.getLastCurrentUIUpdate(); + if (javaTime != null) { + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE, javaTime.getTime()); + } else { + values.putNull(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_CURRENT_UI_UPDATE); + } + javaTime = weatherLocation.getLastForecastUIUpdate(); + if (javaTime != null) { + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_LAST_FORECAST_UI_UPDATE, javaTime.getTime()); + } else { + 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()); + values.put(WeatherLocationContract.WeatherLocation.COLUMN_NAME_IS_NEW, weatherLocation.getIsNew()); + + 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, + final String selection, final DoQuery doQuery) { + final SQLiteDatabase db = this.mDbHelper.getReadableDatabase(); + try { + final Cursor cursor = db.query(table, projection, selection, selectionArgs, null, null, null); + try { + if (!cursor.moveToFirst()) { + return null; + } + else { + return doQuery.doQuery(cursor); + } + } finally { + cursor.close(); + } + } finally { + db.close(); + } + } + + // 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.getWritableDatabase(); + try { + return db.update(table, values, selection, selectionArgs); + } finally { + db.close(); + } + } + +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Clouds.java b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Clouds.java new file mode 100644 index 0000000..cd6ffe1 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Clouds.java @@ -0,0 +1,22 @@ +package name.gumartinm.weather.information.model.currentweather; + +import java.io.Serializable; + +public class Clouds implements Serializable { + private static final long serialVersionUID = 3034435739326030899L; + private Number all; + + public Number getAll(){ + return this.all; + } + public void setAll(final Number all){ + this.all = all; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Clouds [all=").append(this.all).append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Coord.java b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Coord.java new file mode 100644 index 0000000..843403b --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Coord.java @@ -0,0 +1,30 @@ +package name.gumartinm.weather.information.model.currentweather; + +import java.io.Serializable; + +public class Coord implements Serializable { + private static final long serialVersionUID = 7151637605146377486L; + private Number lat; + private Number lon; + + public Number getLat(){ + return this.lat; + } + public void setLat(final Number lat){ + this.lat = lat; + } + public Number getLon(){ + return this.lon; + } + public void setLon(final Number lon){ + this.lon = lon; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Coord [lat=").append(this.lat).append(", lon=").append(this.lon) + .append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Current.java b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Current.java new file mode 100644 index 0000000..6d7e652 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Current.java @@ -0,0 +1,139 @@ +package name.gumartinm.weather.information.model.currentweather; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * Auto generated by: http://jsongen.byingtondesign.com/ + * (with my own modifications) + * + */ +public class Current implements Serializable { + private static final long serialVersionUID = -730690341739860818L; + private String base; + private Clouds clouds; + private Number cod; + private Coord coord; + private Number dt; + private Number id; + private Main main; + private String name; + private Rain rain; + private Snow snow; + private Sys sys; + private List weather; + private Wind wind; + private byte[] iconData; + private Date date; + + public String getBase(){ + return this.base; + } + public void setBase(final String base){ + this.base = base; + } + public Clouds getClouds(){ + return this.clouds; + } + public void setClouds(final Clouds clouds){ + this.clouds = clouds; + } + + public Number getCod() { + return this.cod; + } + + public void setCod(final Number cod) { + this.cod = cod; + } + public Coord getCoord(){ + return this.coord; + } + public void setCoord(final Coord coord){ + this.coord = coord; + } + public Number getDt(){ + return this.dt; + } + public void setDt(final Number dt){ + this.dt = dt; + } + public Number getId(){ + return this.id; + } + public void setId(final Number id){ + this.id = id; + } + public Main getMain(){ + return this.main; + } + public void setMain(final Main main){ + this.main = main; + } + public String getName(){ + return this.name; + } + public void setName(final String name){ + this.name = name; + } + public Rain getRain(){ + return this.rain; + } + public void setRain(final Rain rain){ + this.rain = rain; + } + public Snow getSnow() { + return this.snow; + } + public void setSnow(final Snow snow) { + this.snow = snow; + } + public Sys getSys(){ + return this.sys; + } + public void setSys(final Sys sys){ + this.sys = sys; + } + public List getWeather(){ + return this.weather; + } + public void setWeather(final List weather){ + this.weather = weather; + } + public Wind getWind(){ + return this.wind; + } + public void setWind(final Wind wind){ + this.wind = wind; + } + + public byte[] getIconData() { + return this.iconData; + } + + public void setIconData(final byte[] iconData) { + this.iconData = iconData; + } + + public Date getDate() { + return this.date; + } + + public void setDate(final Date date) { + this.date = date; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Current [base=").append(this.base).append(", clouds=") + .append(this.clouds).append(", cod=").append(this.cod).append(", coord=") + .append(this.coord).append(", dt=").append(this.dt).append(", id=").append(this.id) + .append(", main=").append(this.main).append(", name=").append(this.name) + .append(", rain=").append(this.rain).append(", snow=").append(this.snow) + .append(", sys=").append(this.sys).append(", weather=").append(this.weather) + .append(", wind=").append(this.wind).append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Main.java b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Main.java new file mode 100644 index 0000000..2e196aa --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Main.java @@ -0,0 +1,73 @@ +package name.gumartinm.weather.information.model.currentweather; + +import java.io.Serializable; + +public class Main implements Serializable { + private static final long serialVersionUID = -6000879164436289447L; + private Number grnd_level; + private Number humidity; + private Number pressure; + private Number sea_level; + private Number temp; + private Number temp_max; + private Number temp_min; + + public Number getGrnd_level() { + return this.grnd_level; + } + + public void setGrnd_level(final Number grnd_level) { + this.grnd_level = grnd_level; + } + + public Number getHumidity(){ + return this.humidity; + } + public void setHumidity(final Number humidity){ + this.humidity = humidity; + } + public Number getPressure(){ + return this.pressure; + } + public void setPressure(final Number pressure){ + this.pressure = pressure; + } + + public Number getSea_level() { + return this.sea_level; + } + + public void setSea_level(final Number sea_level) { + this.sea_level = sea_level; + } + + public Number getTemp(){ + return this.temp; + } + public void setTemp(final Number temp){ + this.temp = temp; + } + public Number getTemp_max(){ + return this.temp_max; + } + public void setTemp_max(final Number temp_max){ + this.temp_max = temp_max; + } + public Number getTemp_min(){ + return this.temp_min; + } + public void setTemp_min(final Number temp_min){ + this.temp_min = temp_min; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Main [grnd_level=").append(this.grnd_level).append(", humidity=") + .append(this.humidity).append(", pressure=").append(this.pressure) + .append(", sea_level=").append(this.sea_level).append(", temp=").append(this.temp) + .append(", temp_max=").append(this.temp_max).append(", temp_min=") + .append(this.temp_min).append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Rain.java b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Rain.java new file mode 100644 index 0000000..0c59700 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Rain.java @@ -0,0 +1,23 @@ +package name.gumartinm.weather.information.model.currentweather; + +import java.io.Serializable; + +public class Rain implements Serializable { + private static final long serialVersionUID = 1318464783605029435L; + private Number three; + + public Number get3h(){ + return this.three; + } + + public void set3h(final Number threeh) { + this.three = threeh; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Rain [three=").append(this.three).append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Snow.java b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Snow.java new file mode 100644 index 0000000..1e4ee57 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Snow.java @@ -0,0 +1,23 @@ +package name.gumartinm.weather.information.model.currentweather; + +import java.io.Serializable; + +public class Snow implements Serializable { + private static final long serialVersionUID = 6769716772818311879L; + private Number three; + + public Number get3h() { + return this.three; + } + + public void set3h(final Number threeh) { + this.three = threeh; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Snow [three=").append(this.three).append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Sys.java b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Sys.java new file mode 100644 index 0000000..015a9c2 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Sys.java @@ -0,0 +1,46 @@ +package name.gumartinm.weather.information.model.currentweather; + +import java.io.Serializable; + + +public class Sys implements Serializable { + private static final long serialVersionUID = 5333083785731053139L; + private String country; + private Number message; + private Number sunrise; + private Number sunset; + + public String getCountry(){ + return this.country; + } + public void setCountry(final String country){ + this.country = country; + } + public Number getMessage(){ + return this.message; + } + public void setMessage(final Number message){ + this.message = message; + } + public Number getSunrise(){ + return this.sunrise; + } + public void setSunrise(final Number sunrise){ + this.sunrise = sunrise; + } + public Number getSunset(){ + return this.sunset; + } + public void setSunset(final Number sunset){ + this.sunset = sunset; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Sys [country=").append(this.country).append(", message=") + .append(this.message).append(", sunrise=").append(this.sunrise).append(", sunset=") + .append(this.sunset).append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Weather.java b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Weather.java new file mode 100644 index 0000000..17aa7e5 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Weather.java @@ -0,0 +1,45 @@ +package name.gumartinm.weather.information.model.currentweather; + +import java.io.Serializable; + +public class Weather implements Serializable { + private static final long serialVersionUID = -34336548786316655L; + private String description; + private String icon; + private Number id; + private String main; + + public String getDescription(){ + return this.description; + } + public void setDescription(final String description){ + this.description = description; + } + public String getIcon(){ + return this.icon; + } + public void setIcon(final String icon){ + this.icon = icon; + } + public Number getId(){ + return this.id; + } + public void setId(final Number id){ + this.id = id; + } + public String getMain(){ + return this.main; + } + public void setMain(final String main){ + this.main = main; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Weather [description=").append(this.description).append(", icon=") + .append(this.icon).append(", id=").append(this.id).append(", main=") + .append(this.main).append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Wind.java b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Wind.java new file mode 100644 index 0000000..a39410d --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/currentweather/Wind.java @@ -0,0 +1,30 @@ +package name.gumartinm.weather.information.model.currentweather; + +import java.io.Serializable; + +public class Wind implements Serializable { + private static final long serialVersionUID = 5495842422633674631L; + private Number deg; + private Number speed; + + public Number getDeg(){ + return this.deg; + } + public void setDeg(final Number deg){ + this.deg = deg; + } + public Number getSpeed(){ + return this.speed; + } + public void setSpeed(final Number speed){ + this.speed = speed; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Wind [deg=").append(this.deg).append(", speed=").append(this.speed) + .append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/City.java b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/City.java new file mode 100644 index 0000000..1dc3914 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/City.java @@ -0,0 +1,53 @@ +package name.gumartinm.weather.information.model.forecastweather; + +import java.io.Serializable; + + +public class City implements Serializable { + private static final long serialVersionUID = 3079687975077030704L; + private Coord coord; + private String country; + private Number id; + private String name; + private Number population; + + public Coord getCoord(){ + return this.coord; + } + public void setCoord(final Coord coord){ + this.coord = coord; + } + public String getCountry(){ + return this.country; + } + public void setCountry(final String country){ + this.country = country; + } + public Number getId(){ + return this.id; + } + public void setId(final Number id){ + this.id = id; + } + public String getName(){ + return this.name; + } + public void setName(final String name){ + this.name = name; + } + public Number getPopulation(){ + return this.population; + } + public void setPopulation(final Number population){ + this.population = population; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("City [coord=").append(this.coord).append(", country=").append(this.country) + .append(", id=").append(this.id).append(", name=").append(this.name) + .append(", population=").append(this.population).append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Coord.java b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Coord.java new file mode 100644 index 0000000..eb6e57a --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Coord.java @@ -0,0 +1,30 @@ +package name.gumartinm.weather.information.model.forecastweather; + +import java.io.Serializable; + +public class Coord implements Serializable { + private static final long serialVersionUID = 8069257976701986700L; + private Number lat; + private Number lon; + + public Number getLat(){ + return this.lat; + } + public void setLat(final Number lat){ + this.lat = lat; + } + public Number getLon(){ + return this.lon; + } + public void setLon(final Number lon){ + this.lon = lon; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Coord [lat=").append(this.lat).append(", lon=").append(this.lon) + .append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Forecast.java b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Forecast.java new file mode 100644 index 0000000..336a3bc --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Forecast.java @@ -0,0 +1,62 @@ +package name.gumartinm.weather.information.model.forecastweather; + +import java.io.Serializable; +import java.util.List; + +/** + * Auto generated by: http://jsongen.byingtondesign.com/ + * (with my own modifications) + * + */ +public class Forecast implements Serializable { + private static final long serialVersionUID = 5095443678019686190L; + private City city; + private Number cnt; + private Number cod; + private List list; + private Number message; + + public City getCity(){ + return this.city; + } + public void setCity(final City city){ + this.city = city; + } + public Number getCnt(){ + return this.cnt; + } + public void setCnt(final Number cnt){ + this.cnt = cnt; + } + + public Number getCod() { + return this.cod; + } + + public void setCod(final Number cod) { + this.cod = cod; + } + + public List getList() { + return this.list; + } + + public void setList(final List list) { + this.list = list; + } + public Number getMessage(){ + return this.message; + } + public void setMessage(final Number message){ + this.message = message; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Forecast [city=").append(this.city).append(", cnt=") + .append(this.cnt).append(", cod=").append(this.cod).append(", list=") + .append(this.list).append(", message=").append(this.message).append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/List.java b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/List.java new file mode 100644 index 0000000..6366df2 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/List.java @@ -0,0 +1,93 @@ +package name.gumartinm.weather.information.model.forecastweather; + +import java.io.Serializable; + + +public class List implements Serializable { + private static final long serialVersionUID = 838468273188666785L; + private Number clouds; + private Number deg; + private Number dt; + private Number humidity; + private Number pressure; + private Number rain; + private Number snow; + private Number speed; + private Temp temp; + private java.util.List weather; + + public Number getClouds(){ + return this.clouds; + } + public void setClouds(final Number clouds){ + this.clouds = clouds; + } + public Number getDeg(){ + return this.deg; + } + public void setDeg(final Number deg){ + this.deg = deg; + } + public Number getDt(){ + return this.dt; + } + public void setDt(final Number dt){ + this.dt = dt; + } + public Number getHumidity(){ + return this.humidity; + } + public void setHumidity(final Number humidity){ + this.humidity = humidity; + } + public Number getPressure(){ + return this.pressure; + } + public void setPressure(final Number pressure){ + this.pressure = pressure; + } + public Number getRain(){ + return this.rain; + } + public void setRain(final Number rain){ + this.rain = rain; + } + public Number getSnow() { + return this.snow; + } + public void setSnow(final Number snow) { + this.snow = snow; + } + public Number getSpeed(){ + return this.speed; + } + public void setSpeed(final Number speed){ + this.speed = speed; + } + public Temp getTemp(){ + return this.temp; + } + public void setTemp(final Temp temp){ + this.temp = temp; + } + + public java.util.List getWeather() { + return this.weather; + } + + public void setWeather(final java.util.List weather) { + this.weather = weather; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("List [clouds=").append(this.clouds).append(", deg=").append(this.deg) + .append(", dt=").append(this.dt).append(", humidity=").append(this.humidity) + .append(", pressure=").append(this.pressure).append(", rain=").append(this.rain) + .append(", snow=").append(this.snow).append(", speed=").append(this.speed) + .append(", temp=").append(this.temp).append(", weather=").append(this.weather) + .append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Temp.java b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Temp.java new file mode 100644 index 0000000..fdb454a --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Temp.java @@ -0,0 +1,60 @@ +package name.gumartinm.weather.information.model.forecastweather; + +import java.io.Serializable; + +public class Temp implements Serializable { + private static final long serialVersionUID = -7614799035018271127L; + private Number day; + private Number eve; + private Number max; + private Number min; + private Number morn; + private Number night; + + public Number getDay(){ + return this.day; + } + public void setDay(final Number day){ + this.day = day; + } + public Number getEve(){ + return this.eve; + } + public void setEve(final Number eve){ + this.eve = eve; + } + public Number getMax(){ + return this.max; + } + public void setMax(final Number max){ + this.max = max; + } + public Number getMin(){ + return this.min; + } + public void setMin(final Number min){ + this.min = min; + } + public Number getMorn(){ + return this.morn; + } + public void setMorn(final Number morn){ + this.morn = morn; + } + public Number getNight(){ + return this.night; + } + public void setNight(final Number night){ + this.night = night; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Temp [day=").append(this.day).append(", eve=").append(this.eve) + .append(", max=").append(this.max).append(", min=").append(this.min) + .append(", morn=").append(this.morn).append(", night=").append(this.night) + .append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Weather.java b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Weather.java new file mode 100644 index 0000000..93472d0 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/model/forecastweather/Weather.java @@ -0,0 +1,45 @@ +package name.gumartinm.weather.information.model.forecastweather; + +import java.io.Serializable; + +public class Weather implements Serializable { + private static final long serialVersionUID = -5066357704517363241L; + private String description; + private String icon; + private Number id; + private String main; + + public String getDescription(){ + return this.description; + } + public void setDescription(final String description){ + this.description = description; + } + public String getIcon(){ + return this.icon; + } + public void setIcon(final String icon){ + this.icon = icon; + } + public Number getId(){ + return this.id; + } + public void setId(final Number id){ + this.id = id; + } + public String getMain(){ + return this.main; + } + public void setMain(final String main){ + this.main = main; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Weather [description=").append(this.description).append(", icon=") + .append(this.icon).append(", id=").append(this.id).append(", main=") + .append(this.main).append("]"); + return builder.toString(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/notification/NotificationIntentService.java b/app/src/main/java/name/gumartinm/weather/information/notification/NotificationIntentService.java new file mode 100644 index 0000000..3b9dcd7 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/notification/NotificationIntentService.java @@ -0,0 +1,232 @@ +package name.gumartinm.weather.information.notification; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.Locale; + +import org.apache.http.client.ClientProtocolException; + +import android.app.IntentService; +import android.app.Notification; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.http.AndroidHttpClient; +import android.preference.PreferenceManager; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; +import android.support.v4.app.TaskStackBuilder; +import android.util.Log; +import android.widget.RemoteViews; + +import com.fasterxml.jackson.core.JsonParseException; +import name.gumartinm.weather.information.R; +import name.gumartinm.weather.information.activity.WeatherTabsActivity; +import name.gumartinm.weather.information.httpclient.CustomHTTPClient; +import name.gumartinm.weather.information.model.DatabaseQueries; +import name.gumartinm.weather.information.model.WeatherLocation; +import name.gumartinm.weather.information.model.currentweather.Current; +import name.gumartinm.weather.information.parser.JPOSWeatherParser; +import name.gumartinm.weather.information.service.IconsList; +import name.gumartinm.weather.information.service.ServiceParser; + + +public class NotificationIntentService extends IntentService { + private static final String TAG = "NotificationIntentService"; + + + public NotificationIntentService() { + super("NIS-Thread"); + } + + @Override + protected void onHandleIntent(final Intent intent) { + final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext()); + final WeatherLocation weatherLocation = query.queryDataBase(); + + if (weatherLocation != null) { + final ServiceParser weatherService = new ServiceParser(new JPOSWeatherParser()); + final CustomHTTPClient HTTPClient = new CustomHTTPClient( + AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")); + + Current current = null; + try { + current = this.doInBackgroundThrowable(weatherLocation, HTTPClient, weatherService); + + } catch (final JsonParseException e) { + Log.e(TAG, "doInBackground exception: ", e); + } catch (final ClientProtocolException e) { + Log.e(TAG, "doInBackground exception: ", e); + } catch (final MalformedURLException e) { + Log.e(TAG, "doInBackground exception: ", e); + } catch (final URISyntaxException e) { + Log.e(TAG, "doInBackground exception: ", e); + } catch (final IOException e) { + // logger infrastructure swallows UnknownHostException :/ + Log.e(TAG, "doInBackground exception: " + e.getMessage(), e); + } finally { + HTTPClient.close(); + } + + if (current != null) { + this.showNotification(current, weatherLocation); + } + } + } + + private Current doInBackgroundThrowable(final WeatherLocation weatherLocation, + final CustomHTTPClient HTTPClient, final ServiceParser weatherService) + throws ClientProtocolException, MalformedURLException, URISyntaxException, + JsonParseException, IOException { + + final String APIVersion = this.getResources().getString(R.string.api_version); + + final String urlAPI = this.getResources().getString(R.string.uri_api_weather_today); + final String url = weatherService.createURIAPICurrent(urlAPI, APIVersion, + weatherLocation.getLatitude(), weatherLocation.getLongitude()); + final String urlWithoutCache = url.concat("&time=" + System.currentTimeMillis()); + final String jsonData = HTTPClient.retrieveDataAsString(new URL(urlWithoutCache)); + + return weatherService.retrieveCurrentFromJPOS(jsonData); + } + + private interface UnitsConversor { + + public double doConversion(final double value); + } + + private void showNotification(final Current current, final WeatherLocation weatherLocation) { + final SharedPreferences sharedPreferences = PreferenceManager + .getDefaultSharedPreferences(this.getApplicationContext()); + + // TODO: repeating the same code in Overview, Specific and Current!!! + // 1. Update units of measurement. + // 1.1 Temperature + String tempSymbol; + UnitsConversor tempUnitsConversor; + final String keyPreference = this.getApplicationContext().getString(R.string.weather_preferences_notifications_temperature_key); + final String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); + final String unitsPreferenceValue = sharedPreferences.getString( + keyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); + if (unitsPreferenceValue.equals(values[0])) { + tempSymbol = values[0]; + tempUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return value - 273.15; + } + + }; + } else if (unitsPreferenceValue.equals(values[1])) { + tempSymbol = values[1]; + tempUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return (value * 1.8) - 459.67; + } + + }; + } else { + tempSymbol = values[2]; + tempUnitsConversor = new UnitsConversor(){ + + @Override + public double doConversion(final double value) { + return value; + } + + }; + } + + + // 2. Formatters + final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); + tempFormatter.applyPattern("#####.#####"); + + + // 3. Prepare data for RemoteViews. + String tempMax = ""; + if (current.getMain().getTemp_max() != null) { + double conversion = (Double) current.getMain().getTemp_max(); + conversion = tempUnitsConversor.doConversion(conversion); + tempMax = tempFormatter.format(conversion) + tempSymbol; + } + String tempMin = ""; + if (current.getMain().getTemp_min() != null) { + double conversion = (Double) current.getMain().getTemp_min(); + conversion = tempUnitsConversor.doConversion(conversion); + tempMin = tempFormatter.format(conversion) + tempSymbol; + } + Bitmap picture; + if ((current.getWeather().size() > 0) + && (current.getWeather().get(0).getIcon() != null) + && (IconsList.getIcon(current.getWeather().get(0).getIcon()) != null)) { + final String icon = current.getWeather().get(0).getIcon(); + picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon) + .getResourceDrawable()); + } else { + picture = BitmapFactory.decodeResource(this.getResources(), + R.drawable.weather_severe_alert); + } + final String city = weatherLocation.getCity(); + final String country = weatherLocation.getCountry(); + + // 4. Insert data in RemoteViews. + final RemoteViews remoteView = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.notification); + remoteView.setImageViewBitmap(R.id.weather_notification_image, picture); + remoteView.setTextViewText(R.id.weather_notification_temperature_max, tempMax); + remoteView.setTextViewText(R.id.weather_notification_temperature_min, tempMin); + remoteView.setTextViewText(R.id.weather_notification_city, city); + remoteView.setTextViewText(R.id.weather_notification_country, country); + + // 5. Activity launcher. + final Intent resultIntent = new Intent(this.getApplicationContext(), WeatherTabsActivity.class); + // The PendingIntent to launch our activity if the user selects this notification +// final PendingIntent contentIntent = PendingIntent.getActivity( +// this.getApplicationContext(), 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT); + // The stack builder object will contain an artificial back stack for the started Activity. + // This ensures that navigating backward from the Activity leads out of + // your application to the Home screen. + final TaskStackBuilder stackBuilder = TaskStackBuilder.create(this.getApplicationContext()); + // Adds the back stack for the Intent (but not the Intent itself) + stackBuilder.addParentStack(WeatherTabsActivity.class); + // Adds the Intent that starts the Activity to the top of the stack + stackBuilder.addNextIntent(resultIntent); + final PendingIntent resultPendingIntent = + stackBuilder.getPendingIntent( + 0, + PendingIntent.FLAG_UPDATE_CURRENT + ); + + final NotificationManagerCompat notificationManager = + NotificationManagerCompat.from(this.getApplicationContext()); + + + // 6. Create notification. + final NotificationCompat.Builder notificationBuilder = + new NotificationCompat.Builder(this.getApplicationContext()) + .setContent(remoteView) + .setSmallIcon(R.drawable.ic_launcher) + .setAutoCancel(true) + .setLocalOnly(true) + .setWhen(System.currentTimeMillis()) + .setContentIntent(resultPendingIntent) + .setPriority(NotificationCompat.PRIORITY_DEFAULT); + + final Notification notification = notificationBuilder.build(); + notification.flags |= Notification.FLAG_AUTO_CANCEL; + + // Send the notification. + // Sets an ID for the notification, so it can be updated (just in case) + int notifyID = 1; + notificationManager.notify(notifyID, notification); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/parser/IJPOSParser.java b/app/src/main/java/name/gumartinm/weather/information/parser/IJPOSParser.java new file mode 100644 index 0000000..bdd501f --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/parser/IJPOSParser.java @@ -0,0 +1,17 @@ +package name.gumartinm.weather.information.parser; + +import com.fasterxml.jackson.core.JsonParseException; +import name.gumartinm.weather.information.model.currentweather.Current; +import name.gumartinm.weather.information.model.forecastweather.Forecast; + +import java.io.IOException; + + +public interface IJPOSParser { + + public Current retrieveCurrenFromJPOS(final String jsonData) + throws JsonParseException, IOException; + + public Forecast retrieveForecastFromJPOS(final String jsonData) + throws JsonParseException, IOException; +} diff --git a/app/src/main/java/name/gumartinm/weather/information/parser/JPOSWeatherParser.java b/app/src/main/java/name/gumartinm/weather/information/parser/JPOSWeatherParser.java new file mode 100644 index 0000000..176356c --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/parser/JPOSWeatherParser.java @@ -0,0 +1,405 @@ +package name.gumartinm.weather.information.parser; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import name.gumartinm.weather.information.model.currentweather.Clouds; +import name.gumartinm.weather.information.model.currentweather.Current; +import name.gumartinm.weather.information.model.currentweather.Main; +import name.gumartinm.weather.information.model.currentweather.Rain; +import name.gumartinm.weather.information.model.currentweather.Snow; +import name.gumartinm.weather.information.model.currentweather.Sys; +import name.gumartinm.weather.information.model.currentweather.Wind; +import name.gumartinm.weather.information.model.forecastweather.City; +import name.gumartinm.weather.information.model.forecastweather.Forecast; +import name.gumartinm.weather.information.model.forecastweather.Temp; + +import java.io.IOException; +import java.util.ArrayList; + +public class JPOSWeatherParser implements IJPOSParser { + + @Override + public Current retrieveCurrenFromJPOS(final String jsonData) + throws JsonParseException, IOException { + final JsonFactory f = new JsonFactory(); + + final Current currentWeatherData = new Current(); + currentWeatherData.setClouds(new Clouds()); + currentWeatherData.setCoord(new name.gumartinm.weather.information.model.currentweather.Coord()); + currentWeatherData.setMain(new Main()); + currentWeatherData.setRain(new Rain()); + currentWeatherData.setSys(new Sys()); + currentWeatherData.setSnow(new Snow()); + currentWeatherData + .setWeather(new ArrayList()); + currentWeatherData.setWind(new Wind()); + final JsonParser jParser = f.createParser(jsonData); + + this.getCurrentWeatherData(currentWeatherData, jParser); + + return currentWeatherData; + } + + @Override + public Forecast retrieveForecastFromJPOS(final String jsonData) + throws JsonParseException, IOException { + final JsonFactory f = new JsonFactory(); + + final Forecast forecastWeatherData = new Forecast(); + forecastWeatherData + .setList(new ArrayList(15)); + final City city = new City(); + city.setCoord(new name.gumartinm.weather.information.model.forecastweather.Coord()); + forecastWeatherData.setCity(city); + final JsonParser jParser = f.createParser(jsonData); + + this.getForecastWeatherData(forecastWeatherData, jParser); + + return forecastWeatherData; + } + + private void getCurrentWeatherData(final Current currentWeatherData, + final JsonParser jParser) throws JsonParseException, IOException { + if (jParser.nextToken() == JsonToken.START_OBJECT) { + + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String fieldname = jParser.getCurrentName(); + final JsonToken nextToken = jParser.nextToken(); + if (nextToken == JsonToken.START_OBJECT) { + this.getCurrentWeatherDataObjects(currentWeatherData, jParser, fieldname); + } + if (nextToken == JsonToken.START_ARRAY) { + JsonToken tokenNext = jParser.nextToken(); + while (tokenNext != JsonToken.END_ARRAY) { + if (tokenNext == JsonToken.START_OBJECT) { + this.getCurrentWeatherDataObjects(currentWeatherData, jParser, fieldname); + } + tokenNext = jParser.nextToken(); + } + } + if ((nextToken == JsonToken.VALUE_NUMBER_INT) + || (nextToken == JsonToken.VALUE_STRING)) { + this.getCurrentWeatherDataObjects(currentWeatherData, jParser, fieldname); + } + } + } + } + + private void getCurrentWeatherDataObjects(final Current currentWeatherData, + final JsonParser jParser, final String fieldname) throws JsonParseException, + IOException { + if ("coord".equals(fieldname)) { + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + if ("lon".equals(namefield)) { + currentWeatherData.getCoord().setLon(jParser.getDoubleValue()); + } + if ("lat".equals(namefield)) { + currentWeatherData.getCoord().setLat(jParser.getDoubleValue()); + } + } + } + if ("sys".equals(fieldname)) { + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + if ("message".equals(namefield)) { + currentWeatherData.getSys().setMessage(jParser.getDoubleValue()); + } + if ("country".equals(namefield)) { + currentWeatherData.getSys().setCountry(jParser.getValueAsString()); + } + if ("sunrise".equals(namefield)) { + currentWeatherData.getSys().setSunrise(jParser.getValueAsLong()); + } + if ("sunset".equals(namefield)) { + currentWeatherData.getSys().setSunset(jParser.getValueAsLong()); + } + } + } + if ("weather".equals(fieldname)) { + final name.gumartinm.weather.information.model.currentweather.Weather weather = new name.gumartinm.weather.information.model.currentweather.Weather(); + currentWeatherData.getWeather().add(weather); + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + if ("id".equals(namefield)) { + weather.setId(jParser.getIntValue()); + } + if ("main".equals(namefield)) { + weather.setMain(jParser.getText()); + } + if ("description".equals(namefield)) { + weather.setDescription(jParser.getText()); + } + if ("icon".equals(namefield)) { + weather.setIcon(jParser.getText()); + } + + } + } + if ("base".equals(fieldname)) { + currentWeatherData.setBase(jParser.getText()); + } + if ("main".equals(fieldname)) { + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + if ("temp".equals(namefield)) { + currentWeatherData.getMain().setTemp(jParser.getDoubleValue()); + } + if ("temp_min".equals(namefield)) { + currentWeatherData.getMain().setTemp_min(jParser.getDoubleValue()); + } + if ("temp_max".equals(namefield)) { + currentWeatherData.getMain().setTemp_max(jParser.getDoubleValue()); + } + if ("pressure".equals(namefield)) { + currentWeatherData.getMain().setPressure(jParser.getDoubleValue()); + } + if ("sea_level".equals(namefield)) { + currentWeatherData.getMain().setSea_level(jParser.getDoubleValue()); + } + if ("grnd_level".equals(namefield)) { + currentWeatherData.getMain().setGrnd_level(jParser.getDoubleValue()); + } + if ("humidity".equals(namefield)) { + currentWeatherData.getMain().setHumidity(jParser.getDoubleValue()); + } + } + } + if ("wind".equals(fieldname)) { + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + if ("speed".equals(namefield)) { + currentWeatherData.getWind().setSpeed(jParser.getDoubleValue()); + } + if ("deg".equals(namefield)) { + currentWeatherData.getWind().setDeg(jParser.getDoubleValue()); + } + } + } + if ("clouds".equals(fieldname)) { + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + if ("all".equals(namefield)) { + currentWeatherData.getClouds().setAll(jParser.getDoubleValue()); + } + } + } + if ("dt".equals(fieldname)) { + currentWeatherData.setDt(jParser.getLongValue()); + } + if ("rain".equals(fieldname)) { + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + if ("3h".equals(namefield)) { + currentWeatherData.getRain().set3h(jParser.getDoubleValue()); + } + } + } + if ("snow".equals(fieldname)) { + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + if ("3h".equals(namefield)) { + currentWeatherData.getSnow().set3h(jParser.getDoubleValue()); + } + } + } + if ("id".equals(fieldname)) { + currentWeatherData.setId(jParser.getLongValue()); + } + if ("name".equals(fieldname)) { + currentWeatherData.setName(jParser.getText()); + } + if ("cod".equals(fieldname)) { + currentWeatherData.setCod(jParser.getIntValue()); + } + } + + private void getForecastWeatherData(final Forecast forecastWeatherData, + final JsonParser jParser) throws JsonParseException, IOException { + if (jParser.nextToken() == JsonToken.START_OBJECT) { + + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String fieldname = jParser.getCurrentName(); + final JsonToken nextToken = jParser.nextToken(); + if (nextToken == JsonToken.START_OBJECT) { + this.getForecastWeatherDataObjects(forecastWeatherData, jParser, fieldname); + } + if (nextToken == JsonToken.START_ARRAY) { + JsonToken tokenNext = jParser.nextToken(); + while (tokenNext != JsonToken.END_ARRAY) { + if (tokenNext == JsonToken.START_OBJECT) { + this.getForecastWeatherDataObjects(forecastWeatherData, jParser, fieldname); + } + tokenNext = jParser.nextToken(); + } + } + if ((nextToken == JsonToken.VALUE_NUMBER_INT) + || (nextToken == JsonToken.VALUE_STRING)) { + this.getForecastWeatherDataObjects(forecastWeatherData, jParser, fieldname); + } + } + } + } + + private void getForecastWeatherDataObjects(final Forecast forecastWeatherData, + final JsonParser jParser, final String fieldname) throws JsonParseException, + IOException { + + if ("cod".equals(fieldname)) { + final String stringCod = jParser.getText(); + forecastWeatherData.setCod(Long.valueOf(stringCod)); + } + if ("message".equals(fieldname)) { + forecastWeatherData.setMessage(jParser.getDoubleValue()); + } + if ("city".equals(fieldname)) { + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + final JsonToken nextToken = jParser.nextToken(); // move to + // value + if ("id".equals(namefield)) { + forecastWeatherData.getCity().setId(jParser.getLongValue()); + } + if ("name".equals(namefield)) { + forecastWeatherData.getCity().setName(jParser.getText()); + } + if ("coord".equals(namefield)) { + if (nextToken == JsonToken.START_OBJECT) { + this.getForecastWeatherDataObjects(forecastWeatherData, jParser, namefield); + } + } + if ("country".equals(namefield)) { + forecastWeatherData.getCity().setCountry(jParser.getText()); + } + if ("population".equals(namefield)) { + forecastWeatherData.getCity().setPopulation(jParser.getLongValue()); + } + } + } + if ("cnt".equals(fieldname)) { + forecastWeatherData.setCnt(jParser.getIntValue()); + } + if ("coord".equals(fieldname)) { + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + if ("lon".equals(namefield)) { + forecastWeatherData.getCity().getCoord().setLon(jParser.getDoubleValue()); + } + if ("lat".equals(namefield)) { + forecastWeatherData.getCity().getCoord().setLat(jParser.getDoubleValue()); + } + } + } + if ("list".equals(fieldname)) { + final name.gumartinm.weather.information.model.forecastweather.List list = new name.gumartinm.weather.information.model.forecastweather.List(); + list.setTemp(new Temp()); + list.setWeather(new ArrayList()); + forecastWeatherData.getList().add(list); + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + final JsonToken nextToken = jParser.nextToken(); // move to + // value + if ("dt".equals(namefield)) { + list.setDt(jParser.getLongValue()); + } + if ("temp".equals(namefield)) { + if (nextToken == JsonToken.START_OBJECT) { + this.getForecastWeatherDataObjects(forecastWeatherData, jParser, namefield); + } + } + if ("pressure".equals(namefield)) { + list.setPressure(jParser.getDoubleValue()); + } + if ("humidity".equals(namefield)) { + list.setHumidity(jParser.getDoubleValue()); + } + if ("weather".equals(namefield)) { + if (nextToken == JsonToken.START_ARRAY) { + JsonToken tokenNext = jParser.nextToken(); + while (tokenNext != JsonToken.END_ARRAY) { + if (tokenNext == JsonToken.START_OBJECT) { + this.getForecastWeatherDataObjects(forecastWeatherData, jParser, + namefield); + } + tokenNext = jParser.nextToken(); + } + } + } + if ("speed".equals(namefield)) { + list.setSpeed(jParser.getDoubleValue()); + } + if ("deg".equals(namefield)) { + list.setDeg(jParser.getDoubleValue()); + } + if ("clouds".equals(namefield)) { + list.setClouds(jParser.getDoubleValue()); + } + if ("rain".equals(namefield)) { + list.setRain(jParser.getDoubleValue()); + } + } + } + if ("temp".equals(fieldname)) { + final name.gumartinm.weather.information.model.forecastweather.List list = forecastWeatherData + .getList().get( + (forecastWeatherData.getList().size() - 1)); + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + if ("day".equals(namefield)) { + list.getTemp().setDay(jParser.getDoubleValue()); + } + if ("min".equals(namefield)) { + list.getTemp().setMin(jParser.getDoubleValue()); + } + if ("max".equals(namefield)) { + list.getTemp().setMax(jParser.getDoubleValue()); + } + if ("night".equals(namefield)) { + list.getTemp().setNight(jParser.getDoubleValue()); + } + if ("eve".equals(namefield)) { + list.getTemp().setEve(jParser.getDoubleValue()); + } + if ("morn".equals(namefield)) { + list.getTemp().setMorn(jParser.getDoubleValue()); + } + } + } + if ("weather".equals(fieldname)) { + final name.gumartinm.weather.information.model.forecastweather.List list = forecastWeatherData + .getList().get( + (forecastWeatherData.getList().size() - 1)); + final name.gumartinm.weather.information.model.forecastweather.Weather weather = new name.gumartinm.weather.information.model.forecastweather.Weather(); + while (jParser.nextToken() != JsonToken.END_OBJECT) { + final String namefield = jParser.getCurrentName(); + jParser.nextToken(); // move to value + + if ("id".equals(namefield)) { + weather.setId(jParser.getIntValue()); + } + if ("main".equals(namefield)) { + weather.setMain(jParser.getText()); + } + if ("description".equals(namefield)) { + weather.setDescription(jParser.getText()); + } + if ("icon".equals(namefield)) { + weather.setIcon(jParser.getText()); + } + } + list.getWeather().add(weather); + } + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/service/IconsList.java b/app/src/main/java/name/gumartinm/weather/information/service/IconsList.java new file mode 100644 index 0000000..0148117 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/service/IconsList.java @@ -0,0 +1,152 @@ +package name.gumartinm.weather.information.service; + +import name.gumartinm.weather.information.R; + +import java.util.HashMap; +import java.util.Map; + +public enum IconsList { + ICON_01d("01d") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_clear; + } + }, + // TODO: I am sometimes receiving this code, there is no documentation about it on the + // openweathermap site.... But it exists!!! Some day, try to find out more information about it. + // see: http://openweathermap.org/img/w/01dd.png + ICON_01dd("01dd") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_clear; + } + }, + ICON_01n("01n") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_clear_night; + } + }, + ICON_02d("02d") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_few_clouds; + } + }, + ICON_02n("02n") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_few_clouds_night; + } + }, + ICON_03d("03d") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_few_clouds; + } + }, + ICON_03n("03n") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_few_clouds; + } + }, + ICON_04d("04d") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_overcast; + } + }, + ICON_04n("04n") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_overcast; + } + }, + ICON_09d("09d") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_showers; + } + }, + ICON_09n("09n") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_showers; + } + }, + ICON_10d("10d") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_showers_scattered; + } + }, + ICON_10n("10n") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_showers_scattered; + } + }, + ICON_11d("11d") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_storm; + } + }, + ICON_11n("11n") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_storm; + } + }, + ICON_13d("13d") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_snow; + } + }, + ICON_13n("13n") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_snow; + } + }, + ICON_50d("50d") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_fog; + } + }, + ICON_50n("50n") { + @Override + public int getResourceDrawable() { + return R.drawable.weather_fog; + } + }; + + private final String icon; + // Map with every enum constant. Class variable initializer. JLS§12.4.2 + // Executed in textual order. + private static final Map codeMap = new HashMap(); + + // Static initializer. JLS§12.4.2 Executed in textual order. + static { + for (final IconsList code : IconsList.values()) { + codeMap.put(code.getIcon(), code); + } + } + + private IconsList(final String icon) { + this.icon = icon; + } + + public static final IconsList getIcon(final String icon) { + return codeMap.get(icon); + } + + private String getIcon() { + return this.icon; + } + + public abstract int getResourceDrawable(); +} diff --git a/app/src/main/java/name/gumartinm/weather/information/service/PermanentStorage.java b/app/src/main/java/name/gumartinm/weather/information/service/PermanentStorage.java new file mode 100644 index 0000000..975bf28 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/service/PermanentStorage.java @@ -0,0 +1,189 @@ +package name.gumartinm.weather.information.service; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.StreamCorruptedException; +import java.text.MessageFormat; + +import android.content.Context; +import android.util.Log; + +import name.gumartinm.weather.information.model.currentweather.Current; +import name.gumartinm.weather.information.model.forecastweather.Forecast; + + +public class PermanentStorage { + private static final String TAG = "PermanentStorage"; + private static final String CURRENT_DATA_FILE = "current.file"; + private static final String FORECAST_DATA_FILE = "forecast.file"; + private static final String WIDGET_CURRENT_DATA_FILE = "current.{0}.file"; + private final Context context; + + public PermanentStorage(final Context context) { + this.context = context; + } + + public void saveCurrent(final Current current) { + + try { + this.saveObject(CURRENT_DATA_FILE, current); + } catch (FileNotFoundException e) { + Log.e(TAG, "saveCurrent exception: ", e); + } catch (IOException e) { + Log.e(TAG, "saveCurrent exception: ", e); + } + } + + public Current getCurrent() { + + try { + return (Current) this.getObject(CURRENT_DATA_FILE); + } catch (final StreamCorruptedException e) { + Log.e(TAG, "getCurrent exception: ", e); + } catch (final FileNotFoundException e) { + Log.e(TAG, "getCurrent exception: ", e); + } catch (final IOException e) { + Log.e(TAG, "getCurrent exception: ", e); + } catch (final ClassNotFoundException e) { + Log.e(TAG, "getCurrent exception: ", e); + } + + return null; + } + + public void saveWidgetCurrentData(final Current current, final int appWidgetId) { + + final String fileName = MessageFormat.format(WIDGET_CURRENT_DATA_FILE, appWidgetId); + try { + this.saveObject(fileName, current); + } catch (FileNotFoundException e) { + Log.e(TAG, "saveWidgetCurrentData exception: ", e); + } catch (IOException e) { + Log.e(TAG, "saveWidgetCurrentData exception: ", e); + } + } + + public Current getWidgetCurrentData(final int appWidgetId) { + + final String fileName = MessageFormat.format(WIDGET_CURRENT_DATA_FILE, appWidgetId); + try { + return (Current) this.getObject(fileName); + } catch (final StreamCorruptedException e) { + Log.e(TAG, "getWidgetCurrentData exception: ", e); + } catch (final FileNotFoundException e) { + Log.e(TAG, "getWidgetCurrentData exception: ", e); + } catch (final IOException e) { + Log.e(TAG, "getWidgetCurrentData exception: ", e); + } catch (final ClassNotFoundException e) { + Log.e(TAG, "getWidgetCurrentData exception: ", e); + } + + return null; + } + + public void removeWidgetCurrentData(final int appWidgetId) { + + final String fileName = MessageFormat.format(WIDGET_CURRENT_DATA_FILE, appWidgetId); + + try { + this.removeFile(fileName); + } catch (final IOException e) { + Log.e(TAG, "removeWidgetCurrentData exception: ", e); + } + } + + public void saveForecast(final Forecast forecast) { + + try { + this.saveObject(FORECAST_DATA_FILE, forecast); + } catch (FileNotFoundException e) { + Log.e(TAG, "saveForecast exception: ", e); + } catch (IOException e) { + Log.e(TAG, "saveForecast exception: ", e); + } + } + + public Forecast getForecast() { + + try { + return (Forecast) this.getObject(FORECAST_DATA_FILE); + } catch (final StreamCorruptedException e) { + Log.e(TAG, "getForecast exception: ", e); + } catch (final FileNotFoundException e) { + Log.e(TAG, "getForecast exception: ", e); + } catch (final IOException e) { + Log.e(TAG, "getForecast exception: ", e); + } catch (final ClassNotFoundException e) { + Log.e(TAG, "getForecast exception: ", e); + } + + return null; + } + + private void saveObject(final String fileName, final Object objectToStore) + throws FileNotFoundException, IOException { + final String temporaryFileName = fileName.concat(".tmp"); + + final FileOutputStream tmpPersistFile = this.context.openFileOutput( + temporaryFileName, Context.MODE_PRIVATE); + try { + final ObjectOutputStream oos = new ObjectOutputStream(tmpPersistFile); + try { + oos.writeObject(objectToStore); + + // Don't fear the fsync! + // http://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/ + tmpPersistFile.flush(); + tmpPersistFile.getFD().sync(); + } finally { + oos.close(); + } + } finally { + tmpPersistFile.close(); + } + + this.renameFile(temporaryFileName, fileName); + } + + private Object getObject(final String fileName) throws StreamCorruptedException, FileNotFoundException, + IOException, ClassNotFoundException { + final InputStream persistFile = this.context.openFileInput(fileName); + try { + final ObjectInputStream ois = new ObjectInputStream(persistFile); + try { + return ois.readObject(); + } finally { + ois.close(); + } + } finally { + persistFile.close(); + } + } + + private void renameFile(final String fromFileName, final String toFileName) throws IOException { + final File filesDir = this.context.getFilesDir(); + final File fromFile = new File(filesDir, fromFileName); + final File toFile = new File(filesDir, toFileName); + if (!fromFile.renameTo(toFile)) { + if (!fromFile.delete()) { + throw new IOException("PermanentStorage, delete file error"); + } + throw new IOException("PermanentStorage, rename file error"); + } + } + + private void removeFile(final String fileName) throws IOException { + final File filesDir = this.context.getFilesDir(); + final File file = new File(filesDir, fileName); + + if (!file.delete()) { + throw new IOException("PermanentStorage, remove file error"); + } + } +} + diff --git a/app/src/main/java/name/gumartinm/weather/information/service/ServiceParser.java b/app/src/main/java/name/gumartinm/weather/information/service/ServiceParser.java new file mode 100644 index 0000000..80534a1 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/service/ServiceParser.java @@ -0,0 +1,64 @@ +package name.gumartinm.weather.information.service; + +import com.fasterxml.jackson.core.JsonParseException; +import name.gumartinm.weather.information.model.currentweather.Current; +import name.gumartinm.weather.information.model.forecastweather.Forecast; +import name.gumartinm.weather.information.parser.IJPOSParser; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.Locale; + + +public class ServiceParser { + private final IJPOSParser JPOSParser; + + public ServiceParser(final IJPOSParser JPOSWeatherParser) { + this.JPOSParser = JPOSWeatherParser; + } + + public Current retrieveCurrentFromJPOS(final String jsonData) + throws JsonParseException, IOException { + return this.JPOSParser.retrieveCurrenFromJPOS(jsonData); + } + + public Forecast retrieveForecastFromJPOS(final String jsonData) + throws JsonParseException, IOException { + return this.JPOSParser.retrieveForecastFromJPOS(jsonData); + } + + public String createURIAPIForecast(final String urlAPI, final String APIVersion, + final double latitude, final double longitude, final String resultsNumber) { + + final MessageFormat formatURIAPI = new MessageFormat(urlAPI, Locale.US); + final Object[] values = new Object[4]; + values[0] = APIVersion; + values[1] = latitude; + values[2] = longitude; + values[3] = resultsNumber; + + return formatURIAPI.format(values); + } + + public String createURIAPICurrent(final String urlAPI, final String APIVersion, + final double latitude, final double longitude) { + + final MessageFormat formatURIAPI = new MessageFormat(urlAPI, Locale.US); + final Object[] values = new Object[3]; + values[0] = APIVersion; + values[1] = latitude; + values[2] = longitude; + + return formatURIAPI.format(values); + } + + public String createURIAPIicon(final String icon, final String urlAPI) { + + final MessageFormat formatURIAPI = new MessageFormat(urlAPI, Locale.US); + final Object[] values = new Object[1]; + values[0] = icon; + + return formatURIAPI.format(values); + } + +} diff --git a/app/src/main/java/name/gumartinm/weather/information/widget/WidgetConfigure.java b/app/src/main/java/name/gumartinm/weather/information/widget/WidgetConfigure.java new file mode 100644 index 0000000..c9a2ab2 --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/widget/WidgetConfigure.java @@ -0,0 +1,172 @@ +package name.gumartinm.weather.information.widget; + +import android.app.ActionBar; +import android.app.Activity; +import android.appwidget.AppWidgetManager; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.View; +import android.widget.CompoundButton; +import android.widget.Spinner; +import android.widget.Switch; + +import name.gumartinm.weather.information.R; + +public class WidgetConfigure extends Activity { + private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Find the widget id from the intent. + final Intent intent = getIntent(); + final Bundle extras = intent.getExtras(); + boolean isActionFromUser = false; + + if (extras != null) { + mAppWidgetId = extras.getInt( + AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + + isActionFromUser = extras.getBoolean("actionFromUser", false); + } + + // If they gave us an intent without the widget id, just bail. + if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { + this.finish(); + } + + if (!isActionFromUser) { + // Set the result to CANCELED. This will cause the widget host to cancel + // out of the widget placement if they press the back button. + this.setResult(RESULT_CANCELED); + } + + // Set the view layout resource to use. + this.setContentView(R.layout.appwidget_configure); + + /******************* Show/hide country field *******************/ + String keyPreference = this.getApplicationContext().getString( + R.string.widget_preferences_country_switch_key); + String realKeyPreference = keyPreference + "_" + mAppWidgetId; + + // What was saved to permanent storage (or default values if it is the first time) + final boolean isShowCountry = this.getSharedPreferences("WIDGET_PREFERENCES", Context.MODE_PRIVATE) + .getBoolean(realKeyPreference, false); + + // What is shown on the screen + final Switch countrySwitch = (Switch) this.findViewById(R.id.weather_appwidget_configure_country); + countrySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){ + @Override + public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) { + if (isChecked) { + buttonView.setText(WidgetConfigure.this.getString(R.string.widget_preferences_country_switch_on_summary)); + } else { + buttonView.setText(WidgetConfigure.this.getString(R.string.widget_preferences_country_switch_off_summary)); + } + } + }); + if (isShowCountry) { + countrySwitch.setChecked(true); + countrySwitch.setText(this.getString(R.string.widget_preferences_country_switch_on_summary)); + } else { + countrySwitch.setChecked(false); + countrySwitch.setText(this.getString(R.string.widget_preferences_country_switch_off_summary)); + } + + /********************* Temperature units **********************/ + keyPreference = this.getApplicationContext().getString( + R.string.widget_preferences_temperature_units_key); + realKeyPreference = keyPreference + "_" + mAppWidgetId; + + // What was saved to permanent storage (or default values if it is the first time) + final int tempValue = this.getSharedPreferences("WIDGET_PREFERENCES", Context.MODE_PRIVATE).getInt(realKeyPreference, 0); + + // What is shown on the screen + final Spinner tempUnits = (Spinner) this.findViewById(R.id.weather_appwidget_configure_temperature_units); + tempUnits.setSelection(tempValue); + + /** + * android:saveEnabled + * Controls whether the saving of this view's state is enabled (that is, whether its onSaveInstanceState() method will be called). + * + * After onStart the onSaveInstanceState method will be called for every widget, so + * I do not need to do anything else to retrieve the UI's state after changing orientation. + * + * I do not know if this is a good pattern, it does not look like that. I guess, I should use + * on Resume instead of onCreate/onStart and implement my own onSaveInstanceState method. + * But I am tired... + */ + } + + @Override + public void onResume() { + super.onResume(); + + final ActionBar actionBar = this.getActionBar(); + actionBar.setTitle(this.getString(R.string.widget_preferences_action_settings)); + } + + + public void onClickRefresh(final View view) { + // Push widget update to surface + WidgetProvider.refreshAppWidget(this.getApplicationContext(), mAppWidgetId); + } + + public void onClickOk(final View view) { + // Save to permanent storage + final SharedPreferences.Editor prefs = this.getSharedPreferences( + "WIDGET_PREFERENCES", + Context.MODE_PRIVATE).edit(); + + /******************* Show/hide country field *******************/ + // What is shown on the screen + final Switch countrySwitch = (Switch) this.findViewById(R.id.weather_appwidget_configure_country); + String keyPreference = this.getApplicationContext().getString( + R.string.widget_preferences_country_switch_key); + String realKeyPreference = keyPreference + "_" + mAppWidgetId; + prefs.putBoolean(realKeyPreference, countrySwitch.isChecked()); + + /********************* Temperature units **********************/ + // What is shown on the screen + final Spinner tempUnits = (Spinner) this.findViewById(R.id.weather_appwidget_configure_temperature_units); + keyPreference = this.getApplicationContext().getString( + R.string.widget_preferences_temperature_units_key); + realKeyPreference = keyPreference + "_" + mAppWidgetId; + prefs.putInt(realKeyPreference, tempUnits.getSelectedItemPosition()); + + /****************** Saving to permanent storage ***************/ + prefs.commit(); + + // Push widget update to surface with newly set prefix + WidgetProvider.updateAppWidget(this.getApplicationContext(), mAppWidgetId); + + // Make sure we pass back the original appWidgetId + final Intent resultValue = new Intent(); + resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); + this.setResult(RESULT_OK, resultValue); + finish(); + } + + public static void deletePreference(final Context context, final int appWidgetId) { + final SharedPreferences.Editor prefs = context.getApplicationContext() + .getSharedPreferences("WIDGET_PREFERENCES", Context.MODE_PRIVATE).edit(); + + /******************* Show/hide country field *******************/ + String keyPreference = context.getApplicationContext().getString( + R.string.widget_preferences_country_switch_key); + String realKeyPreference = keyPreference + "_" + appWidgetId; + prefs.remove(realKeyPreference); + + /********************* Temperature units **********************/ + keyPreference = context.getApplicationContext().getString( + R.string.widget_preferences_temperature_units_key); + realKeyPreference = keyPreference + "_" + appWidgetId; + prefs.remove(realKeyPreference); + + /****************** Updating permanent storage ***************/ + prefs.commit(); + } +} diff --git a/app/src/main/java/name/gumartinm/weather/information/widget/WidgetProvider.java b/app/src/main/java/name/gumartinm/weather/information/widget/WidgetProvider.java new file mode 100644 index 0000000..628dbcf --- /dev/null +++ b/app/src/main/java/name/gumartinm/weather/information/widget/WidgetProvider.java @@ -0,0 +1,116 @@ +package name.gumartinm.weather.information.widget; + + +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.appwidget.AppWidgetProviderInfo; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import name.gumartinm.weather.information.widget.service.WidgetIntentService; + +public class WidgetProvider extends AppWidgetProvider { + + @Override + public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) { + // For each widget that needs an update, get the text that we should display: + // - Create a RemoteViews object for it + // - Set the text in the RemoteViews object + // - Tell the AppWidgetManager to show that views object for the widget. + final int N = appWidgetIds.length; + for (int i=0; i 0) + && (current.getWeather().get(0).getIcon() != null) + && (IconsList.getIcon(current.getWeather().get(0).getIcon()) != null)) { + final String icon = current.getWeather().get(0).getIcon(); + picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon) + .getResourceDrawable()); + } else { + picture = BitmapFactory.decodeResource(this.getResources(), + R.drawable.weather_severe_alert); + } + final String city = weatherLocation.getCity(); + final String country = weatherLocation.getCountry(); + + // 5. Insert data in RemoteViews. + final RemoteViews remoteView = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.appwidget); + remoteView.setImageViewBitmap(R.id.weather_appwidget_image, picture); + remoteView.setTextViewText(R.id.weather_appwidget_temperature_max, tempMax); + remoteView.setTextViewText(R.id.weather_appwidget_temperature_min, tempMin); + remoteView.setTextViewText(R.id.weather_appwidget_city, city); + if (!isCountry) { + remoteView.setViewVisibility(R.id.weather_appwidget_country, View.GONE); + } else { + // TODO: It is as if Android had a view cache. If I did not set VISIBLE value, + // the country field would be gone forever... :/ + remoteView.setViewVisibility(R.id.weather_appwidget_country, View.VISIBLE); + remoteView.setTextViewText(R.id.weather_appwidget_country, country); + } + + + // 6. Activity launcher. + final Intent resultIntent = new Intent(this.getApplicationContext(), WidgetConfigure.class); + resultIntent.putExtra("actionFromUser", true); + resultIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); + // resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK ); + // From: http://stackoverflow.com/questions/4011178/multiple-instances-of-widget-only-updating-last-widget + final Uri data = Uri.withAppendedPath(Uri.parse("PAIN" + "://widget/id/") ,String.valueOf(appWidgetId)); + resultIntent.setData(data); + + final TaskStackBuilder stackBuilder = TaskStackBuilder.create(this.getApplicationContext()); + // Adds the back stack for the Intent (but not the Intent itself) + stackBuilder.addParentStack(WidgetConfigure.class); + // Adds the Intent that starts the Activity to the top of the stack + stackBuilder.addNextIntent(resultIntent); + final PendingIntent resultPendingIntent = + stackBuilder.getPendingIntent( + 0, + PendingIntent.FLAG_UPDATE_CURRENT + ); + remoteView.setOnClickPendingIntent(R.id.weather_appwidget, resultPendingIntent); +// final PendingIntent resultPendingIntent = PendingIntent.getActivity( +// this.getApplicationContext(), +// 0, +// resultIntent, +// PendingIntent.FLAG_UPDATE_CURRENT); +// remoteView.setOnClickPendingIntent(R.id.weather_appwidget, resultPendingIntent); + + return remoteView; + } + + private RemoteViews makeErrorView(final int appWidgetId) { + final RemoteViews remoteView = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.appwidget_error); + + // 6. Activity launcher. + final Intent resultIntent = new Intent(this.getApplicationContext(), WidgetConfigure.class); + resultIntent.putExtra("actionFromUser", true); + resultIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); +// resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK ); + // From: http://stackoverflow.com/questions/4011178/multiple-instances-of-widget-only-updating-last-widget + final Uri data = Uri.withAppendedPath(Uri.parse("PAIN" + "://widget/id/") ,String.valueOf(appWidgetId)); + resultIntent.setData(data); + + final TaskStackBuilder stackBuilder = TaskStackBuilder.create(this.getApplicationContext()); + // Adds the back stack for the Intent (but not the Intent itself) + stackBuilder.addParentStack(WidgetConfigure.class); + // Adds the Intent that starts the Activity to the top of the stack + stackBuilder.addNextIntent(resultIntent); + final PendingIntent resultPendingIntent = + stackBuilder.getPendingIntent( + 0, + PendingIntent.FLAG_UPDATE_CURRENT + ); + remoteView.setOnClickPendingIntent(R.id.weather_appwidget_error, resultPendingIntent); +// final PendingIntent resultPendingIntent = PendingIntent.getActivity( +// this.getApplicationContext(), +// 0, +// resultIntent, +// PendingIntent.FLAG_UPDATE_CURRENT); +// remoteView.setOnClickPendingIntent(R.id.weather_appwidget_error, resultPendingIntent); + + return remoteView; + } + + private void updateWidget(final RemoteViews remoteView, final int appWidgetId) { + + final AppWidgetManager manager = AppWidgetManager.getInstance(this.getApplicationContext()); + manager.updateAppWidget(appWidgetId, remoteView); + } + + private boolean isDataFresh(final Date lastUpdate) { + if (lastUpdate == null) { + return false; + } + + final Date currentTime = new Date(); + if (((currentTime.getTime() - lastUpdate.getTime())) < UPDATE_TIME_RATE) { + return true; + } + + return false; + } + +// private void updateWidgets(final RemoteViews remoteView) { +// +// final ComponentName widgets = new ComponentName(this.getApplicationContext(), WidgetProvider.class); +// final AppWidgetManager manager = AppWidgetManager.getInstance(this.getApplicationContext()); +// manager.updateAppWidget(widgets, remoteView); +// } +} diff --git a/app/src/main/res/layout-large/weather_main.xml b/app/src/main/res/layout-large/weather_main.xml index 5be530d..b7af8ba 100644 --- a/app/src/main/res/layout-large/weather_main.xml +++ b/app/src/main/res/layout-large/weather_main.xml @@ -4,19 +4,19 @@ android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="com.weather.information.activity.WeatherInformationActivity" + tools:context="name.gumartinm.weather.information.activity.WeatherInformationActivity" tools:ignore="MergeRootFrame" > + class="name.gumartinm.weather.information.fragment.overview.OverviewFragment" /> + class="name.gumartinm.weather.information.fragment.specific.SpecificFragment" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/weather_current_fragment.xml b/app/src/main/res/layout/weather_current_fragment.xml index 030dba2..46968a0 100644 --- a/app/src/main/res/layout/weather_current_fragment.xml +++ b/app/src/main/res/layout/weather_current_fragment.xml @@ -1,7 +1,9 @@ + android:layout_height="match_parent" + tools:actionBarNavMode="tabs" > + tools:context="name.gumartinm.weather.information.activity.MapActivity" > @@ -15,6 +15,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" tools:layout="@layout/weather_specific_fragment" - class="com.weather.information.fragment.specific.SpecificFragment" /> + class="name.gumartinm.weather.information.fragment.specific.SpecificFragment" /> \ No newline at end of file diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml index 4e21f54..4ad765f 100644 --- a/app/src/main/res/menu/main.xml +++ b/app/src/main/res/menu/main.xml @@ -1,6 +1,6 @@

+ tools:context="name.gumartinm.weather.information.activity.MainActivity" >