1. Save forecast and current data to permanent storage.
2. Update widget from App when location changed (no working yet)
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
- <application android:name="de.example.exampletdd.WeatherInformationApplication"
+ <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <activity android:name=".widget.WeatherInformationWidgetConfigure">
+ <activity android:name="de.example.exampletdd.widget.WeatherInformationWidgetConfigure">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
- <receiver android:name=".WeatherInformationBootReceiver"
+ <receiver android:name="de.example.exampletdd.WeatherInformationBootReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</receiver>
<!-- Service to update Notification -->
- <service android:name=".WeatherInformationBatch"
+ <service android:name="de.example.exampletdd.NotificationIntentService"
android:exported="false"
android:enabled="true" />
<!-- Service to update Widget -->
- <service android:name=".WeatherInformationWidgetProvider$UpdateService"
+ <service android:name="de.example.exampletdd.WidgetIntentService"
android:exported="false"
android:enabled="true" />
android:initialLayout="@layout/appwidget"
android:configure="de.example.exampletdd.widget.WeatherInformationWidgetConfigure"
android:widgetCategory="home_screen|keyguard"
- android:updatePeriodMillis="900000">
+ android:updatePeriodMillis="3600000">
</appwidget-provider>
--- /dev/null
+package de.example.exampletdd;
+
+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.Calendar;
+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 de.example.exampletdd.httpclient.CustomHTTPClient;
+import de.example.exampletdd.model.DatabaseQueries;
+import de.example.exampletdd.model.WeatherLocation;
+import de.example.exampletdd.model.currentweather.Current;
+import de.example.exampletdd.parser.JPOSWeatherParser;
+import de.example.exampletdd.service.IconsList;
+import de.example.exampletdd.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 jsonData = HTTPClient.retrieveDataAsString(new URL(url));
+ final Current current = weatherService.retrieveCurrentFromJPOS(jsonData);
+ // TODO: what is this for? I guess I could skip it :/
+ final Calendar now = Calendar.getInstance();
+ current.setDate(now.getTime());
+
+ return current;
+ }
+
+ 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.
+ boolean mIsFahrenheit = false;
+ final String keyPreference = this.getResources().getString(
+ R.string.weather_preferences_units_key);
+ final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
+ final String celsius = this.getResources().getString(
+ R.string.weather_preferences_units_celsius);
+ if (unitsPreferenceValue.equals(celsius)) {
+ mIsFahrenheit = false;
+ } else {
+ mIsFahrenheit = true;
+ }
+ final double tempUnits = mIsFahrenheit ? 0 : 273.15;
+ final String symbol = mIsFahrenheit ? "ºF" : "ºC";
+
+
+ // 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 = conversion - tempUnits;
+ tempMax = tempFormatter.format(conversion) + symbol;
+ }
+ String tempMin = "";
+ if (current.getMain().getTemp_min() != null) {
+ double conversion = (Double) current.getMain().getTemp_min();
+ conversion = conversion - tempUnits;
+ tempMin = tempFormatter.format(conversion) + symbol;
+ }
+ 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);
+ }
+}
+++ /dev/null
-package de.example.exampletdd;
-
-import android.app.Application;
-import de.example.exampletdd.model.currentweather.Current;
-import de.example.exampletdd.model.forecastweather.Forecast;
-
-public class WeatherInformationApplication extends Application {
- private Forecast mForecast;
- private Current mCurrent;
- private String mCity;
- private String mCountry;
-
-
- public void setForecast(final Forecast forecast) {
- this.mForecast = forecast;
- }
-
- public Forecast getForecast() {
- return this.mForecast;
- }
-
- public void setCurrent(final Current current) {
- this.mCurrent = current;
- }
-
- public Current getCurrent() {
- return this.mCurrent;
- }
-
- public void setCity(final String city) {
- this.mCity = city;
- }
-
- public String getCity() {
- return this.mCity;
- }
-
- public void setCountry(final String country) {
- this.mCountry = country;
- }
-
- public String getCountry() {
- return this.mCountry;
- }
-}
+++ /dev/null
-package de.example.exampletdd;
-
-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.Calendar;
-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 de.example.exampletdd.httpclient.CustomHTTPClient;
-import de.example.exampletdd.model.DatabaseQueries;
-import de.example.exampletdd.model.WeatherLocation;
-import de.example.exampletdd.model.currentweather.Current;
-import de.example.exampletdd.parser.JPOSWeatherParser;
-import de.example.exampletdd.service.IconsList;
-import de.example.exampletdd.service.ServiceParser;
-
-public class WeatherInformationBatch extends IntentService {
- private static final String TAG = "WeatherInformationBatch";
-
-
- public WeatherInformationBatch() {
- super("WIB-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 jsonData = HTTPClient.retrieveDataAsString(new URL(url));
- final Current current = weatherService.retrieveCurrentFromJPOS(jsonData);
- // TODO: what is this for? I guess I could skip it :/
- final Calendar now = Calendar.getInstance();
- current.setDate(now.getTime());
-
- return current;
- }
-
- 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.
- boolean mIsFahrenheit = false;
- final String keyPreference = this.getResources().getString(
- R.string.weather_preferences_units_key);
- final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
- final String celsius = this.getResources().getString(
- R.string.weather_preferences_units_celsius);
- if (unitsPreferenceValue.equals(celsius)) {
- mIsFahrenheit = false;
- } else {
- mIsFahrenheit = true;
- }
- final double tempUnits = mIsFahrenheit ? 0 : 273.15;
- final String symbol = mIsFahrenheit ? "ºF" : "ºC";
-
-
- // 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 = conversion - tempUnits;
- tempMax = tempFormatter.format(conversion) + symbol;
- }
- String tempMin = "";
- if (current.getMain().getTemp_min() != null) {
- double conversion = (Double) current.getMain().getTemp_min();
- conversion = conversion - tempUnits;
- tempMin = tempFormatter.format(conversion) + symbol;
- }
- 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);
- }
-}
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, WeatherInformationBatch.class);
+ 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()
--- /dev/null
+package de.example.exampletdd;
+
+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.Calendar;
+import java.util.Locale;
+
+import org.apache.http.client.ClientProtocolException;
+
+import android.app.IntentService;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.ComponentName;
+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.TaskStackBuilder;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+import com.fasterxml.jackson.core.JsonParseException;
+
+import de.example.exampletdd.httpclient.CustomHTTPClient;
+import de.example.exampletdd.model.DatabaseQueries;
+import de.example.exampletdd.model.WeatherLocation;
+import de.example.exampletdd.model.currentweather.Current;
+import de.example.exampletdd.parser.JPOSWeatherParser;
+import de.example.exampletdd.service.IconsList;
+import de.example.exampletdd.service.PermanentStorage;
+import de.example.exampletdd.service.ServiceParser;
+
+public class WidgetIntentService extends IntentService {
+ private static final String TAG = "WidgetIntentService";
+
+
+ public WidgetIntentService() {
+ super("WIS-Thread");
+ }
+
+ @Override
+ protected void onHandleIntent(final Intent intent) {
+ Log.i(TAG, "onHandleIntent");
+ final int appWidgetId = intent.getIntExtra("appWidgetId", -666);
+ final boolean isUpdateByApp = intent.getBooleanExtra("updateByApp", false);
+
+ final DatabaseQueries query = new DatabaseQueries(this.getApplicationContext());
+ final WeatherLocation weatherLocation = query.queryDataBase();
+
+ if (weatherLocation == null) {
+ // Nothing to do.
+ return;
+ }
+
+ if (isUpdateByApp) {
+ this.updateByApp(weatherLocation);
+ } else {
+ this.updateByTimeout(weatherLocation, appWidgetId);
+ }
+
+ }
+
+ private void updateByApp(final WeatherLocation weatherLocation) {
+ final PermanentStorage store = new PermanentStorage(this.getApplicationContext());
+ final Current current = store.getCurrent();
+ final RemoteViews view = this.makeView(current, weatherLocation);
+
+ this.updateWidgets(view);
+ }
+
+ private void updateByTimeout(final WeatherLocation weatherLocation, final int appWidgetId) {
+ if (appWidgetId == -666) {
+ // Nothing to do. Something went wrong.
+ return;
+ }
+
+ final Current current = this.getRemoteCurrent(weatherLocation);
+ if (current != null) {
+ final RemoteViews view = this.makeView(current, weatherLocation);
+ this.updateWidget(view, appWidgetId);
+ } else {
+ // TODO: show layout error in Widget
+ }
+ }
+
+ private Current getRemoteCurrent(final WeatherLocation weatherLocation) {
+
+ final ServiceParser weatherService = new ServiceParser(new JPOSWeatherParser());
+ final CustomHTTPClient HTTPClient = new CustomHTTPClient(
+ AndroidHttpClient.newInstance("Android 4.3 WeatherInformation Agent"));
+
+ try {
+ return this.getRemoteCurrentThrowable(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();
+ }
+
+ return null;
+ }
+
+ private Current getRemoteCurrentThrowable(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 jsonData = HTTPClient.retrieveDataAsString(new URL(url));
+ final Current current = weatherService.retrieveCurrentFromJPOS(jsonData);
+ // TODO: what is this for? I guess I could skip it :/
+ final Calendar now = Calendar.getInstance();
+ current.setDate(now.getTime());
+
+ return current;
+ }
+
+ private RemoteViews makeView(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.
+ boolean mIsFahrenheit = false;
+ final String keyPreference = this.getResources().getString(
+ R.string.weather_preferences_units_key);
+ final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
+ final String celsius = this.getResources().getString(
+ R.string.weather_preferences_units_celsius);
+ if (unitsPreferenceValue.equals(celsius)) {
+ mIsFahrenheit = false;
+ } else {
+ mIsFahrenheit = true;
+ }
+ final double tempUnits = mIsFahrenheit ? 0 : 273.15;
+ final String symbol = mIsFahrenheit ? "ºF" : "ºC";
+
+
+ // 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 = conversion - tempUnits;
+ tempMax = tempFormatter.format(conversion) + symbol;
+ }
+ String tempMin = "";
+ if (current.getMain().getTemp_min() != null) {
+ double conversion = (Double) current.getMain().getTemp_min();
+ conversion = conversion - tempUnits;
+ tempMin = tempFormatter.format(conversion) + symbol;
+ }
+ 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.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);
+ remoteView.setTextViewText(R.id.weather_appwidget_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
+ );
+ remoteView.setOnClickPendingIntent(R.id.weather_appwidget, resultPendingIntent);
+
+ return remoteView;
+ }
+
+ private void updateWidget(final RemoteViews remoteView, final int appWidgetId) {
+
+ final AppWidgetManager manager = AppWidgetManager.getInstance(this);
+ manager.updateAppWidget(appWidgetId, remoteView);
+
+ Log.i(TAG, "updateWidget updated");
+ }
+
+ private void updateWidgets(final RemoteViews remoteView) {
+
+ final ComponentName widgets = new ComponentName("de.example.exampletdd.widget", AppWidgetProvider.class.getCanonicalName());
+ final AppWidgetManager manager = AppWidgetManager.getInstance(this);
+ manager.updateAppWidget(widgets, remoteView);
+
+ Log.i(TAG, "updateWidgets updated");
+ }
+}
import com.fasterxml.jackson.core.JsonParseException;
import de.example.exampletdd.R;
-import de.example.exampletdd.WeatherInformationApplication;
+import de.example.exampletdd.WidgetIntentService;
import de.example.exampletdd.httpclient.CustomHTTPClient;
import de.example.exampletdd.model.DatabaseQueries;
import de.example.exampletdd.model.WeatherLocation;
import de.example.exampletdd.model.currentweather.Current;
import de.example.exampletdd.parser.JPOSWeatherParser;
import de.example.exampletdd.service.IconsList;
+import de.example.exampletdd.service.PermanentStorage;
import de.example.exampletdd.service.ServiceParser;
public class CurrentFragment extends Fragment {
// TODO: Could it be better to store in global forecast data even if it is null value?
// So, perhaps do not check for null value and always store in global variable.
if (current != null) {
- final WeatherInformationApplication application =
- (WeatherInformationApplication) getActivity().getApplication();
- application.setCurrent(current);
+ final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
+ store.saveCurrent(current);
}
}
// 1. Check conditions. They must be the same as the ones that triggered the AsyncTask.
final DatabaseQueries query = new DatabaseQueries(CurrentFragment.this.getActivity().getApplicationContext());
final WeatherLocation weatherLocation = query.queryDataBase();
- final WeatherInformationApplication application =
- (WeatherInformationApplication) CurrentFragment.this.getActivity().getApplication();
- final Current current = application.getCurrent();
+ final PermanentStorage store = new PermanentStorage(CurrentFragment.this.getActivity().getApplicationContext());
+ final Current current = store.getCurrent();
if (current == null || !CurrentFragment.this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) {
// 2. Update UI.
CurrentFragment.this.updateUI(currentRemote);
// 3. Update Data.
- application.setCurrent(currentRemote);
+ store.saveCurrent(currentRemote);
weatherLocation.setLastCurrentUIUpdate(new Date());
query.updateDataBase(weatherLocation);
+
+ // 4. Update Widget's UI.
+ // TODO: Unable to start service intent not found U=0 WHYYYYYYYY? ANDROID SUCKSSSSSSS
+ final Intent intentWidget = new Intent();
+ intentWidget.setClassName("de.example.exampletdd", WidgetIntentService.class.getCanonicalName());
+ intent.putExtra("appWidgetId", 0);
+ intentWidget.putExtra("updateByApp", true);
+ CurrentFragment.this.getActivity().getApplicationContext().startService(intent);
}
} else {
errorMessage.setVisibility(View.VISIBLE);
return;
}
-
- final WeatherInformationApplication application =
- (WeatherInformationApplication) getActivity().getApplication();
- final Current current = application.getCurrent();
+
+ final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
+ final Current current = store.getCurrent();
if (current != null && this.isDataFresh(weatherLocation.getLastCurrentUIUpdate())) {
this.updateUI(current);
public void onSaveInstanceState(final Bundle savedInstanceState) {
// Save UI state
- final WeatherInformationApplication application =
- (WeatherInformationApplication) getActivity().getApplication();
- final Current current = application.getCurrent();
+ final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
+ final Current current = store.getCurrent();
// TODO: Could it be better to save current data even if it is null value?
// So, perhaps do not check for null value.
import com.fasterxml.jackson.core.JsonParseException;
import de.example.exampletdd.R;
-import de.example.exampletdd.WeatherInformationApplication;
import de.example.exampletdd.fragment.specific.SpecificFragment;
import de.example.exampletdd.httpclient.CustomHTTPClient;
import de.example.exampletdd.model.DatabaseQueries;
import de.example.exampletdd.model.forecastweather.Forecast;
import de.example.exampletdd.parser.JPOSWeatherParser;
import de.example.exampletdd.service.IconsList;
+import de.example.exampletdd.service.PermanentStorage;
import de.example.exampletdd.service.ServiceParser;
public class OverviewFragment extends ListFragment {
// TODO: Could it be better to store in global forecast data even if it is null value?
// So, perhaps do not check for null value and always store in global variable.
if (forecast != null) {
- final WeatherInformationApplication application =
- (WeatherInformationApplication) getActivity().getApplication();
- application.setForecast(forecast);
+ final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
+ store.saveForecast(forecast);
}
}
// 1. Check conditions. They must be the same as the ones that triggered the AsyncTask.
final DatabaseQueries query = new DatabaseQueries(OverviewFragment.this.getActivity().getApplicationContext());
final WeatherLocation weatherLocation = query.queryDataBase();
- final WeatherInformationApplication application =
- (WeatherInformationApplication) OverviewFragment.this.getActivity().getApplication();
- final Forecast forecast = application.getForecast();
+ final PermanentStorage store = new PermanentStorage(OverviewFragment.this.getActivity().getApplicationContext());
+ final Forecast forecast = store.getForecast();
if (forecast == null || !OverviewFragment.this.isDataFresh(weatherLocation.getLastForecastUIUpdate())) {
// 2. Update UI.
OverviewFragment.this.updateUI(forecastRemote);
// 3. Update Data.
- application.setForecast(forecastRemote);
+ store.saveForecast(forecastRemote);
weatherLocation.setLastForecastUIUpdate(new Date());
query.updateDataBase(weatherLocation);
return;
}
- final WeatherInformationApplication application =
- (WeatherInformationApplication) getActivity().getApplication();
- final Forecast forecast = application.getForecast();
+ final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
+ final Forecast forecast = store.getForecast();
+ // TODO: store forecast data in permanent storage and check here if there is data in permanent storage
if (forecast != null && this.isDataFresh(weatherLocation.getLastForecastUIUpdate())) {
this.updateUI(forecast);
} else {
public void onSaveInstanceState(final Bundle savedInstanceState) {
// Save UI state
- final WeatherInformationApplication application =
- (WeatherInformationApplication) getActivity().getApplication();
- final Forecast forecast = application.getForecast();
+ final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
+ final Forecast forecast = store.getForecast();
// TODO: Could it be better to save forecast data even if it is null value?
// So, perhaps do not check for null value.
import android.preference.Preference;
import android.preference.PreferenceFragment;
import de.example.exampletdd.R;
-import de.example.exampletdd.WeatherInformationBatch;
+import de.example.exampletdd.NotificationIntentService;
public class WeatherInformationPreferencesFragment extends PreferenceFragment
implements OnSharedPreferenceChangeListener {
// 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(), WeatherInformationBatch.class);
+ new Intent(this.getActivity().getApplicationContext(), NotificationIntentService.class);
final PendingIntent alarmIntent =
PendingIntent.getService(
this.getActivity().getApplicationContext(),
import android.widget.ImageView;
import android.widget.TextView;
import de.example.exampletdd.R;
-import de.example.exampletdd.WeatherInformationApplication;
import de.example.exampletdd.model.forecastweather.Forecast;
import de.example.exampletdd.service.IconsList;
+import de.example.exampletdd.service.PermanentStorage;
public class SpecificFragment extends Fragment {
private int mChosenDay;
// TODO: Could it be better to store in global data forecast even if it is null value?
// So, perhaps do not check for null value and always store in global variable.
if (forecast != null) {
- final WeatherInformationApplication application =
- (WeatherInformationApplication) getActivity().getApplication();
- application.setForecast(forecast);
+ final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
+ store.saveForecast(forecast);
}
this.mChosenDay = savedInstanceState.getInt("mChosenDay");
public void onSaveInstanceState(final Bundle savedInstanceState) {
// Save UI state
- final WeatherInformationApplication application =
- (WeatherInformationApplication) getActivity().getApplication();
- final Forecast forecast = application.getForecast();
+ final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
+ final Forecast forecast = store.getForecast();
// TODO: Could it be better to save forecast data even if it is null value?
// So, perhaps do not check for null value.
* @param chosenDay
*/
public void updateUIByChosenDay(final int chosenDay) {
- final WeatherInformationApplication application =
- (WeatherInformationApplication) getActivity().getApplication();
- final Forecast forecast = application.getForecast();
+ final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
+ final Forecast forecast = store.getForecast();
if (forecast != null) {
this.updateUI(forecast, chosenDay);
public void onResume() {
super.onResume();
- final WeatherInformationApplication application =
- (WeatherInformationApplication) getActivity().getApplication();
- final Forecast forecast = application.getForecast();
+ final PermanentStorage store = new PermanentStorage(this.getActivity().getApplicationContext());
+ final Forecast forecast = store.getForecast();
if (forecast != null) {
this.updateUI(forecast, this.mChosenDay);
--- /dev/null
+package de.example.exampletdd.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 android.content.Context;
+import android.util.Log;
+import de.example.exampletdd.model.currentweather.Current;
+import de.example.exampletdd.model.forecastweather.Forecast;
+
+
+/**
+ * TODO: show some error message when there is no enough space for saving files. :/
+ *
+ */
+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 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 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");
+ }
+ }
+}
+
package de.example.exampletdd.widget;
-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.Calendar;
-import java.util.Locale;
-
-import org.apache.http.client.ClientProtocolException;
-
-import android.app.IntentService;
-import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.http.AndroidHttpClient;
import android.os.Bundle;
-import android.preference.PreferenceManager;
-import android.support.v4.app.TaskStackBuilder;
-import android.util.Log;
-import android.widget.RemoteViews;
-
-import com.fasterxml.jackson.core.JsonParseException;
-
-import de.example.exampletdd.R;
-import de.example.exampletdd.WeatherTabsActivity;
-import de.example.exampletdd.httpclient.CustomHTTPClient;
-import de.example.exampletdd.model.DatabaseQueries;
-import de.example.exampletdd.model.WeatherLocation;
-import de.example.exampletdd.model.currentweather.Current;
-import de.example.exampletdd.parser.JPOSWeatherParser;
-import de.example.exampletdd.service.IconsList;
-import de.example.exampletdd.service.ServiceParser;
+import de.example.exampletdd.WidgetIntentService;
public class WeatherInformationWidgetProvider extends AppWidgetProvider {
- private static final String TAG = "WeatherInformationWidgetProvider";
@Override
public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) {
- Log.d(TAG, "onUpdate");
// 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
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
// To prevent any ANR timeouts, we perform the update in a service
- final Intent intent = new Intent(context, UpdateService.class);
+ final Intent intent = new Intent(context, WidgetIntentService.class);
intent.putExtra("appWidgetId", appWidgetId);
+ intent.putExtra("updateByApp", false);
context.startService(intent);
- //updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
- Log.d(TAG, "onDeleted");
// When the user deletes the widget, delete the preference associated with it.
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
}
static void updateAppWidget(final Context context, final AppWidgetManager appWidgetManager, final int appWidgetId) {
- Log.i(TAG, "updateAppWidget appWidgetId=" + appWidgetId);
int widgetId;
Bundle myOptions = appWidgetManager.getAppWidgetOptions(appWidgetId);
// Construct the RemoteViews object. It takes the package name (in our case, it's our
// package, but it needs this because on the other side it's the widget host inflating
// the layout from our package).
- final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget);
-
- // Tell the widget manager
- appWidgetManager.updateAppWidget(appWidgetId, views);
- }
-
- public static class UpdateService extends IntentService {
- private static final String TAG = "UpdateService";
-
-
- public UpdateService() {
- super("UpdateWidget-Thread");
- }
-
- @Override
- protected void onHandleIntent(final Intent intent) {
- int appWidgetId = intent.getIntExtra("appWidgetId", -666);
-
- if (appWidgetId == -666) {
- // Nothing to do. Something went wrong.
- Log.e(TAG, "appWidgetId error value");
- return;
- }
-
- 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.updateWidget(current, weatherLocation, appWidgetId);
- } else {
- // TODO: show layout error in Widget
- }
-
- } else {
- // TODO: show layout error in Widget
- }
- }
-
- 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 jsonData = HTTPClient.retrieveDataAsString(new URL(url));
- final Current current = weatherService.retrieveCurrentFromJPOS(jsonData);
- // TODO: what is this for? I guess I could skip it :/
- final Calendar now = Calendar.getInstance();
- current.setDate(now.getTime());
-
- return current;
- }
+ //final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget);
- private void updateWidget(final Current current, final WeatherLocation weatherLocation, final int appWidgetId) {
- final SharedPreferences sharedPreferences = PreferenceManager
- .getDefaultSharedPreferences(this.getApplicationContext());
-
- // TODO: repeating the same code in Overview, Specific and Current!!!
- // 1. Update units of measurement.
- boolean mIsFahrenheit = false;
- final String keyPreference = this.getResources().getString(
- R.string.weather_preferences_units_key);
- final String unitsPreferenceValue = sharedPreferences.getString(keyPreference, "");
- final String celsius = this.getResources().getString(
- R.string.weather_preferences_units_celsius);
- if (unitsPreferenceValue.equals(celsius)) {
- mIsFahrenheit = false;
- } else {
- mIsFahrenheit = true;
- }
- final double tempUnits = mIsFahrenheit ? 0 : 273.15;
- final String symbol = mIsFahrenheit ? "ºF" : "ºC";
-
-
- // 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 = conversion - tempUnits;
- tempMax = tempFormatter.format(conversion) + symbol;
- }
- String tempMin = "";
- if (current.getMain().getTemp_min() != null) {
- double conversion = (Double) current.getMain().getTemp_min();
- conversion = conversion - tempUnits;
- tempMin = tempFormatter.format(conversion) + symbol;
- }
- 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.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);
- remoteView.setTextViewText(R.id.weather_appwidget_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
- );
- remoteView.setOnClickPendingIntent(R.id.weather_appwidget, resultPendingIntent);
-
-
- // Push update for this widget to the home screen
- final AppWidgetManager manager = AppWidgetManager.getInstance(this);
- manager.updateAppWidget(appWidgetId, remoteView);
-
- Log.i("WordWidget.UpdateService", "widget updated");
- }
+ final Intent intent = new Intent(context, WidgetIntentService.class);
+ intent.putExtra("appWidgetId", appWidgetId);
+ context.startService(intent);
}
}