b63b0aa4360c358d6af1573a2256035815f4ac17
[JavaForFun] /
1 package de.example.exampletdd.fragment.current;
2
3 import java.io.IOException;
4 import java.net.MalformedURLException;
5 import java.net.URISyntaxException;
6 import java.net.URL;
7 import java.text.DecimalFormat;
8 import java.text.NumberFormat;
9 import java.text.SimpleDateFormat;
10 import java.util.Calendar;
11 import java.util.Date;
12 import java.util.Locale;
13
14 import org.apache.http.client.ClientProtocolException;
15
16 import android.content.BroadcastReceiver;
17 import android.content.Context;
18 import android.content.Intent;
19 import android.content.IntentFilter;
20 import android.content.SharedPreferences;
21 import android.graphics.Bitmap;
22 import android.graphics.BitmapFactory;
23 import android.net.http.AndroidHttpClient;
24 import android.os.AsyncTask;
25 import android.os.Bundle;
26 import android.preference.PreferenceManager;
27 import android.support.v4.app.Fragment;
28 import android.support.v4.content.LocalBroadcastManager;
29 import android.util.Log;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.widget.ImageView;
34 import android.widget.ProgressBar;
35 import android.widget.TextView;
36
37 import com.fasterxml.jackson.core.JsonParseException;
38
39 import de.example.exampletdd.R;
40 import de.example.exampletdd.httpclient.CustomHTTPClient;
41 import de.example.exampletdd.model.DatabaseQueries;
42 import de.example.exampletdd.model.WeatherLocation;
43 import de.example.exampletdd.model.currentweather.Current;
44 import de.example.exampletdd.parser.JPOSWeatherParser;
45 import de.example.exampletdd.service.IconsList;
46 import de.example.exampletdd.service.PermanentStorage;
47 import de.example.exampletdd.service.ServiceParser;
48 import de.example.exampletdd.widget.WidgetProvider;
49
50 public class CurrentFragment extends Fragment {
51     private static final String TAG = "CurrentFragment";
52     private BroadcastReceiver mReceiver;
53
54     @Override
55     public void onCreate(final Bundle savedInstanceState) {
56         super.onCreate(savedInstanceState);
57     }
58
59     @Override
60     public View onCreateView(LayoutInflater inflater, ViewGroup container,
61                              Bundle savedInstanceState) {
62     
63         // Inflate the layout for this fragment
64         return inflater.inflate(R.layout.weather_current_fragment, container, false);
65     }
66     
67     @Override
68     public void onActivityCreated(final Bundle savedInstanceState) {
69         super.onActivityCreated(savedInstanceState);
70
71         if (savedInstanceState != null) {
72                 // Restore UI state
73             final Current current = (Current) savedInstanceState.getSerializable("Current");
74
75             if (current != null) {
76                 final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
77                 store.saveCurrent(current);
78             }
79         }     
80         
81         this.setHasOptionsMenu(false);
82
83         this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE);
84         this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.VISIBLE);
85         this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE);   
86     }
87
88     @Override
89     public void onResume() {
90         super.onResume();
91
92
93         this.mReceiver = new BroadcastReceiver() {
94
95                         @Override
96                         public void onReceive(final Context context, final Intent intent) {
97                                 final String action = intent.getAction();
98                                 if (action.equals("de.example.exampletdd.UPDATECURRENT")) {
99                                         final Current currentRemote = (Current) intent.getSerializableExtra("current");
100
101                                         if (currentRemote != null) {
102
103                                                 // 1. Check conditions. They must be the same as the ones that triggered the AsyncTask.
104                                                 final DatabaseQueries query = new DatabaseQueries(context.getApplicationContext());
105                                     final WeatherLocation weatherLocation = query.queryDataBase();
106                                     final PermanentStorage store = new PermanentStorage(context.getApplicationContext());
107                                     final Current current = store.getCurrent();
108
109                                     if (current == null || !CurrentFragment.this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) {
110                                         // 2. Update UI.
111                                         CurrentFragment.this.updateUI(currentRemote);
112
113                                         // 3. Update current data.
114                                                         store.saveCurrent(currentRemote);
115
116                             // 4. Update location data.
117                             weatherLocation.setLastCurrentUIUpdate(new Date());
118                             query.updateDataBase(weatherLocation);
119                                     }
120
121                                         } else {
122                                                 // Empty UI and show error message
123                                                 CurrentFragment.this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE);
124                                                 CurrentFragment.this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.GONE);
125                                                 CurrentFragment.this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.VISIBLE);
126                                         }
127                                 }
128                         }
129         };
130
131         // Register receiver
132         final IntentFilter filter = new IntentFilter();
133         filter.addAction("de.example.exampletdd.UPDATECURRENT");
134         LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext())
135                                                         .registerReceiver(this.mReceiver, filter);
136
137         // Empty UI
138         this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.GONE);
139         
140         final DatabaseQueries query = new DatabaseQueries(this.getActivity().getApplicationContext());
141         final WeatherLocation weatherLocation = query.queryDataBase();
142         if (weatherLocation == null) {
143             // Nothing to do.
144                 // Show error message
145                 final ProgressBar progress = (ProgressBar) getActivity().findViewById(R.id.weather_current_progressbar);
146                 progress.setVisibility(View.GONE);
147                         final TextView errorMessage = (TextView) getActivity().findViewById(R.id.weather_current_error_message);
148                 errorMessage.setVisibility(View.VISIBLE);
149             return;
150         }
151
152         // If is new location update widgets.
153         if (weatherLocation.getIsNew()) {
154             WidgetProvider.refreshAllAppWidgets(this.getActivity().getApplicationContext());
155             // Update location data.
156             weatherLocation.setIsNew(false);
157             query.updateDataBase(weatherLocation);
158         }
159
160
161         final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
162         final Current current = store.getCurrent();
163
164         if (current != null && this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) {
165             this.updateUI(current);
166         } else {
167             // Load remote data (aynchronous)
168             // Gets the data from the web.
169                 this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.VISIBLE);
170                 this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE);
171             final CurrentTask task = new CurrentTask(
172                         this.getActivity().getApplicationContext(),
173                     new CustomHTTPClient(AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent")),
174                     new ServiceParser(new JPOSWeatherParser()));
175
176             task.execute(weatherLocation.getLatitude(), weatherLocation.getLongitude());
177         }
178     }
179
180     @Override
181     public void onSaveInstanceState(final Bundle savedInstanceState) {
182
183         // Save UI state
184         final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
185         final Current current = store.getCurrent();
186
187         if (current != null) {
188             savedInstanceState.putSerializable("Current", current);
189         }
190
191         super.onSaveInstanceState(savedInstanceState);
192     }
193
194     @Override
195     public void onPause() {
196         LocalBroadcastManager.getInstance(this.getActivity().getApplicationContext()).unregisterReceiver(this.mReceiver);
197
198         super.onPause();
199     }
200
201     private interface UnitsConversor {
202         
203         public double doConversion(final double value);
204     }
205
206     private void updateUI(final Current current) {
207         
208         final SharedPreferences sharedPreferences = PreferenceManager
209                 .getDefaultSharedPreferences(this.getActivity().getApplicationContext());
210
211         // TODO: repeating the same code in Overview, Specific and Current!!!
212         // 1. Update units of measurement.
213         // 1.1 Temperature
214         String tempSymbol;
215         UnitsConversor tempUnitsConversor;
216         String keyPreference = this.getResources().getString(R.string.weather_preferences_temperature_key);
217         String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature);
218         String unitsPreferenceValue = sharedPreferences.getString(
219                 keyPreference, this.getString(R.string.weather_preferences_temperature_celsius));
220         if (unitsPreferenceValue.equals(values[0])) {
221                 tempSymbol = values[0];
222                 tempUnitsConversor = new UnitsConversor(){
223
224                                 @Override
225                                 public double doConversion(final double value) {
226                                         return value - 273.15;
227                                 }
228                         
229                 };
230         } else if (unitsPreferenceValue.equals(values[1])) {
231                 tempSymbol = values[1];
232                 tempUnitsConversor = new UnitsConversor(){
233
234                                 @Override
235                                 public double doConversion(final double value) {
236                                         return (value * 1.8) - 459.67;
237                                 }
238                         
239                 };
240         } else {
241                 tempSymbol = values[2];
242                 tempUnitsConversor = new UnitsConversor(){
243
244                                 @Override
245                                 public double doConversion(final double value) {
246                                         return value;
247                                 }
248                         
249                 };
250         }
251
252         // 1.2 Wind
253         String windSymbol;
254         UnitsConversor windUnitsConversor;
255         keyPreference = this.getResources().getString(R.string.weather_preferences_wind_key);
256         values = this.getResources().getStringArray(R.array.weather_preferences_wind);
257         unitsPreferenceValue = sharedPreferences.getString(
258                 keyPreference, this.getString(R.string.weather_preferences_wind_meters));
259         if (unitsPreferenceValue.equals(values[0])) {
260                 windSymbol = values[0];
261                 windUnitsConversor = new UnitsConversor(){
262
263                         @Override
264                         public double doConversion(double value) {
265                                 return value;
266                         }       
267                 };
268         } else {
269                 windSymbol = values[1];
270                 windUnitsConversor = new UnitsConversor(){
271
272                         @Override
273                         public double doConversion(double value) {
274                                 return value * 2.237;
275                         }       
276                 };
277         }
278
279         // 1.3 Pressure
280         String pressureSymbol;
281         UnitsConversor pressureUnitsConversor;
282         keyPreference = this.getResources().getString(R.string.weather_preferences_pressure_key);
283         values = this.getResources().getStringArray(R.array.weather_preferences_pressure);
284         unitsPreferenceValue = sharedPreferences.getString(
285                 keyPreference, this.getString(R.string.weather_preferences_pressure_pascal));
286         if (unitsPreferenceValue.equals(values[0])) {
287                 pressureSymbol = values[0];
288                 pressureUnitsConversor = new UnitsConversor(){
289
290                         @Override
291                         public double doConversion(double value) {
292                                 return value;
293                         }       
294                 };
295         } else {
296                 pressureSymbol = values[1];
297                 pressureUnitsConversor = new UnitsConversor(){
298
299                         @Override
300                         public double doConversion(double value) {
301                                 return value / 113.25d;
302                         }       
303                 };
304         }
305
306
307         // 2. Formatters
308         final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
309         tempFormatter.applyPattern("#####.#####");
310         final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.US);
311
312         
313         // 3. Prepare data for UI.
314         String tempMax = "";
315         if (current.getMain().getTemp_max() != null) {
316             double conversion = (Double) current.getMain().getTemp_max();
317             conversion = tempUnitsConversor.doConversion(conversion);
318             tempMax = tempFormatter.format(conversion) + tempSymbol;
319         }
320         String tempMin = "";
321         if (current.getMain().getTemp_min() != null) {
322             double conversion = (Double) current.getMain().getTemp_min();
323             conversion = tempUnitsConversor.doConversion(conversion);
324             tempMin = tempFormatter.format(conversion) + tempSymbol;
325         }
326         Bitmap picture;
327         if ((current.getWeather().size() > 0)
328                 && (current.getWeather().get(0).getIcon() != null)
329                 && (IconsList.getIcon(current.getWeather().get(0).getIcon()) != null)) {
330             final String icon = current.getWeather().get(0).getIcon();
331             picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon)
332                     .getResourceDrawable());
333         } else {
334             picture = BitmapFactory.decodeResource(this.getResources(),
335                     R.drawable.weather_severe_alert);
336         }
337
338         String description = this.getString(R.string.text_field_description_when_error);
339         if (current.getWeather().size() > 0) {
340             description = current.getWeather().get(0).getDescription();
341         }
342
343         String humidityValue = "";
344         if ((current.getMain() != null)
345                 && (current.getMain().getHumidity() != null)) {
346             final double conversion = (Double) current.getMain().getHumidity();
347             humidityValue = tempFormatter.format(conversion);
348         }
349         String pressureValue = "";
350         if ((current.getMain() != null)
351                 && (current.getMain().getPressure() != null)) {
352             double conversion = (Double) current.getMain().getPressure();
353             conversion = pressureUnitsConversor.doConversion(conversion);
354             pressureValue = tempFormatter.format(conversion);
355         }
356         String windValue = "";
357         if ((current.getWind() != null)
358                 && (current.getWind().getSpeed() != null)) {
359             double conversion = (Double) current.getWind().getSpeed();
360             conversion = windUnitsConversor.doConversion(conversion);
361             windValue = tempFormatter.format(conversion);
362         }
363         String rainValue = "";
364         if ((current.getRain() != null)
365                 && (current.getRain().get3h() != null)) {
366             final double conversion = (Double) current.getRain().get3h();
367             rainValue = tempFormatter.format(conversion);
368         }
369         String cloudsValue = "";
370         if ((current.getClouds() != null)
371                 && (current.getClouds().getAll() != null)) {
372             final double conversion = (Double) current.getClouds().getAll();
373             cloudsValue = tempFormatter.format(conversion);
374         }
375         String snowValue = "";
376         if ((current.getSnow() != null)
377                 && (current.getSnow().get3h() != null)) {
378             final double conversion = (Double) current.getSnow().get3h();
379             snowValue = tempFormatter.format(conversion);
380         }
381         String feelsLike = "";
382         if (current.getMain().getTemp() != null) {
383             double conversion = (Double) current.getMain().getTemp();
384             conversion = tempUnitsConversor.doConversion(conversion);
385             feelsLike = tempFormatter.format(conversion);
386         }
387         String sunRiseTime = "";
388         if (current.getSys().getSunrise() != null) {
389             final long unixTime = (Long) current.getSys().getSunrise();
390             final Date unixDate = new Date(unixTime * 1000L);
391             sunRiseTime = dateFormat.format(unixDate);
392         }
393         String sunSetTime = "";
394         if (current.getSys().getSunset() != null) {
395             final long unixTime = (Long) current.getSys().getSunset();
396             final Date unixDate = new Date(unixTime * 1000L);
397             sunSetTime = dateFormat.format(unixDate);
398         }
399
400
401         // 4. Update UI.
402         final TextView tempMaxView = (TextView) getActivity().findViewById(R.id.weather_current_temp_max);
403         tempMaxView.setText(tempMax);
404         final TextView tempMinView = (TextView) getActivity().findViewById(R.id.weather_current_temp_min);
405         tempMinView.setText(tempMin);
406         final ImageView pictureView = (ImageView) getActivity().findViewById(R.id.weather_current_picture);
407         pictureView.setImageBitmap(picture);    
408         
409         final TextView descriptionView = (TextView) getActivity().findViewById(R.id.weather_current_description);
410         descriptionView.setText(description);
411         
412         ((TextView) getActivity().findViewById(R.id.weather_current_humidity_value)).setText(humidityValue);
413         ((TextView) getActivity().findViewById(R.id.weather_current_humidity_units)).setText(
414                         this.getActivity().getApplicationContext().getString(R.string.text_units_percent));
415         
416         ((TextView) getActivity().findViewById(R.id.weather_current_pressure_value)).setText(pressureValue);
417         ((TextView) getActivity().findViewById(R.id.weather_current_pressure_units)).setText(pressureSymbol);
418         
419         ((TextView) getActivity().findViewById(R.id.weather_current_wind_value)).setText(windValue);
420         ((TextView) getActivity().findViewById(R.id.weather_current_wind_units)).setText(windSymbol);
421         
422         ((TextView) getActivity().findViewById(R.id.weather_current_rain_value)).setText(rainValue);
423         ((TextView) getActivity().findViewById(R.id.weather_current_rain_units)).setText(
424                         this.getActivity().getApplicationContext().getString(R.string.text_units_mm3h));
425         
426         ((TextView) getActivity().findViewById(R.id.weather_current_clouds_value)).setText(cloudsValue);
427         ((TextView) getActivity().findViewById(R.id.weather_current_clouds_units)).setText(
428                         this.getActivity().getApplicationContext().getString(R.string.text_units_percent));
429         
430         ((TextView) getActivity().findViewById(R.id.weather_current_snow_value)).setText(snowValue);
431         ((TextView) getActivity().findViewById(R.id.weather_current_snow_units)).setText(
432                         this.getActivity().getApplicationContext().getString(R.string.text_units_mm3h));
433         
434         ((TextView) getActivity().findViewById(R.id.weather_current_feelslike_value)).setText(feelsLike);
435         ((TextView) getActivity().findViewById(R.id.weather_current_feelslike_units)).setText(tempSymbol);
436         
437         ((TextView) getActivity().findViewById(R.id.weather_current_sunrise_value)).setText(sunRiseTime);
438
439         ((TextView) getActivity().findViewById(R.id.weather_current_sunset_value)).setText(sunSetTime);
440         
441         this.getActivity().findViewById(R.id.weather_current_data_container).setVisibility(View.VISIBLE);
442         this.getActivity().findViewById(R.id.weather_current_progressbar).setVisibility(View.GONE);
443         this.getActivity().findViewById(R.id.weather_current_error_message).setVisibility(View.GONE);       
444     }
445     
446     private boolean isDataFresh(final Date lastUpdate) {
447         if (lastUpdate == null) {
448                 return false;
449         }
450         
451         final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(
452                         this.getActivity().getApplicationContext());
453         final String keyPreference = this.getString(R.string.weather_preferences_refresh_interval_key);
454         final String refresh = sharedPreferences.getString(
455                         keyPreference,
456                         this.getResources().getStringArray(R.array.weather_preferences_refresh_interval)[0]);
457         final Date currentTime = new Date();
458         if (((currentTime.getTime() - lastUpdate.getTime())) < Long.valueOf(refresh)) {
459                 return true;
460         }
461         
462         return false;
463     }
464
465     private class CurrentTask extends AsyncTask<Object, Void, Current> {
466         // Store the context passed to the AsyncTask when the system instantiates it.
467         private final Context localContext;
468         final CustomHTTPClient HTTPClient;
469         final ServiceParser weatherService;
470
471         public CurrentTask(final Context context, final CustomHTTPClient HTTPClient,
472                         final ServiceParser weatherService) {
473                 this.localContext = context;
474             this.HTTPClient = HTTPClient;
475             this.weatherService = weatherService;
476         }
477
478         @Override
479         protected Current doInBackground(final Object... params) {
480                 final double latitude = (Double) params[0];
481             final double longitude = (Double) params[1];
482   
483             Current current = null;
484             try {
485                 current = this.doInBackgroundThrowable(latitude, longitude);
486             } catch (final JsonParseException e) {
487                 Log.e(TAG, "CurrentTask doInBackground exception: ", e);
488             } catch (final ClientProtocolException e) {
489                 Log.e(TAG, "CurrentTask doInBackground exception: ", e);
490             } catch (final MalformedURLException e) {
491                 Log.e(TAG, "CurrentTask doInBackground exception: ", e);
492             } catch (final URISyntaxException e) {
493                 Log.e(TAG, "CurrentTask doInBackground exception: ", e);
494             } catch (final IOException e) {
495                 // logger infrastructure swallows UnknownHostException :/
496                 Log.e(TAG, "CurrentTask doInBackground exception: " + e.getMessage(), e);
497             } finally {
498                 HTTPClient.close();
499             }
500
501             return current;
502         }
503
504         private Current doInBackgroundThrowable(final double latitude, final double longitude)
505                         throws URISyntaxException, ClientProtocolException, JsonParseException, IOException {
506
507                 final String APIVersion = localContext.getResources().getString(R.string.api_version);
508             final String urlAPI = localContext.getResources().getString(R.string.uri_api_weather_today);
509             final String url = weatherService.createURIAPICurrent(urlAPI, APIVersion, latitude, longitude);
510             final String urlWithoutCache = url.concat("&time=" + System.currentTimeMillis());
511             final String jsonData = HTTPClient.retrieveDataAsString(new URL(urlWithoutCache));
512
513             return weatherService.retrieveCurrentFromJPOS(jsonData);
514         }
515
516         @Override
517         protected void onPostExecute(final Current current) {
518
519             // Call updateUI on the UI thread.
520             final Intent currentData = new Intent("de.example.exampletdd.UPDATECURRENT");
521             currentData.putExtra("current", current);
522             LocalBroadcastManager.getInstance(this.localContext).sendBroadcastSync(currentData);
523         }
524     }
525 }