From e67f622ccaecad2547fd8a869af030d17c48c518 Mon Sep 17 00:00:00 2001 From: Ronald Schaten Date: Sat, 4 Jun 2011 22:14:39 +0200 Subject: [PATCH] First commit --- .classpath | 7 + .project | 33 +++ AndroidManifest.xml | 27 ++ default.properties | 11 + proguard.cfg | 34 +++ res/drawable-hdpi/icon.png | Bin 0 -> 4147 bytes res/drawable-ldpi/icon.png | Bin 0 -> 1723 bytes res/drawable-mdpi/icon.png | Bin 0 -> 2574 bytes res/drawable/background.png | Bin 0 -> 405 bytes res/layout/config.xml | 26 ++ res/layout/main.xml | 26 ++ res/values/arrays.xml | 15 + res/values/strings.xml | 28 ++ res/xml/preferences.xml | 25 ++ res/xml/waldemar_info.xml | 7 + .../datepreference/DatePreference.java | 280 ++++++++++++++++++ .../android/waldemar/WaldemarPreferences.java | 103 +++++++ .../android/waldemar/WaldemarWidget.java | 111 +++++++ 18 files changed, 733 insertions(+) create mode 100644 .classpath create mode 100644 .project create mode 100644 AndroidManifest.xml create mode 100644 default.properties create mode 100644 proguard.cfg create mode 100644 res/drawable-hdpi/icon.png create mode 100644 res/drawable-ldpi/icon.png create mode 100644 res/drawable-mdpi/icon.png create mode 100644 res/drawable/background.png create mode 100644 res/layout/config.xml create mode 100644 res/layout/main.xml create mode 100644 res/values/arrays.xml create mode 100644 res/values/strings.xml create mode 100644 res/xml/preferences.xml create mode 100644 res/xml/waldemar_info.xml create mode 100644 src/de/schatenseite/android/datepreference/DatePreference.java create mode 100644 src/de/schatenseite/android/waldemar/WaldemarPreferences.java create mode 100644 src/de/schatenseite/android/waldemar/WaldemarWidget.java diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..609aa00 --- /dev/null +++ b/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..74fa4a6 --- /dev/null +++ b/.project @@ -0,0 +1,33 @@ + + + Waldemar + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..02def10 --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/default.properties b/default.properties new file mode 100644 index 0000000..e2e8061 --- /dev/null +++ b/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-8 diff --git a/proguard.cfg b/proguard.cfg new file mode 100644 index 0000000..8ad7d33 --- /dev/null +++ b/proguard.cfg @@ -0,0 +1,34 @@ +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembernames class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8074c4c571b8cd19e27f4ee5545df367420686d7 GIT binary patch literal 4147 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 literal 0 HcmV?d00001 diff --git a/res/drawable-ldpi/icon.png b/res/drawable-ldpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1095584ec21f71cd0afc9e0993aa2209671b590c GIT binary patch literal 1723 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 + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/main.xml b/res/layout/main.xml new file mode 100644 index 0000000..93fdbf5 --- /dev/null +++ b/res/layout/main.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/res/values/arrays.xml b/res/values/arrays.xml new file mode 100644 index 0000000..a69d649 --- /dev/null +++ b/res/values/arrays.xml @@ -0,0 +1,15 @@ + + + + @string/mode1 + @string/mode2 + @string/mode3 + @string/mode4 + + + 1 + 2 + 3 + 4 + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100644 index 0000000..0cc711f --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,28 @@ + + + Waldemar + Waldemar + Waldemar Einstellungen + Allgemein + Tage + NaN + Name + Überschrift des Widgets + Bitte eine Überschrift für das Widget eingeben + Waldemar + Zeiteinstellung + Modus + Welche Daten sind gegeben? + Nur Zieldatum + Start- und Zieldatum + Dauer und Zieldatum + Startdatum und Dauer + Startdatum + Wann beginnt der Countdown? + Dauer + Wie lang ist der Countdown? + Bitte die Dauer in Tagen eingeben + 267 + Zieldatum + Wann endet der Countdown? + diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml new file mode 100644 index 0000000..9c73520 --- /dev/null +++ b/res/xml/preferences.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/res/xml/waldemar_info.xml b/res/xml/waldemar_info.xml new file mode 100644 index 0000000..5d3f467 --- /dev/null +++ b/res/xml/waldemar_info.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/src/de/schatenseite/android/datepreference/DatePreference.java b/src/de/schatenseite/android/datepreference/DatePreference.java new file mode 100644 index 0000000..65c85ed --- /dev/null +++ b/src/de/schatenseite/android/datepreference/DatePreference.java @@ -0,0 +1,280 @@ +package de.schatenseite.android.datepreference; + +/* based on https://github.com/bostonandroid/DatePreference */ + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.content.res.TypedArray; +import android.os.Parcel; +import android.os.Parcelable; +import android.preference.DialogPreference; +import android.util.AttributeSet; +import android.view.View; +import android.widget.DatePicker; + +public class DatePreference extends DialogPreference implements + DatePicker.OnDateChangedListener { + private String dateString; + private String changedValueCanBeNull; + private DatePicker datePicker; + + public DatePreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public DatePreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + /** + * Produces a DatePicker set to the date produced by {@link #getDate()}. + * When overriding be sure to call the super. + * + * @return a DatePicker with the date set + */ + @Override + protected View onCreateDialogView() { + this.datePicker = new DatePicker(getContext()); + Calendar calendar = getDate(); + datePicker.init(calendar.get(Calendar.YEAR), + calendar.get(Calendar.MONTH), + calendar.get(Calendar.DAY_OF_MONTH), this); + return datePicker; + } + + /** + * Produces the date used for the date picker. If the user has not selected + * a date, produces the default from the XML's android:defaultValue. If the + * default is not set in the XML or if the XML's default is invalid it uses + * the value produced by {@link #defaultCalendar()}. + * + * @return the Calendar for the date picker + */ + public Calendar getDate() { + try { + Date date = formatter().parse(defaultValue()); + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + return cal; + } catch (java.text.ParseException e) { + return defaultCalendar(); + } + } + + /** + * Set the selected date to the specified string. + * + * @param dateString + * The date, represented as a string, in the format specified by + * {@link #formatter()}. + */ + public void setDate(String dateString) { + this.dateString = dateString; + } + + /** + * Produces the date formatter used for dates in the XML. The default is + * yyyy.MM.dd. Override this to change that. + * + * @return the SimpleDateFormat used for XML dates + */ + public static SimpleDateFormat formatter() { + return new SimpleDateFormat("yyyy.MM.dd"); + } + + /** + * Produces the date formatter used for showing the date in the summary. The + * default is MMMM dd, yyyy. Override this to change it. + * + * @return the SimpleDateFormat used for summary dates + */ + public static SimpleDateFormat summaryFormatter() { + return new SimpleDateFormat("dd. MMMM yyyy"); + } + + @Override + protected Object onGetDefaultValue(TypedArray a, int index) { + return a.getString(index); + } + + /** + * Called when the date picker is shown or restored. If it's a restore it + * gets the persisted value, otherwise it persists the value. + */ + @Override + protected void onSetInitialValue(boolean restoreValue, Object def) { + if (restoreValue) { + this.dateString = getPersistedString(defaultValue()); + setTheDate(this.dateString); + } else { + boolean wasNull = this.dateString == null; + setDate((String) def); + if (!wasNull) + persistDate(this.dateString); + } + } + + /** + * Called when Android pauses the activity. + */ + @Override + protected Parcelable onSaveInstanceState() { + if (isPersistent()) + return super.onSaveInstanceState(); + else + return new SavedState(super.onSaveInstanceState()); + } + + /** + * Called when Android restores the activity. + */ + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state == null || !state.getClass().equals(SavedState.class)) { + super.onRestoreInstanceState(state); + setTheDate(((SavedState) state).dateValue); + } else { + SavedState s = (SavedState) state; + super.onRestoreInstanceState(s.getSuperState()); + setTheDate(s.dateValue); + } + } + + /** + * Called when the user changes the date. + */ + public void onDateChanged(DatePicker view, int year, int month, int day) { + Calendar selected = new GregorianCalendar(year, month, day); + this.changedValueCanBeNull = formatter().format(selected.getTime()); + } + + /** + * Called when the dialog is closed. If the close was by pressing "OK" it + * saves the value. + */ + @Override + protected void onDialogClosed(boolean shouldSave) { + if (shouldSave && this.changedValueCanBeNull != null) { + setTheDate(this.changedValueCanBeNull); + this.changedValueCanBeNull = null; + } + } + + private void setTheDate(String s) { + setDate(s); + persistDate(s); + } + + public String getSummaryString() { + return summaryFormatter().format(getDate().getTime()); + } + + private void persistDate(String s) { + persistString(s); + //setSummary(summaryFormatter().format(getDate().getTime())); + } + + /** + * The default date to use when the XML does not set it or the XML has an + * error. + * + * @return the Calendar set to the default date + */ + public static Calendar defaultCalendar() { + return new GregorianCalendar(); + } + + /** + * The defaultCalendar() as a string using the {@link #formatter()}. + * + * @return a String representation of the default date + */ + public static String defaultCalendarString() { + return formatter().format(defaultCalendar().getTime()); + } + + private String defaultValue() { + if (this.dateString == null) + setDate(defaultCalendarString()); + return this.dateString; + } + + /** + * Called whenever the user clicks on a button. Invokes + * {@link #onDateChanged(DatePicker, int, int, int)} and + * {@link #onDialogClosed(boolean)}. Be sure to call the super when + * overriding. + */ + @Override + public void onClick(DialogInterface dialog, int which) { + super.onClick(dialog, which); + datePicker.clearFocus(); + onDateChanged(datePicker, datePicker.getYear(), datePicker.getMonth(), + datePicker.getDayOfMonth()); + onDialogClosed(which == DialogInterface.BUTTON1); // OK? + } + + /** + * Produces the date the user has selected for the given preference, as a + * calendar. + * + * @param preferences + * the SharedPreferences to get the date from + * @param field + * the name of the preference to get the date from + * @return a Calendar that the user has selected + */ + public static Calendar getDateFor(SharedPreferences preferences, + String field) { + Date date = stringToDate(preferences.getString(field, + defaultCalendarString())); + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + return cal; + } + + private static Date stringToDate(String dateString) { + try { + return formatter().parse(dateString); + } catch (ParseException e) { + return defaultCalendar().getTime(); + } + } + + private static class SavedState extends BaseSavedState { + String dateValue; + + public SavedState(Parcel p) { + super(p); + dateValue = p.readString(); + } + + public SavedState(Parcelable p) { + super(p); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeString(dateValue); + } + + @SuppressWarnings("unused") + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } +} \ No newline at end of file diff --git a/src/de/schatenseite/android/waldemar/WaldemarPreferences.java b/src/de/schatenseite/android/waldemar/WaldemarPreferences.java new file mode 100644 index 0000000..7002e74 --- /dev/null +++ b/src/de/schatenseite/android/waldemar/WaldemarPreferences.java @@ -0,0 +1,103 @@ +package de.schatenseite.android.waldemar; + +import android.appwidget.AppWidgetManager; +import android.content.Intent; +import android.os.Bundle; +import android.preference.EditTextPreference; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceActivity; +import android.preference.PreferenceManager; +import de.schatenseite.android.datepreference.DatePreference; + +public class WaldemarPreferences extends PreferenceActivity { + int widgetId; + public void enableDisablePreferences(String val) { + EditTextPreference pref_name = (EditTextPreference)findPreference("pref_name"); + ListPreference pref_mode = (ListPreference)findPreference("pref_mode"); + EditTextPreference pref_duration = (EditTextPreference)findPreference("pref_duration"); + DatePreference pref_dateStart = (DatePreference)findPreference("pref_dateStart"); + DatePreference pref_dateThen = (DatePreference)findPreference("pref_dateThen"); + + pref_name.setSummary(pref_name.getText()); + + int index = pref_mode.findIndexOfValue(val); + if (index == 0) { + pref_mode.setSummary(R.string.mode1); + pref_duration.setEnabled(false); + pref_duration.setSummary(R.string.duration_summary); + pref_dateStart.setEnabled(false); + pref_dateStart.setSummary(R.string.dateStart_summary); + pref_dateThen.setEnabled(true); + pref_dateThen.setSummary(pref_dateThen.getSummaryString()); + } else if (index == 1) { + pref_mode.setSummary(R.string.mode2); + pref_duration.setEnabled(false); + pref_duration.setSummary(R.string.duration_summary); + pref_dateStart.setEnabled(true); + pref_dateStart.setSummary(pref_dateStart.getSummaryString()); + pref_dateThen.setEnabled(true); + pref_dateThen.setSummary(pref_dateThen.getSummaryString()); + } else if (index == 2) { + pref_mode.setSummary(R.string.mode3); + pref_duration.setEnabled(true); + pref_duration.setSummary(pref_duration.getText()+" "+getApplicationContext().getString(R.string.days)); + pref_dateStart.setEnabled(false); + pref_dateStart.setSummary(R.string.dateStart_summary); + pref_dateThen.setEnabled(true); + pref_dateThen.setSummary(pref_dateThen.getSummaryString()); + } else if (index == 3) { + pref_mode.setSummary(R.string.mode4); + pref_duration.setEnabled(true); + pref_duration.setSummary(pref_duration.getText()+" "+getApplicationContext().getString(R.string.days)); + pref_dateStart.setEnabled(true); + pref_dateStart.setSummary(pref_dateStart.getSummaryString()); + pref_dateThen.setEnabled(false); + pref_dateThen.setSummary(R.string.dateThen_summary); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + PreferenceManager.setDefaultValues(this, R.xml.preferences, false); + addPreferencesFromResource(R.xml.preferences); + + Intent intent=getIntent(); + Bundle extras=intent.getExtras(); + if (extras != null) { + widgetId=extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + } + + final EditTextPreference pref_name = (EditTextPreference)findPreference("pref_name"); + final ListPreference pref_mode = (ListPreference)findPreference("pref_mode"); + + String val = pref_mode.getValue(); + enableDisablePreferences(val); + + pref_name.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference preference, Object newValue) { + pref_name.setSummary((CharSequence)newValue); + return true; + } + }); + pref_mode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference preference, Object newValue) { + final String val = newValue.toString(); + enableDisablePreferences(val); + return true; + } + }); + } + + @Override + public void onBackPressed() { + // this is the intent broadcast/returned to the widget + Intent updateIntent = new Intent(this, WaldemarWidget.class); + updateIntent.setAction("PreferencesUpdated"); + updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); + setResult(RESULT_OK, updateIntent); + sendBroadcast(updateIntent); + finish(); + } +} \ No newline at end of file diff --git a/src/de/schatenseite/android/waldemar/WaldemarWidget.java b/src/de/schatenseite/android/waldemar/WaldemarWidget.java new file mode 100644 index 0000000..5227bbb --- /dev/null +++ b/src/de/schatenseite/android/waldemar/WaldemarWidget.java @@ -0,0 +1,111 @@ +package de.schatenseite.android.waldemar; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.widget.RemoteViews; +import android.widget.Toast; +import de.schatenseite.android.datepreference.DatePreference; + +public class WaldemarWidget extends AppWidgetProvider { + public static String MIDNIGHTLY_WIDGET_UPDATE = "MIDNIGHTLY_WIDGET_UPDATE"; + static AlarmManager myAlarmManager; + static PendingIntent myPendingIntent; + + @Override + public void onEnabled(Context context) { + Intent intent = new Intent( + WaldemarWidget.MIDNIGHTLY_WIDGET_UPDATE); + PendingIntent pendingIntent = PendingIntent.getBroadcast( + context, 0, intent, 0); + AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); + Calendar calendar = new GregorianCalendar(); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + + alarmManager.setRepeating(AlarmManager.RTC, + calendar.getTimeInMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent); + + WaldemarWidget.SaveAlarmManager(alarmManager, pendingIntent); + Toast.makeText(context, "onEnabled()", Toast.LENGTH_LONG).show(); + } + + @Override + public void onDisabled(Context context) { + myAlarmManager.cancel(myPendingIntent); + Toast.makeText(context, "onDisabled()", Toast.LENGTH_LONG).show(); + } + + @Override + public void onReceive(Context context, Intent intent) { + if (MIDNIGHTLY_WIDGET_UPDATE.equals(intent.getAction()) || "PreferencesUpdated".equals(intent.getAction())) { + Bundle extras = intent.getExtras(); + if (extras != null) { + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); + ComponentName thisAppWidget = new ComponentName( + context.getPackageName(), + WaldemarWidget.class.getName()); + int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget); + + onUpdate(context, appWidgetManager, appWidgetIds); + } + } else { + super.onReceive(context, intent); + } + } + + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, + int[] appWidgetIds) { + for (int appWidgetId : appWidgetIds) { + updateAppWidget(context, appWidgetManager, appWidgetId); + } + } + + public static void updateAppWidget(Context context, + AppWidgetManager appWidgetManager, int appWidgetId) { + RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + remoteViews.setTextViewText(R.id.name, prefs.getString("pref_name", context.getString(R.string.title))); + + Calendar calNow = new GregorianCalendar(); + calNow.set(Calendar.HOUR_OF_DAY, 0); + calNow.set(Calendar.MINUTE, 0); + calNow.set(Calendar.SECOND, 0); + long timeNow = calNow.getTimeInMillis(); + + Calendar calThen = DatePreference.getDateFor(PreferenceManager.getDefaultSharedPreferences(context), "pref_dateThen"); + long timeThen = calThen.getTimeInMillis(); + + long days = Math.round((double) (timeThen - timeNow) / 86400000.); + remoteViews.setTextViewText(R.id.daycount, String.valueOf(days)); + + DateFormat format = SimpleDateFormat.getTimeInstance( + SimpleDateFormat.MEDIUM, Locale.getDefault()); + remoteViews.setTextViewText(R.id.debug, format.format(new Date())); + + appWidgetManager.updateAppWidget(appWidgetId, remoteViews); + } + + static void SaveAlarmManager(AlarmManager tAlarmManager, + PendingIntent tPendingIntent) { + myAlarmManager = tAlarmManager; + myPendingIntent = tPendingIntent; + } +} \ No newline at end of file