2 * Copyright 2014 Gustavo Martin Morcuende
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package name.gumartinm.weather.information.notification;
18 import java.io.IOException;
19 import java.net.MalformedURLException;
20 import java.net.URISyntaxException;
22 import java.text.DecimalFormat;
23 import java.text.NumberFormat;
24 import java.util.Locale;
26 import org.apache.http.client.ClientProtocolException;
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;
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;
55 public class NotificationIntentService extends IntentService {
56 private static final String TAG = "NotificationIntentService";
59 public NotificationIntentService() {
64 protected void onHandleIntent(final Intent intent) {
65 final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext());
66 final WeatherLocation weatherLocation = query.queryDataBase();
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)));
73 Current current = null;
75 current = this.doInBackgroundThrowable(weatherLocation, HTTPClient, weatherService);
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);
92 if (current != null) {
93 this.showNotification(current, weatherLocation);
98 private Current doInBackgroundThrowable(final WeatherLocation weatherLocation,
99 final CustomHTTPClient HTTPClient, final ServiceCurrentParser weatherService)
100 throws ClientProtocolException, MalformedURLException, URISyntaxException,
101 JsonParseException, IOException {
103 final String APIVersion = this.getResources().getString(R.string.api_version);
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));
111 return weatherService.retrieveCurrentFromJPOS(jsonData);
114 private interface UnitsConversor {
116 public double doConversion(final double value);
119 private void showNotification(final Current current, final WeatherLocation weatherLocation) {
120 final SharedPreferences sharedPreferences = PreferenceManager
121 .getDefaultSharedPreferences(this.getApplicationContext());
123 // TODO: repeating the same code in Overview, Specific and Current!!!
124 // 1. Update units of measurement.
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(){
137 public double doConversion(final double value) {
138 return value - 273.15;
142 } else if (unitsPreferenceValue.equals(values[1])) {
143 tempSymbol = values[1];
144 tempUnitsConversor = new UnitsConversor(){
147 public double doConversion(final double value) {
148 return (value * 1.8) - 459.67;
153 tempSymbol = values[2];
154 tempUnitsConversor = new UnitsConversor(){
157 public double doConversion(final double value) {
166 final DecimalFormat tempFormatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
167 tempFormatter.applyPattern("#####.#####");
170 // 3. Prepare data for RemoteViews.
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;
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;
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());
191 picture = BitmapFactory.decodeResource(this.getResources(),
192 R.drawable.weather_severe_alert);
194 final String city = weatherLocation.getCity();
195 final String country = weatherLocation.getCountry();
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);
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(
221 PendingIntent.FLAG_UPDATE_CURRENT
224 final NotificationManagerCompat notificationManager =
225 NotificationManagerCompat.from(this.getApplicationContext());
228 // 6. Create notification.
229 final NotificationCompat.Builder notificationBuilder =
230 new NotificationCompat.Builder(this.getApplicationContext())
231 .setContent(remoteView)
232 .setSmallIcon(R.drawable.ic_launcher)
235 .setWhen(System.currentTimeMillis())
236 .setContentIntent(resultPendingIntent)
237 .setPriority(NotificationCompat.PRIORITY_DEFAULT);
239 final Notification notification = notificationBuilder.build();
240 notification.flags |= Notification.FLAG_AUTO_CANCEL;
242 // Send the notification.
243 // Sets an ID for the notification, so it can be updated (just in case)
245 notificationManager.notify(notifyID, notification);