From 8688fbd6c774bea44328d54ee317f8d1e404089f Mon Sep 17 00:00:00 2001 From: "gu.martinm@gmail.com" Date: Wed, 15 Oct 2014 22:38:09 +0200 Subject: [PATCH] WeatherInformation: widget configuration WIP. --- Android/WeatherInformation/res/values/strings.xml | 8 +- .../res/xml/appwidget_preferences.xml | 24 +-- .../de/example/exampletdd/WidgetIntentService.java | 46 +++--- .../fragment/current/CurrentFragment.java | 2 + .../example/exampletdd/widget/WidgetConfigure.java | 24 +-- .../exampletdd/widget/WidgetPreferences.java | 175 ++++++++++++--------- .../example/exampletdd/widget/WidgetProvider.java | 4 +- 7 files changed, 163 insertions(+), 120 deletions(-) diff --git a/Android/WeatherInformation/res/values/strings.xml b/Android/WeatherInformation/res/values/strings.xml index 138f8e8..f21b278 100644 --- a/Android/WeatherInformation/res/values/strings.xml +++ b/Android/WeatherInformation/res/values/strings.xml @@ -59,10 +59,14 @@ Settings + Country Units widget_preferences_temperature - widget_preferences_refresh_interval - Refresh interval + widget_preferences_countries_switch + Hide + Show + OFF + ON diff --git a/Android/WeatherInformation/res/xml/appwidget_preferences.xml b/Android/WeatherInformation/res/xml/appwidget_preferences.xml index b7510a0..db489da 100644 --- a/Android/WeatherInformation/res/xml/appwidget_preferences.xml +++ b/Android/WeatherInformation/res/xml/appwidget_preferences.xml @@ -1,22 +1,26 @@ - + + + + android:defaultValue="@string/weather_preferences_temperature_celsius" /> diff --git a/Android/WeatherInformation/src/de/example/exampletdd/WidgetIntentService.java b/Android/WeatherInformation/src/de/example/exampletdd/WidgetIntentService.java index 8845f22..c7f6438 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/WidgetIntentService.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/WidgetIntentService.java @@ -20,6 +20,7 @@ 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; @@ -35,6 +36,7 @@ import de.example.exampletdd.parser.JPOSWeatherParser; import de.example.exampletdd.service.IconsList; import de.example.exampletdd.service.PermanentStorage; import de.example.exampletdd.service.ServiceParser; +import de.example.exampletdd.widget.WidgetConfigure; import de.example.exampletdd.widget.WidgetProvider; public class WidgetIntentService extends IntentService { @@ -56,23 +58,23 @@ public class WidgetIntentService extends IntentService { if (weatherLocation == null) { // Nothing to do. Show error. - final RemoteViews view = this.makeErrorView(); + final RemoteViews view = this.makeErrorView(appWidgetId); this.updateWidgets(view); return; } if (isUpdateByApp) { - this.updateByApp(weatherLocation); + this.updateByApp(weatherLocation, appWidgetId); } else { this.updateByTimeout(weatherLocation, appWidgetId); } } - private void updateByApp(final WeatherLocation weatherLocation) { + private void updateByApp(final WeatherLocation weatherLocation, final int appWidgetId) { final PermanentStorage store = new PermanentStorage(this.getApplicationContext()); final Current current = store.getCurrent(); - final RemoteViews view = this.makeView(current, weatherLocation); + final RemoteViews view = this.makeView(current, weatherLocation, appWidgetId); this.updateWidgets(view); } @@ -80,18 +82,18 @@ public class WidgetIntentService extends IntentService { private void updateByTimeout(final WeatherLocation weatherLocation, final int appWidgetId) { if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { // Nothing to do. Something went wrong. Show error. - final RemoteViews view = this.makeErrorView(); + final RemoteViews view = this.makeErrorView(appWidgetId); this.updateWidgets(view); return; } final Current current = this.getRemoteCurrent(weatherLocation); if (current != null) { - final RemoteViews view = this.makeView(current, weatherLocation); + final RemoteViews view = this.makeView(current, weatherLocation, appWidgetId); this.updateWidget(view, appWidgetId); } else { // Show error. - final RemoteViews view = this.makeErrorView(); + final RemoteViews view = this.makeErrorView(appWidgetId); this.updateWidgets(view); } } @@ -148,7 +150,7 @@ public class WidgetIntentService extends IntentService { public double doConversion(final double value); } - private RemoteViews makeView(final Current current, final WeatherLocation weatherLocation) { + private RemoteViews makeView(final Current current, final WeatherLocation weatherLocation, final int appWidgetId) { final SharedPreferences sharedPreferences = PreferenceManager .getDefaultSharedPreferences(this.getApplicationContext()); @@ -234,16 +236,13 @@ public class WidgetIntentService extends IntentService { 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 Intent resultIntent = new Intent(this.getApplicationContext(), WidgetConfigure.class); + resultIntent.putExtra("actionFromUser", true); + resultIntent.putExtra("appWidgetId", appWidgetId); + final TaskStackBuilder stackBuilder = TaskStackBuilder.create(this.getApplicationContext()); // Adds the back stack for the Intent (but not the Intent itself) - stackBuilder.addParentStack(WeatherTabsActivity.class); + stackBuilder.addParentStack(WidgetConfigure.class); // Adds the Intent that starts the Activity to the top of the stack stackBuilder.addNextIntent(resultIntent); final PendingIntent resultPendingIntent = @@ -256,20 +255,17 @@ public class WidgetIntentService extends IntentService { return remoteView; } - private RemoteViews makeErrorView() { + private RemoteViews makeErrorView(final int appWidgetId) { final RemoteViews remoteView = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.appwidget_error); // 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 Intent resultIntent = new Intent(this.getApplicationContext(), WidgetConfigure.class); + resultIntent.putExtra("actionFromUser", true); + resultIntent.putExtra("appWidgetId", appWidgetId); + final TaskStackBuilder stackBuilder = TaskStackBuilder.create(this.getApplicationContext()); // Adds the back stack for the Intent (but not the Intent itself) - stackBuilder.addParentStack(WeatherTabsActivity.class); + stackBuilder.addParentStack(WidgetConfigure.class); // Adds the Intent that starts the Activity to the top of the stack stackBuilder.addNextIntent(resultIntent); final PendingIntent resultPendingIntent = diff --git a/Android/WeatherInformation/src/de/example/exampletdd/fragment/current/CurrentFragment.java b/Android/WeatherInformation/src/de/example/exampletdd/fragment/current/CurrentFragment.java index ac7e3b9..d199fef 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/fragment/current/CurrentFragment.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/fragment/current/CurrentFragment.java @@ -118,6 +118,8 @@ public class CurrentFragment extends Fragment { query.updateDataBase(weatherLocation); // 4. Update Widget's UI. + // TODO: MEJOR PONER UN REFRESH EN LA ACTIVITY DE CONFIGURACION DEL WIDGET!!!! + // PARA DE ESA FORMA NO PERDER EL WIDGETID final Intent intentWidget = new Intent(context.getApplicationContext(), WidgetIntentService.class); intentWidget.putExtra("updateByApp", true); context.getApplicationContext().startService(intentWidget); diff --git a/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetConfigure.java b/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetConfigure.java index ce20fce..5f73926 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetConfigure.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetConfigure.java @@ -37,17 +37,27 @@ public class WidgetConfigure extends Activity { @Override public void onCreate(final Bundle icicle) { super.onCreate(icicle); - - // Set the result to CANCELED. This will cause the widget host to cancel - // out of the widget placement if they press the back button. - this.setResult(RESULT_CANCELED); // Find the widget id from the intent. final Intent intent = getIntent(); final Bundle extras = intent.getExtras(); + boolean isActionFromUser = false; if (extras != null) { mAppWidgetId = extras.getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + + isActionFromUser = extras.getBoolean("actionFromUser", false); + } + + if (!isActionFromUser) { + // If they gave us an intent without the widget id, just bail. + if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { + this.finish(); + } + + // Set the result to CANCELED. This will cause the widget host to cancel + // out of the widget placement if they press the back button. + this.setResult(RESULT_CANCELED); } // Set the view layout resource to use. @@ -65,12 +75,6 @@ public class WidgetConfigure extends Activity { // Bind the action for the save button. this.findViewById(R.id.weather_appwidget_configure_save_button).setOnClickListener(mOnClickListener); - - - // If they gave us an intent without the widget id, just bail. - if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { - this.finish(); - } } @Override diff --git a/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetPreferences.java b/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetPreferences.java index 4f3191b..b4aecf2 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetPreferences.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetPreferences.java @@ -1,82 +1,89 @@ package de.example.exampletdd.widget; -import de.example.exampletdd.R; +import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; -import android.preference.Preference; +import android.preference.ListPreference; import android.preference.PreferenceFragment; +import android.preference.SwitchPreference; +import de.example.exampletdd.R; -public class WidgetPreferences extends PreferenceFragment { - +/** + * TODO: + * IT DOES NOT WORK IF USER IS WORKING WITH TWO OR MORE WIDGET PREFERENCE WINDOWS AT THE SAME TIME + * (hopefully nobody will realize...) + * How to implement custom preference activities (no extending from PreferenceActivity or PreferenceFragment) + * without pain? + */ +public class WidgetPreferences extends PreferenceFragment implements OnSharedPreferenceChangeListener { + private int appWidgetId; + @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // Retain this fragment across configuration changes. + // Retain this fragment across configuration changes. this.setRetainInstance(true); final Bundle bundle = this.getArguments(); - int appWidgetId = bundle.getInt("appWidgetId"); + appWidgetId = bundle.getInt("appWidgetId"); // Load the preferences from an XML resource this.addPreferencesFromResource(R.xml.appwidget_preferences); + - // Temperature units + /******************* Show/hide country field *******************/ + + /******************* Temperature units *******************/ String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); String[] humanValues = this.getResources().getStringArray(R.array.weather_preferences_temperature_human_value); + String keyPreference = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_temperature_key); - Preference connectionPref = this.findPreference(keyPreference); - String value = this.getPreferenceManager().getSharedPreferences() - .getString(keyPreference, ""); - String humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } - connectionPref.setSummary(humanValue); - - - // Refresh interval - values = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval_human_value); - keyPreference = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_refresh_interval_key); - connectionPref = this.findPreference(keyPreference); - value = this.getPreferenceManager().getSharedPreferences().getString(keyPreference, ""); - humanValue = ""; + R.string.widget_preferences_temperature_key); + String realKeyPreference = keyPreference + "_" + appWidgetId; + + + // What was saved to permanent storage (or default values if it is the first time) + String value = this.getActivity().getSharedPreferences("WIDGET_PREFERENCES", Context.MODE_PRIVATE) + .getString(realKeyPreference, this.getString(R.string.weather_preferences_temperature_celsius)); + String humanValue = this.getString(R.string.weather_preferences_temperature_celsius_human_value); + int index = 0; if (value.equals(values[0])) { + index = 0; humanValue = humanValues[0]; } else if (value.equals(values[1])) { + index = 1; humanValue = humanValues[1]; } else if (value.equals(values[2])) { + index = 2; humanValue = humanValues[2]; - } else if (value.equals(values[3])) { - humanValue = humanValues[3]; - } else if (value.equals(values[4])) { - humanValue = humanValues[4]; - } else if (value.equals(values[5])) { - humanValue = humanValues[5]; - } else if (value.equals(values[6])) { - humanValue = humanValues[6]; } - connectionPref.setSummary(humanValue); + + + // What is shown on the screen + final ListPreference listPref = (ListPreference) this.findPreference(keyPreference); + listPref.setSummary(humanValue); + listPref.setValueIndex(index); + listPref.setValue(value); } + @Override public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) { // Temperature units - String[] values = this.getResources().getStringArray(R.array.weather_preferences_temperature); - String[] humanValues = this.getResources().getStringArray(R.array.weather_preferences_temperature_human_value); String keyValue = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_temperature_key); + R.string.widget_preferences_temperature_key); if (key.equals(keyValue)) { - final Preference connectionPref = this.findPreference(key); - final String value = sharedPreferences.getString(key, ""); + final String[] values = this.getResources().getStringArray( + R.array.weather_preferences_temperature); + final String[] humanValues = this.getResources().getStringArray( + R.array.weather_preferences_temperature_human_value); + + final ListPreference listPref = (ListPreference) this.findPreference(key); + final String value = listPref.getValue(); + // What was saved to permanent storage + //final String value = sharedPreferences.getString(key, ""); String humanValue = ""; if (value.equals(values[0])) { humanValue = humanValues[0]; @@ -85,37 +92,63 @@ public class WidgetPreferences extends PreferenceFragment { } else if (value.equals(values[2])) { humanValue = humanValues[2]; } - - connectionPref.setSummary(humanValue); + // Update data on screen + listPref.setSummary(humanValue); + + + // Saving to permanent storage. + final String keyPreference = this.getActivity().getApplicationContext().getString( + R.string.widget_preferences_temperature_key); + final String realKeyPreference = keyPreference + "_" + appWidgetId; + + final SharedPreferences.Editor prefs = + this.getActivity().getSharedPreferences( + "WIDGET_PREFERENCES", + Context.MODE_PRIVATE).edit(); + prefs.putString(realKeyPreference, value); + prefs.commit(); return; } - - // Refresh interval - values = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval); - humanValues = this.getResources().getStringArray(R.array.weather_preferences_refresh_interval_human_value); + + + // Notification switch keyValue = this.getActivity().getApplicationContext().getString( - R.string.weather_preferences_refresh_interval_key); + R.string.widget_preferences_country_switch_key); if (key.equals(keyValue)) { - final Preference connectionPref = this.findPreference(key); - final String value = sharedPreferences.getString(key, ""); - String humanValue = ""; - if (value.equals(values[0])) { - humanValue = humanValues[0]; - } else if (value.equals(values[1])) { - humanValue = humanValues[1]; - } else if (value.equals(values[2])) { - humanValue = humanValues[2]; - } else if (value.equals(values[3])) { - humanValue = humanValues[3]; - } else if (value.equals(values[4])) { - humanValue = humanValues[4]; - } else if (value.equals(values[5])) { - humanValue = humanValues[5]; - } else if (value.equals(values[6])) { - humanValue = humanValues[6]; - } - connectionPref.setSummary(humanValue); - return; + final SwitchPreference preference = (SwitchPreference) this.findPreference(key); + if (preference.isChecked()) + { + keyValue = this.getActivity().getApplicationContext().getString( + R.string.weather_preferences_update_time_rate_key); + final String value = sharedPreferences.getString(keyValue, ""); + this.updateNotification(value); + } else { + this.cancelNotification(); + } } } + + @Override + public void onResume() { + super.onResume(); + this.getPreferenceManager().getSharedPreferences() + .registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onPause() { + super.onPause(); + this.getPreferenceManager().getSharedPreferences() + .unregisterOnSharedPreferenceChangeListener(this); + } + + public static void deletePreference(final Context context, final int appWidgetId) { + final String keyPreference = context.getApplicationContext().getString( + R.string.widget_preferences_temperature_key); + final String realKeyPreference = keyPreference + "_" + appWidgetId; + + final SharedPreferences.Editor prefs = context.getSharedPreferences("WIDGET_PREFERENCES", Context.MODE_PRIVATE).edit(); + prefs.remove(realKeyPreference); + prefs.commit(); + } } diff --git a/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetProvider.java b/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetProvider.java index ca92d7b..6cd1d74 100644 --- a/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetProvider.java +++ b/Android/WeatherInformation/src/de/example/exampletdd/widget/WidgetProvider.java @@ -29,11 +29,11 @@ public class WidgetProvider extends AppWidgetProvider { } @Override - public void onDeleted(Context context, int[] appWidgetIds) { + public void onDeleted(final Context context, final int[] appWidgetIds) { // When the user deletes the widget, delete the preference associated with it. final int N = appWidgetIds.length; for (int i=0; i