932b49cbd3cb3dd5fc526a584c313bd1fca347d4
[JavaForFun] /
1 /**
2  * Copyright 2014 Gustavo Martin Morcuende
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package name.gumartinm.weather.information.notification;
17
18 import java.io.IOException;
19 import java.net.MalformedURLException;
20 import java.net.URISyntaxException;
21 import java.net.URL;
22 import java.text.DecimalFormat;
23 import java.text.NumberFormat;
24 import java.util.Locale;
25
26 import org.apache.http.client.ClientProtocolException;
27
28 import android.app.IntentService;
29 import android.app.Notification;
30 import android.app.PendingIntent;
31 import android.content.Intent;
32 import android.content.SharedPreferences;
33 import android.graphics.Bitmap;
34 import android.graphics.BitmapFactory;
35 import android.net.http.AndroidHttpClient;
36 import android.preference.PreferenceManager;
37 import android.support.v4.app.NotificationCompat;
38 import android.support.v4.app.NotificationManagerCompat;
39 import android.support.v4.app.TaskStackBuilder;
40 import android.util.Log;
41 import android.widget.RemoteViews;
42
43 import com.fasterxml.jackson.core.JsonParseException;
44 import name.gumartinm.weather.information.R;
45 import name.gumartinm.weather.information.activity.MainTabsActivity;
46 import name.gumartinm.weather.information.httpclient.CustomHTTPClient;
47 import name.gumartinm.weather.information.model.DatabaseQueries;
48 import name.gumartinm.weather.information.model.WeatherLocation;
49 import name.gumartinm.weather.information.model.currentweather.Current;
50 import name.gumartinm.weather.information.parser.JPOSCurrentParser;
51 import name.gumartinm.weather.information.service.IconsList;
52 import name.gumartinm.weather.information.service.ServiceCurrentParser;
53
54
55 public class NotificationIntentService extends IntentService {
56     private static final String TAG = "NotificationIntentService";
57
58
59     public NotificationIntentService() {
60         super("NIS-Thread");
61     }
62
63     @Override
64     protected void onHandleIntent(final Intent intent) {
65         final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext());
66         final WeatherLocation weatherLocation = query.queryDataBase();
67         
68         if (weatherLocation != null) {
69             final ServiceCurrentParser weatherService = new ServiceCurrentParser(new JPOSCurrentParser());
70             final CustomHTTPClient HTTPClient = new CustomHTTPClient(
71                     AndroidHttpClient.newInstance(this.getString(R.string.http_client_agent)));
72
73             Current current = null;
74             try {
75                 current = this.doInBackgroundThrowable(weatherLocation, HTTPClient, weatherService);
76                 
77             } catch (final JsonParseException e) {
78                 Log.e(TAG, "doInBackground exception: ", e);
79             } catch (final ClientProtocolException e) {
80                 Log.e(TAG, "doInBackground exception: ", e);
81             } catch (final MalformedURLException e) {
82                 Log.e(TAG, "doInBackground exception: ", e);
83             } catch (final URISyntaxException e) {
84                 Log.e(TAG, "doInBackground exception: ", e);
85             } catch (final IOException e) {
86                 // logger infrastructure swallows UnknownHostException :/
87                 Log.e(TAG, "doInBackground exception: " + e.getMessage(), e);
88             } finally {
89                 HTTPClient.close();
90             }
91             
92             if (current != null) {
93                 this.showNotification(current, weatherLocation);
94             }
95         }
96     }
97
98     private Current doInBackgroundThrowable(final WeatherLocation weatherLocation,
99             final CustomHTTPClient HTTPClient, final ServiceCurrentParser weatherService)
100                     throws ClientProtocolException, MalformedURLException, URISyntaxException,
101                     JsonParseException, IOException {
102
103         final String APIVersion = this.getResources().getString(R.string.api_version);
104
105         final String urlAPI = this.getResources().getString(R.string.uri_api_weather_today);
106         final String url = weatherService.createURIAPICurrent(urlAPI, APIVersion,
107                 weatherLocation.getLatitude(), weatherLocation.getLongitude());
108         final String urlWithoutCache = url.concat("&time=" + System.currentTimeMillis());
109         final String jsonData = HTTPClient.retrieveDataAsString(new URL(urlWithoutCache));
110
111         return weatherService.retrieveCurrentFromJPOS(jsonData);
112     }
113     
114     private interface UnitsConversor {
115         
116         public double doConversion(final double value);
117     }
118     
119     private void showNotification(final Current current, final WeatherLocation weatherLocation) {
120         final SharedPreferences sharedPreferences = PreferenceManager
121                 .getDefaultSharedPreferences(this.getApplicationContext());
122
123                 // TODO: repeating the same code in Overview, Specific and Current!!!
124                 // 1. Update units of measurement.
125         // 1.1 Temperature
126         String tempSymbol;
127         UnitsConversor tempUnitsConversor;
128         final String keyPreference = this.getApplicationContext().getString(R.string.weather_preferences_notifications_temperature_key);
129         final String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature);
130         final String unitsPreferenceValue = sharedPreferences.getString(
131                 keyPreference, this.getString(R.string.weather_preferences_temperature_celsius));
132         if (unitsPreferenceValue.equals(values[0])) {
133                 tempSymbol = values[0];
134                 tempUnitsConversor = new UnitsConversor(){
135
136                                 @Override
137                                 public double doConversion(final double value) {
138                                         return value - 273.15;
139                                 }
140
141                 };
142         } else if (unitsPreferenceValue.equals(values[1])) {
143                 tempSymbol = values[1];
144                 tempUnitsConversor = new UnitsConversor(){
145
146                                 @Override
147                                 public double doConversion(final double value) {
148                                         return (value * 1.8) - 459.67;
149                                 }
150                         
151                 };
152         } else {
153                 tempSymbol = values[2];
154                 tempUnitsConversor = new UnitsConversor(){
155
156                                 @Override
157                                 public double doConversion(final double value) {
158                                         return value;
159                                 }
160                         
161                 };
162         }
163
164
165         // 2. Formatters
166         final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
167         tempFormatter.applyPattern("#####.#####");
168
169
170         // 3. Prepare data for RemoteViews.
171         String tempMax = "";
172         if (current.getMain().getTemp_max() != null) {
173             double conversion = (Double) current.getMain().getTemp_max();
174             conversion = tempUnitsConversor.doConversion(conversion);
175             tempMax = tempFormatter.format(conversion) + tempSymbol;
176         }
177         String tempMin = "";
178         if (current.getMain().getTemp_min() != null) {
179             double conversion = (Double) current.getMain().getTemp_min();
180             conversion = tempUnitsConversor.doConversion(conversion);
181             tempMin = tempFormatter.format(conversion) + tempSymbol;
182         }
183         Bitmap picture;
184         if ((current.getWeather().size() > 0)
185                 && (current.getWeather().get(0).getIcon() != null)
186                 && (IconsList.getIcon(current.getWeather().get(0).getIcon()) != null)) {
187             final String icon = current.getWeather().get(0).getIcon();
188             picture = BitmapFactory.decodeResource(this.getResources(), IconsList.getIcon(icon)
189                     .getResourceDrawable());
190         } else {
191             picture = BitmapFactory.decodeResource(this.getResources(),
192                     R.drawable.weather_severe_alert);
193         }
194         final String city = weatherLocation.getCity();
195         final String country = weatherLocation.getCountry();
196         
197         // 4. Insert data in RemoteViews.
198         final RemoteViews remoteView = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.notification);
199         remoteView.setImageViewBitmap(R.id.weather_notification_image, picture);
200         remoteView.setTextViewText(R.id.weather_notification_temperature_max, tempMax);
201         remoteView.setTextViewText(R.id.weather_notification_temperature_min, tempMin);
202         remoteView.setTextViewText(R.id.weather_notification_city, city);
203         remoteView.setTextViewText(R.id.weather_notification_country, country);
204
205         // 5. Activity launcher.
206         final Intent resultIntent =  new Intent(this.getApplicationContext(), MainTabsActivity.class);
207         // The PendingIntent to launch our activity if the user selects this notification
208 //        final PendingIntent contentIntent = PendingIntent.getActivity(
209 //                      this.getApplicationContext(), 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
210         // The stack builder object will contain an artificial back stack for the started Activity.
211         // This ensures that navigating backward from the Activity leads out of
212         // your application to the Home screen.
213         final TaskStackBuilder stackBuilder = TaskStackBuilder.create(this.getApplicationContext());
214         // Adds the back stack for the Intent (but not the Intent itself)
215         stackBuilder.addParentStack(MainTabsActivity.class);
216         // Adds the Intent that starts the Activity to the top of the stack
217         stackBuilder.addNextIntent(resultIntent);
218         final PendingIntent resultPendingIntent =
219                         stackBuilder.getPendingIntent(
220                     0,
221                     PendingIntent.FLAG_UPDATE_CURRENT
222                 );
223         
224         final NotificationManagerCompat notificationManager =
225                         NotificationManagerCompat.from(this.getApplicationContext());
226         
227
228         // 6. Create notification.
229         final NotificationCompat.Builder notificationBuilder =
230                         new NotificationCompat.Builder(this.getApplicationContext())
231                         .setContent(remoteView)
232                 .setSmallIcon(R.drawable.ic_launcher)
233                 .setAutoCancel(true)
234                 .setLocalOnly(true)
235                 .setWhen(System.currentTimeMillis())
236                 .setContentIntent(resultPendingIntent)
237                 .setPriority(NotificationCompat.PRIORITY_DEFAULT);
238         
239         final Notification notification = notificationBuilder.build();
240         notification.flags |= Notification.FLAG_AUTO_CANCEL;
241
242         // Send the notification.
243         // Sets an ID for the notification, so it can be updated (just in case)
244         int notifyID = 1;
245         notificationManager.notify(notifyID, notification);
246     }
247 }