diff --git a/HypoAlarm/src/main/AndroidManifest.xml b/HypoAlarm/src/main/AndroidManifest.xml index f28cadd..2621bb4 100644 --- a/HypoAlarm/src/main/AndroidManifest.xml +++ b/HypoAlarm/src/main/AndroidManifest.xml @@ -16,8 +16,8 @@ - - + + = 19) { diff --git a/HypoAlarm/src/main/java/za/org/treehouse/hypoalarm/BootReceiver.java b/HypoAlarm/src/main/java/za/org/treehouse/hypoalarm/BootReceiver.java index 37cbfb8..eeddc1b 100644 --- a/HypoAlarm/src/main/java/za/org/treehouse/hypoalarm/BootReceiver.java +++ b/HypoAlarm/src/main/java/za/org/treehouse/hypoalarm/BootReceiver.java @@ -1,12 +1,9 @@ package za.org.treehouse.hypoalarm; -import android.app.AlarmManager; -import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.os.Build; import android.preference.PreferenceManager; import android.util.Log; @@ -17,21 +14,10 @@ public class BootReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { - // Reset for tomorrow; as of API 19, setRepeating() is inexact, so we use setExact() String alarmTimeStr = sharedPref.getString(context.getString(R.string.AlarmTimePref), null); - Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), true); - if (alarmTimeStr != null && alarmActive) { - // If it's later than alarmTimeStr, Calendar automatically advances the day. - Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr); - AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); - if (Build.VERSION.SDK_INT >= 19) { - alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmPendingIntent); - } else { - alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmPendingIntent); - } - Log.d("BootReceiver", "Setting alarm for "+MainActivity.debugDate(cal)); - } + Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr); + Log.d("BootReceiver", "Booting: Setting alarm for " + MainActivity.debugDate(cal)); + MainActivity.resetAlarm(context, cal); } } } diff --git a/HypoAlarm/src/main/java/za/org/treehouse/hypoalarm/MainActivity.java b/HypoAlarm/src/main/java/za/org/treehouse/hypoalarm/MainActivity.java index 931ceb4..f0589a3 100644 --- a/HypoAlarm/src/main/java/za/org/treehouse/hypoalarm/MainActivity.java +++ b/HypoAlarm/src/main/java/za/org/treehouse/hypoalarm/MainActivity.java @@ -60,13 +60,11 @@ import java.util.regex.Pattern; public class MainActivity extends ActionBarActivity { public static final int ALARM_REQUEST = 1; public static final int GRACE_REQUEST = 2; - public static final int PRENOTIFY_REQUEST = 3; + public static final int PRE_NOTIFY_REQUEST = 3; public static final int CANCEL_GRACE_REQUEST = 4; public static final int CANCEL_ALARM_REQUEST = 5; public static final int PHONE_NUMBER_REQUEST = 6; public static final int RINGTONE_REQUEST = 7; - private static Button alarmTimeButton; - private static EditText messageButton; public static final Boolean HYPOALARM_DEBUG = false; @@ -91,63 +89,18 @@ public class MainActivity extends ActionBarActivity { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_main, container, false); - return rootView; + return inflater.inflate(R.layout.fragment_main, container, false); } public void onStart() { - super.onStart(); - final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity()); - // Allow alarm to activate - Boolean alarmActive = sharedPref.getBoolean(getString(R.string.AlarmActivePref), true); - CompoundButton alarmActiveSwitch = (CompoundButton) getActivity().findViewById(R.id.alarm_active_switch); - alarmActiveSwitch.setChecked(alarmActive); - alarmActiveSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton compoundButton, boolean b) { - AlarmManager alarmManager; - PendingIntent alarmPendingIntent, gracePendingIntent, preNotifyPendingIntent; - SharedPreferences.Editor editor = sharedPref.edit(); - - editor.putBoolean(getString(R.string.AlarmActivePref), b); - editor.commit(); - - if (!b) { - // Cancel any current alarm - alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE); - Intent alarmIntent = new Intent(getActivity(), AlarmReceiver.class); - alarmPendingIntent = PendingIntent.getBroadcast(getActivity(), ALARM_REQUEST, alarmIntent, 0); - alarmManager.cancel(alarmPendingIntent); - // Cancel any pre-alarm notification - Intent preNotifyIntent = new Intent(getActivity(), AlarmReceiver.class); - preNotifyPendingIntent = PendingIntent.getBroadcast(getActivity(), PRENOTIFY_REQUEST, alarmIntent, 0); - alarmManager.cancel(preNotifyPendingIntent); - // Cancel any grace period - Intent graceIntent = new Intent(getActivity(), GraceReceiver.class); - gracePendingIntent = PendingIntent.getBroadcast(getActivity(), GRACE_REQUEST, graceIntent, 0); - alarmManager.cancel(gracePendingIntent); - // Stop any notifications - getActivity().stopService(new Intent(getActivity(), AlarmNotify.class)); - getActivity().stopService(new Intent(getActivity(), PreAlarmNotify.class)); - - Log.d("MainActivity", "Alarms cancelled"); - Toast.makeText(getActivity().getApplicationContext(), getString(R.string.alarmCancelled), Toast.LENGTH_SHORT).show(); - } else { - // Activate the alarm - DialogFragment alarmFragment = new TimePickerFragment(); - alarmFragment.show(getActivity().getSupportFragmentManager(), "alarmTimePicker"); - alarmFragment.dismiss(); - } - } - }); - + super.onStart(); // Set alarm time - String defaultTimeStr = "09:00"; + final String defaultTimeStr = "09:00"; String alarmTimeStr = verifyTimeString(sharedPref.getString(getString(R.string.AlarmTimePref), defaultTimeStr)); - alarmTimeButton = (Button) getActivity().findViewById(R.id.alarm_time); + final Button alarmTimeButton = (Button) getActivity().findViewById(R.id.alarm_time); // When debugging, set the alarm for one minute's time if (HYPOALARM_DEBUG) { @@ -165,15 +118,37 @@ public class MainActivity extends ActionBarActivity { } }); - // Activate the time when starting the app. - DialogFragment alarmFragment = new TimePickerFragment(); - alarmFragment.show(getActivity().getSupportFragmentManager(), "alarmTimePicker"); - alarmFragment.dismiss(); + // Allow alarm to activate + Boolean alarmActive = sharedPref.getBoolean(getString(R.string.AlarmActivePref), true); + final CompoundButton alarmActiveSwitch = (CompoundButton) getActivity().findViewById(R.id.alarm_active_switch); + alarmActiveSwitch.setChecked(alarmActive); + alarmActiveSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean active) { + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putBoolean(getString(R.string.AlarmActivePref), active); + editor.commit(); + + if (!active) { + cancelAllAlarms(getActivity()); + Toast.makeText(getActivity(), getString(R.string.alarmCancelled), Toast.LENGTH_SHORT).show(); + } else { + String alarmTimeStr = verifyTimeString(sharedPref.getString(getString(R.string.AlarmTimePref), defaultTimeStr)); + Calendar cal = TimeStringToCalendar(alarmTimeStr); + resetAlarm(getActivity(), cal); + } + } + }); + + // Activate the time (after setting alarmActive) when starting the app. + Calendar cal = TimeStringToCalendar(alarmTimeStr); + resetAlarm(getActivity(), cal); // Set grace period - int defaultGrace = 60; + final int defaultGrace = 60; int gracePeriod = sharedPref.getInt(getString(R.string.GracePeriodPref), defaultGrace); - Spinner gracePeriodSpinner = (Spinner) getActivity().findViewById(R.id.grace_period); + final Spinner gracePeriodSpinner = (Spinner) getActivity().findViewById(R.id.grace_period); + gracePeriodSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity()); @@ -191,7 +166,7 @@ public class MainActivity extends ActionBarActivity { } }); // Set value of drop-down list to value of gracePeriodStr - ArrayAdapter gracePeriodSpinnerAdapter = (ArrayAdapter) gracePeriodSpinner.getAdapter(); + ArrayAdapter gracePeriodSpinnerAdapter = (ArrayAdapter) gracePeriodSpinner.getAdapter(); int spinnerPosition = gracePeriodSpinnerAdapter.getPosition(MinutesToGracePeriodStr(gracePeriod)); gracePeriodSpinner.setSelection(spinnerPosition); @@ -218,7 +193,7 @@ public class MainActivity extends ActionBarActivity { // Set phone number String phoneNumberStr = sharedPref.getString(getString(R.string.PhoneNumberPref), null); - EditText phoneNumberButton = (EditText) getActivity().findViewById(R.id.phone_number); + final EditText phoneNumberButton = (EditText) getActivity().findViewById(R.id.phone_number); phoneNumberButton.setText(phoneNumberStr); phoneNumberButton.setOnClickListener(new View.OnClickListener() { @Override @@ -230,7 +205,7 @@ public class MainActivity extends ActionBarActivity { // Set message String messageStr = sharedPref.getString(getString(R.string.MessagePref), getString(R.string.defaultMessage)); - messageButton = (EditText) getActivity().findViewById(R.id.message); + final EditText messageButton = (EditText) getActivity().findViewById(R.id.message); messageButton.setText(messageStr); messageButton.setOnClickListener(new View.OnClickListener() { @Override @@ -285,7 +260,7 @@ public class MainActivity extends ActionBarActivity { // If we're answering a ringtone dialogue, update the correct button if (requestCode == RINGTONE_REQUEST && resultCode == RESULT_OK) { - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext()); + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity()); SharedPreferences.Editor editor = sharedPref.edit(); Button ringtoneButton = (Button) getActivity().findViewById(R.id.ringtone); @@ -302,16 +277,92 @@ public class MainActivity extends ActionBarActivity { } } + public static void cancelAllAlarms(Context context) { + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + + // Cancel any current alarm + Intent alarmIntent = new Intent(context, AlarmReceiver.class); + PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(context, ALARM_REQUEST, alarmIntent, 0); + alarmManager.cancel(alarmPendingIntent); + + // Cancel any pre-alarm notification + Intent preNotifyIntent = new Intent(context, PreAlarmReceiver.class); + PendingIntent preNotifyPendingIntent = PendingIntent.getBroadcast(context, PRE_NOTIFY_REQUEST, preNotifyIntent, 0); + alarmManager.cancel(preNotifyPendingIntent); + + // Cancel any grace period + Intent graceIntent = new Intent(context, GraceReceiver.class); + PendingIntent gracePendingIntent = PendingIntent.getBroadcast(context, GRACE_REQUEST, graceIntent, 0); + alarmManager.cancel(gracePendingIntent); + + // Stop any notifications + context.stopService(new Intent(context, AlarmNotify.class)); + context.stopService(new Intent(context, PreAlarmNotify.class)); + + Log.d("MainActivity", "Alarms cancelled"); + } + + public static void resetAlarm(Context context, Calendar cal) { + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + PendingIntent alarmPendingIntent, preNotifyPendingIntent; + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); + Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), true); + + cancelAllAlarms(context); + + // Advance cal to tomorrow if setting a time earlier than now + if (cal.before(Calendar.getInstance())) { + cal.add(Calendar.DAY_OF_MONTH, 1); + } + + if (alarmActive) { + // Initialise alarm, which displays a dialog and system alert, and + // calls AlarmManager with grace_period as the delay + // which in turn, sends SMS if dialog is not exited. + // Advance to tomorrow if setting a time earlier than now + Intent alarmIntent = new Intent(context, AlarmReceiver.class); + alarmPendingIntent = PendingIntent.getBroadcast(context, ALARM_REQUEST, alarmIntent, 0); + // Set or reset alarm + if (Build.VERSION.SDK_INT >= 19) { + alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmPendingIntent); + } else { + alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmPendingIntent); + } + Log.d("MainActivity", "Setting alarm for " + MainActivity.debugDate(cal)); + + // Set an alarm for the pre-alarm notification, half an hour before the alarm + Calendar preNotifyCal = (Calendar) cal.clone(); + preNotifyCal.add(Calendar.MINUTE, -30); + Intent preNotifyIntent = new Intent(context, PreAlarmReceiver.class); + preNotifyPendingIntent = PendingIntent.getBroadcast(context, PRE_NOTIFY_REQUEST, preNotifyIntent, 0); + // Set or reset alarm + if (Build.VERSION.SDK_INT >= 19) { + alarmManager.setExact(AlarmManager.RTC_WAKEUP, preNotifyCal.getTimeInMillis(), preNotifyPendingIntent); + } else { + alarmManager.set(AlarmManager.RTC_WAKEUP, preNotifyCal.getTimeInMillis(), preNotifyPendingIntent); + } + Log.d("MainActivity", "Setting pre-alarm for " + MainActivity.debugDate(preNotifyCal)); + + // Set boot receiver, so alarm restarts on boot + ComponentName bootReceiver = new ComponentName(context, BootReceiver.class); + PackageManager pm = context.getPackageManager(); + pm.setComponentEnabledSetting(bootReceiver, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); + Log.d("MainActivity", "Setting BootReceiver"); + + } + } + // Alarm time picker public static class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener { SharedPreferences sharedPref; - private AlarmManager alarmManager; - private PendingIntent alarmPendingIntent, preNotifyPendingIntent; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity()); // Use the current set time as the default value for the picker + Button alarmTimeButton = (Button) getActivity().findViewById(R.id.alarm_time); String alarmTimeStr = alarmTimeButton.getText().toString(); // For selecting a time, the date doesn't matter, just the hour and minute Calendar cal = TimeStringToCalendar(alarmTimeStr); @@ -324,17 +375,11 @@ public class MainActivity extends ActionBarActivity { } public void onTimeSet(TimePicker view, int hourOfDay, int minute) { - Boolean alarmActive = sharedPref.getBoolean(getString(R.string.AlarmActivePref), true); - // Set time preference Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, hourOfDay); cal.set(Calendar.MINUTE, minute); cal.set(Calendar.SECOND, 0); - // Advance to tomorrow if setting a time earlier than now - if (cal.before(Calendar.getInstance())) { - cal.add(Calendar.DAY_OF_MONTH, 1); - } String alarmStr = CalendarToTimeString(cal); SharedPreferences.Editor editor = sharedPref.edit(); @@ -344,73 +389,37 @@ public class MainActivity extends ActionBarActivity { Button alarm_time = (Button) getActivity().findViewById(R.id.alarm_time); alarm_time.setText(alarmStr); - if (alarmActive) { - // Initialise alarm, which displays a dialog and system alert, and - // calls AlarmManager with grace_period as the delay - // which in turn, sends SMS if dialog is not exited. - alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE); - Intent alarmIntent = new Intent(getActivity(), AlarmReceiver.class); - alarmPendingIntent = PendingIntent.getBroadcast(getActivity(), ALARM_REQUEST, alarmIntent, 0); - // Cancel any existing alarms - alarmManager.cancel(alarmPendingIntent); - // Set or reset alarm - if (Build.VERSION.SDK_INT >= 19) { - alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmPendingIntent); - } else { - alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmPendingIntent); - } - Log.d("MainActivity", "Setting alarm for " + MainActivity.debugDate(cal)); + // Set actual alarm + resetAlarm(getActivity(), cal); - // Set an alarm for the pre-alarm notification, half an hour before the alarm - Calendar preNotifyCal = cal; - preNotifyCal.add(Calendar.MINUTE, -30); - Intent preNotifyIntent = new Intent(getActivity(), PreAlarmReceiver.class); - preNotifyPendingIntent = PendingIntent.getBroadcast(getActivity(), PRENOTIFY_REQUEST, preNotifyIntent, 0); - // Cancel any existing alarms - alarmManager.cancel(preNotifyPendingIntent); - // Set or reset alarm - if (Build.VERSION.SDK_INT >= 19) { - alarmManager.setExact(AlarmManager.RTC_WAKEUP, preNotifyCal.getTimeInMillis(), preNotifyPendingIntent); - } else { - alarmManager.set(AlarmManager.RTC_WAKEUP, preNotifyCal.getTimeInMillis(), preNotifyPendingIntent); - } - Log.d("MainActivity", "Setting pre-alarm for " + MainActivity.debugDate(preNotifyCal)); - - // Set boot receiver, so alarm restarts on boot - ComponentName receiver = new ComponentName(getActivity(), BootReceiver.class); - PackageManager pm = getActivity().getPackageManager(); - pm.setComponentEnabledSetting(receiver, - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, - PackageManager.DONT_KILL_APP); - - // Display toast - CharSequence text = getString(R.string.alarmSetToast) + " " + alarmStr; - Toast.makeText(getActivity().getApplicationContext(), text, Toast.LENGTH_SHORT).show(); - } + // Display toast + CharSequence text = getString(R.string.alarmSetToast) + " " + CalendarToTimeString(cal); + Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT).show(); } } public static class PhonePickerFragment extends DialogFragment { - EditText phoneButton; + SharedPreferences sharedPref; EditText phoneInput; - Button contactsButton; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity()); + sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity()); AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); alert.setMessage(R.string.setPhoneNumber); LayoutInflater inflater = getActivity().getLayoutInflater(); + // Pass null instead of the parent ViewGroup, as the parent View is a + // ScrollView, which can only have one direct child View dialogView = inflater.inflate(R.layout.phone_dialog, null); alert.setView(dialogView); - phoneButton = (EditText) getActivity().findViewById(R.id.phone_number); + final EditText phoneButton = (EditText) getActivity().findViewById(R.id.phone_number); phoneInput = (EditText) dialogView.findViewById(R.id.dialog_phone_number); phoneInput.setText(phoneButton.getText().toString()); phoneInput.setSelection(phoneInput.getText().length()); - contactsButton = (Button) dialogView.findViewById(R.id.dialog_contacts_button); + final Button contactsButton = (Button) dialogView.findViewById(R.id.dialog_contacts_button); alert.setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { diff --git a/HypoAlarm/src/main/res/drawable-hdpi/ic_handle_pressed.png b/HypoAlarm/src/main/res/drawable-hdpi/ic_handle_pressed.png deleted file mode 100644 index 58a5f16..0000000 Binary files a/HypoAlarm/src/main/res/drawable-hdpi/ic_handle_pressed.png and /dev/null differ diff --git a/HypoAlarm/src/main/res/drawable-mdpi/ic_handle_pressed.png b/HypoAlarm/src/main/res/drawable-mdpi/ic_handle_pressed.png deleted file mode 100644 index 0187a02..0000000 Binary files a/HypoAlarm/src/main/res/drawable-mdpi/ic_handle_pressed.png and /dev/null differ diff --git a/HypoAlarm/src/main/res/drawable-xhdpi/ic_handle_pressed.png b/HypoAlarm/src/main/res/drawable-xhdpi/ic_handle_pressed.png deleted file mode 100644 index 2d28009..0000000 Binary files a/HypoAlarm/src/main/res/drawable-xhdpi/ic_handle_pressed.png and /dev/null differ diff --git a/HypoAlarm/src/main/res/layout/fragment_main.xml b/HypoAlarm/src/main/res/layout/fragment_main.xml index 9886621..e477018 100644 --- a/HypoAlarm/src/main/res/layout/fragment_main.xml +++ b/HypoAlarm/src/main/res/layout/fragment_main.xml @@ -62,7 +62,7 @@ android:layout_height="wrap_content" android:id="@+id/alarm_time" android:gravity="center_vertical" - style="?android:attr/borderlessButtonStyle" + style="@style/borderless_button" android:layout_column="1" /> diff --git a/HypoAlarm/src/main/res/values-small/styles.xml b/HypoAlarm/src/main/res/values-small/styles.xml new file mode 100644 index 0000000..d4e61d9 --- /dev/null +++ b/HypoAlarm/src/main/res/values-small/styles.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/HypoAlarm/src/main/res/values/styles.xml b/HypoAlarm/src/main/res/values/styles.xml index 898d102..822720e 100644 --- a/HypoAlarm/src/main/res/values/styles.xml +++ b/HypoAlarm/src/main/res/values/styles.xml @@ -3,4 +3,6 @@ + +