1 package com.weather.information.fragment.current;
3 import java.io.IOException;
4 import java.net.MalformedURLException;
5 import java.net.URISyntaxException;
7 import java.text.DecimalFormat;
8 import java.text.NumberFormat;
9 import java.text.SimpleDateFormat;
10 import java.util.Date;
11 import java.util.Locale;
13 import org.apache.http.client.ClientProtocolException;
15 import android.content.BroadcastReceiver;
16 import android.content.Context;
17 import android.content.Intent;
18 import android.content.IntentFilter;
19 import android.content.SharedPreferences;
20 import android.graphics.Bitmap;
21 import android.graphics.BitmapFactory;
22 import android.net.http.AndroidHttpClient;
23 import android.os.AsyncTask;
24 import android.os.Bundle;
25 import android.preference.PreferenceManager;
26 import android.support.v4.app.Fragment;
27 import android.support.v4.content.LocalBroadcastManager;
28 import android.util.Log;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.ImageView;
33 import android.widget.ProgressBar;
34 import android.widget.TextView;
36 import com.fasterxml.jackson.core.JsonParseException;
37 import com.weather.information.R;
38 import com.weather.information.httpclient.CustomHTTPClient;
39 import com.weather.information.model.DatabaseQueries;
40 import com.weather.information.model.WeatherLocation;
41 import com.weather.information.model.currentweather.Current;
42 import com.weather.information.parser.JPOSWeatherParser;
43 import com.weather.information.service.IconsList;
44 import com.weather.information.service.PermanentStorage;
45 import com.weather.information.service.ServiceParser;
46 import com.weather.information.widget.WidgetProvider;
48 public class CurrentFragment extends Fragment {
49 private static final String TAG = "CurrentFragment";
50 private BroadcastReceiver mReceiver;
53 public void onCreate(final Bundle savedInstanceState) {
54 super.onCreate(savedInstanceState);
58 public View onCreateView(LayoutInflater inflater, ViewGroup container,
59 Bundle savedInstanceState) {
61 // Inflate the layout for this fragment
62 return inflater.inflate(R.layout.weather_current_fragment, container, false);
66 public void onActivityCreated(final Bundle savedInstanceState) {
67 super.onActivityCreated(savedInstanceState);
69 if (savedInstanceState != null) {
71 final Current current = (Current) savedInstanceState.getSerializable("Current");
73 if (current != null) {
74 final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
75 store.saveCurrent(current);
79 this.setHasOptionsMenu(false);
81 this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE);
82 this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.VISIBLE);
83 this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE);
87 public void onResume() {
91 this.mReceiver = new BroadcastReceiver() {
94 public void onReceive(final Context context, final Intent intent) {
95 final String action = intent.getAction();
96 if (action.equals("com.weather.information.UPDATECURRENT")) {
97 final Current currentRemote = (Current) intent.getSerializableExtra("current");
99 if (currentRemote != null) {
101 // 1. Check conditions. They must be the same as the ones that triggered the AsyncTask.
102 final DatabaseQueries query = new DatabaseQueries(context.getApplicationContext());
103 final WeatherLocation weatherLocation = query.queryDataBase();
104 final PermanentStorage store = new PermanentStorage(context.getApplicationContext());
105 final Current current = store.getCurrent();
107 if (current == null || !CurrentFragment.this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) {
109 CurrentFragment.this.updateUI(currentRemote);
111 // 3. Update current data.
112 store.saveCurrent(currentRemote);
114 // 4. Update location data.
115 weatherLocation.setLastCurrentUIUpdate(new Date());
116 query.updateDataBase(weatherLocation);
120 // Empty UI and show error message
121 CurrentFragment.this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE);
122 CurrentFragment.this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.GONE);
123 CurrentFragment.this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.VISIBLE);
130 final IntentFilter filter = new IntentFilter();
131 filter.addAction("com.weather.information.UPDATECURRENT");
132 LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext())
133 .registerReceiver(this.mReceiver, filter);
136 this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE);
138 final DatabaseQueries query = new DatabaseQueries(this.getActivity().getApplicationContext());
139 final WeatherLocation weatherLocation = query.queryDataBase();
140 if (weatherLocation == null) {
142 // Show error message
143 final ProgressBar progress = (ProgressBar) getActivity().findViewById(R.id.weather_current_progressbar);
144 progress.setVisibility(View.GONE);
145 final TextView errorMessage = (TextView) getActivity().findViewById(R.id.weather_current_error_message);
146 errorMessage.setVisibility(View.VISIBLE);
150 // If is new location update widgets.
151 if (weatherLocation.getIsNew()) {
152 WidgetProvider.refreshAllAppWidgets(this.getActivity().getApplicationContext());
153 // Update location data.
154 weatherLocation.setIsNew(false);
155 query.updateDataBase(weatherLocation);
159 final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
160 final Current current = store.getCurrent();
162 if (current != null && this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) {
163 this.updateUI(current);
165 // Load remote data (aynchronous)
166 // Gets the data from the web.
167 this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.VISIBLE);
168 this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE);
169 final CurrentTask task = new CurrentTask(
170 this.getActivity().getApplicationContext(),
171 new CustomHTTPClient(AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")),
172 new ServiceParser(new JPOSWeatherParser()));
174 task.execute(weatherLocation.getLatitude(), weatherLocation.getLongitude());
179 public void onSaveInstanceState(final Bundle savedInstanceState) {
182 final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
183 final Current current = store.getCurrent();
185 if (current != null) {
186 savedInstanceState.putSerializable("Current", current);
189 super.onSaveInstanceState(savedInstanceState);
193 public void onPause() {
194 LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()).unregisterReceiver(this.mReceiver);
199 private interface UnitsConversor {
201 public double doConversion(final double value);
204 private void updateUI(final Current current) {
206 final SharedPreferences sharedPreferences = PreferenceManager
207 .getDefaultSharedPreferences(this.getActivity().getApplicationContext());
209 // TODO: repeating the same code in Overview, Specific and Current!!!
210 // 1. Update units of measurement.
213 UnitsConversor tempUnitsConversor;
214 String keyPreference = this.getResources().getString(R.string.weather_preferences_temperature_key);
215 String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature);
216 String unitsPreferenceValue = sharedPreferences.getString(
217 keyPreference, this.getString(R.string.weather_preferences_temperature_celsius));
218 if (unitsPreferenceValue.equals(values[0])) {
219 tempSymbol = values[0];
220 tempUnitsConversor = new UnitsConversor(){
223 public double doConversion(final double value) {
224 return value - 273.15;
228 } else if (unitsPreferenceValue.equals(values[1])) {
229 tempSymbol = values[1];
230 tempUnitsConversor = new UnitsConversor(){
233 public double doConversion(final double value) {
234 return (value * 1.8) - 459.67;
239 tempSymbol = values[2];
240 tempUnitsConversor = new UnitsConversor(){
243 public double doConversion(final double value) {
252 UnitsConversor windUnitsConversor;
253 keyPreference = this.getResources().getString(R.string.weather_preferences_wind_key);
254 values = this.getResources().getStringArray(R.array.weather_preferences_wind);
255 unitsPreferenceValue = sharedPreferences.getString(
256 keyPreference, this.getString(R.string.weather_preferences_wind_meters));
257 if (unitsPreferenceValue.equals(values[0])) {
258 windSymbol = values[0];
259 windUnitsConversor = new UnitsConversor(){
262 public double doConversion(double value) {
267 windSymbol = values[1];
268 windUnitsConversor = new UnitsConversor(){
271 public double doConversion(double value) {
272 return value * 2.237;
278 String pressureSymbol;
279 UnitsConversor pressureUnitsConversor;
280 keyPreference = this.getResources().getString(R.string.weather_preferences_pressure_key);
281 values = this.getResources().getStringArray(R.array.weather_preferences_pressure);
282 unitsPreferenceValue = sharedPreferences.getString(
283 keyPreference, this.getString(R.string.weather_preferences_pressure_pascal));
284 if (unitsPreferenceValue.equals(values[0])) {
285 pressureSymbol = values[0];
286 pressureUnitsConversor = new UnitsConversor(){
289 public double doConversion(double value) {
294 pressureSymbol = values[1];
295 pressureUnitsConversor = new UnitsConversor(){
298 public double doConversion(double value) {
299 return value / 113.25d;
306 final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
307 tempFormatter.applyPattern("#####.#####");
308 final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.US);
311 // 3. Prepare data for UI.
313 if (current.getMain().getTemp_max() != null) {
314 double conversion = (Double) current.getMain().getTemp_max();
315 conversion = tempUnitsConversor.doConversion(conversion);
316 tempMax = tempFormatter.format(conversion) + tempSymbol;
319 if (current.getMain().getTemp_min() != null) {
320 double conversion = (Double) current.getMain().getTemp_min();
321 conversion = tempUnitsConversor.doConversion(conversion);
322 tempMin = tempFormatter.format(conversion) + tempSymbol;
325 if ((current.getWeather().size() > 0)
326 && (current.getWeather().get(0).getIcon() != null)
327 && (IconsList.getIcon(current.getWeather().get(0).getIcon()) != null)) {
328 final String icon = current.getWeather().get(0).getIcon();
329 picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon)
330 .getResourceDrawable());
332 picture = BitmapFactory.decodeResource(this.getResources(),
333 R.drawable.weather_severe_alert);
336 String description = this.getString(R.string.text_field_description_when_error);
337 if (current.getWeather().size() > 0) {
338 description = current.getWeather().get(0).getDescription();
341 String humidityValue = "";
342 if ((current.getMain() != null)
343 && (current.getMain().getHumidity() != null)) {
344 final double conversion = (Double) current.getMain().getHumidity();
345 humidityValue = tempFormatter.format(conversion);
347 String pressureValue = "";
348 if ((current.getMain() != null)
349 && (current.getMain().getPressure() != null)) {
350 double conversion = (Double) current.getMain().getPressure();
351 conversion = pressureUnitsConversor.doConversion(conversion);
352 pressureValue = tempFormatter.format(conversion);
354 String windValue = "";
355 if ((current.getWind() != null)
356 && (current.getWind().getSpeed() != null)) {
357 double conversion = (Double) current.getWind().getSpeed();
358 conversion = windUnitsConversor.doConversion(conversion);
359 windValue = tempFormatter.format(conversion);
361 String rainValue = "";
362 if ((current.getRain() != null)
363 && (current.getRain().get3h() != null)) {
364 final double conversion = (Double) current.getRain().get3h();
365 rainValue = tempFormatter.format(conversion);
367 String cloudsValue = "";
368 if ((current.getClouds() != null)
369 && (current.getClouds().getAll() != null)) {
370 final double conversion = (Double) current.getClouds().getAll();
371 cloudsValue = tempFormatter.format(conversion);
373 String snowValue = "";
374 if ((current.getSnow() != null)
375 && (current.getSnow().get3h() != null)) {
376 final double conversion = (Double) current.getSnow().get3h();
377 snowValue = tempFormatter.format(conversion);
379 String feelsLike = "";
380 if (current.getMain().getTemp() != null) {
381 double conversion = (Double) current.getMain().getTemp();
382 conversion = tempUnitsConversor.doConversion(conversion);
383 feelsLike = tempFormatter.format(conversion);
385 String sunRiseTime = "";
386 if (current.getSys().getSunrise() != null) {
387 final long unixTime = (Long) current.getSys().getSunrise();
388 final Date unixDate = new Date(unixTime * 1000L);
389 sunRiseTime = dateFormat.format(unixDate);
391 String sunSetTime = "";
392 if (current.getSys().getSunset() != null) {
393 final long unixTime = (Long) current.getSys().getSunset();
394 final Date unixDate = new Date(unixTime * 1000L);
395 sunSetTime = dateFormat.format(unixDate);
400 final TextView tempMaxView = (TextView) getActivity().findViewById(R.id.weather_current_temp_max);
401 tempMaxView.setText(tempMax);
402 final TextView tempMinView = (TextView) getActivity().findViewById(R.id.weather_current_temp_min);
403 tempMinView.setText(tempMin);
404 final ImageView pictureView = (ImageView) getActivity().findViewById(R.id.weather_current_picture);
405 pictureView.setImageBitmap(picture);
407 final TextView descriptionView = (TextView) getActivity().findViewById(R.id.weather_current_description);
408 descriptionView.setText(description);
410 ((TextView) getActivity().findViewById(R.id.weather_current_humidity_value)).setText(humidityValue);
411 ((TextView) getActivity().findViewById(R.id.weather_current_humidity_units)).setText(
412 this.getActivity().getApplicationContext().getString(R.string.text_units_percent));
414 ((TextView) getActivity().findViewById(R.id.weather_current_pressure_value)).setText(pressureValue);
415 ((TextView) getActivity().findViewById(R.id.weather_current_pressure_units)).setText(pressureSymbol);
417 ((TextView) getActivity().findViewById(R.id.weather_current_wind_value)).setText(windValue);
418 ((TextView) getActivity().findViewById(R.id.weather_current_wind_units)).setText(windSymbol);
420 ((TextView) getActivity().findViewById(R.id.weather_current_rain_value)).setText(rainValue);
421 ((TextView) getActivity().findViewById(R.id.weather_current_rain_units)).setText(
422 this.getActivity().getApplicationContext().getString(R.string.text_units_mm3h));
424 ((TextView) getActivity().findViewById(R.id.weather_current_clouds_value)).setText(cloudsValue);
425 ((TextView) getActivity().findViewById(R.id.weather_current_clouds_units)).setText(
426 this.getActivity().getApplicationContext().getString(R.string.text_units_percent));
428 ((TextView) getActivity().findViewById(R.id.weather_current_snow_value)).setText(snowValue);
429 ((TextView) getActivity().findViewById(R.id.weather_current_snow_units)).setText(
430 this.getActivity().getApplicationContext().getString(R.string.text_units_mm3h));
432 ((TextView) getActivity().findViewById(R.id.weather_current_feelslike_value)).setText(feelsLike);
433 ((TextView) getActivity().findViewById(R.id.weather_current_feelslike_units)).setText(tempSymbol);
435 ((TextView) getActivity().findViewById(R.id.weather_current_sunrise_value)).setText(sunRiseTime);
437 ((TextView) getActivity().findViewById(R.id.weather_current_sunset_value)).setText(sunSetTime);
439 this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.VISIBLE);
440 this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.GONE);
441 this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE);
444 private boolean isDataFresh(final Date lastUpdate) {
445 if (lastUpdate == null) {
449 final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(
450 this.getActivity().getApplicationContext());
451 final String keyPreference = this.getString(R.string.weather_preferences_refresh_interval_key);
452 final String refresh = sharedPreferences.getString(
454 this.getResources().getStringArray(R.array.weather_preferences_refresh_interval)[0]);
455 final Date currentTime = new Date();
456 if (((currentTime.getTime() - lastUpdate.getTime())) < Long.valueOf(refresh)) {
463 private class CurrentTask extends AsyncTask<Object, Void, Current> {
464 // Store the context passed to the AsyncTask when the system instantiates it.
465 private final Context localContext;
466 final CustomHTTPClient HTTPClient;
467 final ServiceParser weatherService;
469 public CurrentTask(final Context context, final CustomHTTPClient HTTPClient,
470 final ServiceParser weatherService) {
471 this.localContext = context;
472 this.HTTPClient = HTTPClient;
473 this.weatherService = weatherService;
477 protected Current doInBackground(final Object... params) {
478 final double latitude = (Double) params[0];
479 final double longitude = (Double) params[1];
481 Current current = null;
483 current = this.doInBackgroundThrowable(latitude, longitude);
484 } catch (final JsonParseException e) {
485 Log.e(TAG, "CurrentTask doInBackground exception: ", e);
486 } catch (final ClientProtocolException e) {
487 Log.e(TAG, "CurrentTask doInBackground exception: ", e);
488 } catch (final MalformedURLException e) {
489 Log.e(TAG, "CurrentTask doInBackground exception: ", e);
490 } catch (final URISyntaxException e) {
491 Log.e(TAG, "CurrentTask doInBackground exception: ", e);
492 } catch (final IOException e) {
493 // logger infrastructure swallows UnknownHostException :/
494 Log.e(TAG, "CurrentTask doInBackground exception: " + e.getMessage(), e);
502 private Current doInBackgroundThrowable(final double latitude, final double longitude)
503 throws URISyntaxException, ClientProtocolException, JsonParseException, IOException {
505 final String APIVersion = localContext.getResources().getString(R.string.api_version);
506 final String urlAPI = localContext.getResources().getString(R.string.uri_api_weather_today);
507 final String url = weatherService.createURIAPICurrent(urlAPI, APIVersion, latitude, longitude);
508 final String urlWithoutCache = url.concat("&time=" + System.currentTimeMillis());
509 final String jsonData = HTTPClient.retrieveDataAsString(new URL(urlWithoutCache));
511 return weatherService.retrieveCurrentFromJPOS(jsonData);
515 protected void onPostExecute(final Current current) {
517 // Call updateUI on the UI thread.
518 final Intent currentData = new Intent("com.weather.information.UPDATECURRENT");
519 currentData.putExtra("current", current);
520 LocalBroadcastManager.getInstance(this.localContext).sendBroadcastSync(currentData);