Prevent subsequent alarms from snoozing; make pre-alarm an hour earlier; correct boot receiver bug.
This commit is contained in:
		| @@ -8,10 +8,11 @@ | ||||
|     </facet> | ||||
|     <facet type="android" name="Android"> | ||||
|       <configuration> | ||||
|         <option name="SELECTED_BUILD_VARIANT" value="release" /> | ||||
|         <option name="ASSEMBLE_TASK_NAME" value="assembleRelease" /> | ||||
|         <option name="COMPILE_JAVA_TASK_NAME" value="compileReleaseJava" /> | ||||
|         <option name="SOURCE_GEN_TASK_NAME" value="generateReleaseSources" /> | ||||
|         <option name="SELECTED_BUILD_VARIANT" value="debug" /> | ||||
|         <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" /> | ||||
|         <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugJava" /> | ||||
|         <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" /> | ||||
|         <option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" /> | ||||
|         <option name="ALLOW_USER_CONFIGURATION" value="false" /> | ||||
|         <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" /> | ||||
|         <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" /> | ||||
| @@ -21,21 +22,26 @@ | ||||
|     </facet> | ||||
|   </component> | ||||
|   <component name="NewModuleRootManager" inherit-compiler-output="false"> | ||||
|     <output url="file://$MODULE_DIR$/build/classes/release" /> | ||||
|     <output url="file://$MODULE_DIR$/build/classes/debug" /> | ||||
|     <exclude-output /> | ||||
|     <content url="file://$MODULE_DIR$"> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/r/release" isTestSource="false" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/aidl/release" isTestSource="false" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/release" isTestSource="false" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/rs/release" isTestSource="false" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/res/rs/release" type="java-resource" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/release/res" type="java-resource" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/release/resources" type="java-resource" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/release/aidl" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/release/assets" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/release/java" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/release/jni" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/release/rs" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/r/debug" isTestSource="false" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/aidl/debug" isTestSource="false" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/debug" isTestSource="false" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/rs/debug" isTestSource="false" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/res/rs/debug" type="java-resource" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/r/test/debug" isTestSource="true" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/aidl/test/debug" isTestSource="true" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/test/debug" isTestSource="true" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/source/rs/test/debug" isTestSource="true" generated="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/build/res/rs/test/debug" type="java-test-resource" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" /> | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import android.view.WindowManager; | ||||
| import net.frakbot.glowpadbackport.GlowPadView; | ||||
|  | ||||
| public class AlarmAlertActivity extends Activity { | ||||
|     public  static Activity alertActivity; | ||||
|     public static Activity alertActivity; | ||||
|  | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|   | ||||
| @@ -16,10 +16,10 @@ public class AlarmChangeReceiver extends BroadcastReceiver { | ||||
|         if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED") || | ||||
|                 intent.getAction().equals("android.intent.action.TIMEZONE_CHANGED") || | ||||
|                 intent.getAction().equals("android.intent.action.TIME_SET")) { | ||||
|             String alarmTimeStr = sharedPref.getString(context.getString(R.string.AlarmTimePref), null); | ||||
|             String alarmTimeStr = sharedPref.getString(context.getString(R.string.AlarmTimePref), MainActivity.defaultTimeStr); | ||||
|             Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr); | ||||
|             Log.d("AlarmChangeReceiver", intent.getAction() + ": resetting alarm for " + MainActivity.debugDate(cal)); | ||||
|             MainActivity.resetAlarm(context, cal); | ||||
|             MainActivity.setAlarm(context, cal); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -42,7 +42,7 @@ public class AlarmNotify extends Service { | ||||
|         Log.d("AlarmNotify", "Notification started."); | ||||
|  | ||||
|         //final String phoneNumber = sharedPref.getString(getString(R.string.PhoneNumberPref), null); | ||||
|         final int gracePeriod = sharedPref.getInt(getString(R.string.GracePeriodPref), 60); | ||||
|         final int gracePeriod = sharedPref.getInt(getString(R.string.GracePeriodPref), MainActivity.defaultGracePeriod); | ||||
|  | ||||
|         Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_grey); | ||||
|         final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package za.org.treehouse.hypoalarm; | ||||
|  | ||||
| import android.app.ActivityManager; | ||||
| import android.app.AlarmManager; | ||||
| import android.app.PendingIntent; | ||||
| import android.app.Service; | ||||
| @@ -18,7 +19,7 @@ import java.util.Calendar; | ||||
|  | ||||
| public class AlarmService extends Service { | ||||
|     private static final int SNOOZE_TIME = 1000*60*5; // Snooze for 5 minutes if need be | ||||
|     private static final int ALERT_LIFE  = 1000*60*1; // 2 minutes | ||||
|     private static final int ALERT_LIFE  = 1000*60*2; // 2 minutes | ||||
|     private static PowerManager.WakeLock wl; | ||||
|     private static AlarmManager alarmManager; | ||||
|     private static Intent alarmServiceIntent, alertActivityIntent, notifyIntent; | ||||
| @@ -36,13 +37,15 @@ public class AlarmService extends Service { | ||||
|         // Ensure that CPU runs while the service is running, so we don't miss an alert or snooze | ||||
|         PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); | ||||
|         wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AlarmService"); | ||||
|         // TODO: wake lock? | ||||
|         //wl.acquire(); | ||||
|  | ||||
|         alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); | ||||
|  | ||||
|     } | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         Log.d("AlarmService", "Destroying alarm"); | ||||
|         Log.d("AlarmService", "Destroying alarm (alarmStarted: " + alarmStarted + ")"); | ||||
|         if (alarmStarted) { | ||||
|             stopAlert(getApplicationContext()); | ||||
|             alarmStarted = false; | ||||
| @@ -56,9 +59,9 @@ public class AlarmService extends Service { | ||||
|     public int onStartCommand(Intent intent, int flags, int startId) { | ||||
|         alarmServiceIntent = intent; | ||||
|         SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); | ||||
|         final Boolean alarmActive = sharedPref.getBoolean(getString(R.string.AlarmActivePref), true); | ||||
|         final int gracePeriod = sharedPref.getInt(getString(R.string.GracePeriodPref), 60); | ||||
|         final String alarmTimeStr = sharedPref.getString(getString(R.string.AlarmTimePref), null); | ||||
|         final Boolean alarmActive = sharedPref.getBoolean(getString(R.string.AlarmActivePref), MainActivity.defaultActive); | ||||
|         final String alarmTimeStr = sharedPref.getString(getString(R.string.AlarmTimePref), MainActivity.defaultTimeStr); | ||||
|         final int gracePeriod = sharedPref.getInt(getString(R.string.GracePeriodPref), MainActivity.defaultGracePeriod); | ||||
|  | ||||
|         if (alarmActive) { | ||||
|             // Cancel the pre-alarm notification, if it exists | ||||
| @@ -79,23 +82,22 @@ public class AlarmService extends Service { | ||||
|             // if nothing else happens, assume the alert was ignored. | ||||
|             alarmStatus = ALARM_RUNNING; | ||||
|  | ||||
|             // If dialing, active in a phone call, or on hold, don't bother with the alarm, just reset it for tomorrow | ||||
|             // Reset for tomorrow; as of API 19, setRepeating() is inexact, so we use setExact() | ||||
|             Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr); | ||||
|             // Advance the calendar to tomorrow (and make sure the calendar hasn't already been advanced) | ||||
|             if (cal.before(Calendar.getInstance())) { | ||||
|                 cal.add(Calendar.DAY_OF_MONTH, 1); | ||||
|             } | ||||
|  | ||||
|             MainActivity.setAlarm(getApplicationContext(), cal); | ||||
|             Log.d("AlarmService", "Alarm reset for next period"); | ||||
|  | ||||
|             // If dialing, active in a phone call, or on hold, don't bother with today's alarm, just reset it for tomorrow | ||||
|             TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); | ||||
|             if (telephonyManager.getCallState() != TelephonyManager.CALL_STATE_OFFHOOK) { | ||||
|  | ||||
|                 // Set a grace period alarm to send SMS | ||||
|                 Calendar graceCal = Calendar.getInstance(); | ||||
|                 graceCal.set(Calendar.SECOND, 0); | ||||
|                 graceCal.add(Calendar.MINUTE, gracePeriod); | ||||
|                 Intent graceIntent = new Intent(this, GraceReceiver.class); | ||||
|                 PendingIntent gracePendingIntent = PendingIntent.getBroadcast(this, MainActivity.GRACE_REQUEST, graceIntent, 0); | ||||
|                 alarmManager.cancel(gracePendingIntent); | ||||
|                 if (Build.VERSION.SDK_INT >= 19) { | ||||
|                     alarmManager.setExact(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent); | ||||
|                 } else { | ||||
|                     alarmManager.set(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent); | ||||
|                 } | ||||
|                 Log.d("AlarmService", "Setting grace alarm for " + MainActivity.debugDate(graceCal)); | ||||
|                 // set grace period, which sends the text message upon firing | ||||
|                 MainActivity.setGraceAlarm(getApplicationContext()); | ||||
|  | ||||
|                 // Calculate when the grace period (converted from minutes to milliseconds) ends | ||||
|                 graceEndTime = System.currentTimeMillis() + (gracePeriod * 60 * 1000); | ||||
| @@ -103,22 +105,6 @@ public class AlarmService extends Service { | ||||
|                 // Allow user to acknowledge alarm and cancel grace alarm | ||||
|                 startAlert(this); | ||||
|             } | ||||
|  | ||||
|             // Reset for tomorrow; as of API 19, setRepeating() is inexact, so we use setExact() | ||||
|             Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr); | ||||
|             // Advance the calendar to tomorrow if it's in the past | ||||
|             if (cal.before(Calendar.getInstance())) { | ||||
|                 cal.add(Calendar.DAY_OF_MONTH, 1); | ||||
|             } | ||||
|  | ||||
|             PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(this, MainActivity.ALARM_REQUEST, intent, 0); | ||||
|             alarmManager.cancel(alarmPendingIntent); | ||||
|             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("AlarmService", "Resetting alarm for " + MainActivity.debugDate(cal)); | ||||
|         } | ||||
|         return super.onStartCommand(intent, flags, startId); | ||||
|     } | ||||
| @@ -134,12 +120,13 @@ public class AlarmService extends Service { | ||||
|         // Turn off the alert activity after a period, and switch to a notification | ||||
|         new Handler().postDelayed(new Runnable() { | ||||
|             public void run() { | ||||
|                 Log.d("AlarmService", "Closing alert activity, status is " + alarmStatus); | ||||
|                 // Close the dialogue and switch to notification | ||||
|                 // if the Activity has not been closed by the user | ||||
|                 // (that is, snoozeAlert and dismissAlert have not been called) | ||||
|                 if (alarmStatus.contentEquals(ALARM_DISMISSED) || | ||||
|                         alarmStatus.contentEquals(ALARM_SNOOZED)) { | ||||
|                     return; | ||||
|                     // Do nothing | ||||
|                 // Stop if we've already run the snooze alert | ||||
|                 } else if (alarmStatus.contentEquals(ALARM_SNOOZE_RUNNING)) { | ||||
|                     alarmStatus = ALARM_IGNORED; | ||||
| @@ -156,7 +143,9 @@ public class AlarmService extends Service { | ||||
|         Log.d("AlarmService", "Stopping alert; status is " + alarmStatus); | ||||
|         if (alarmStarted) { | ||||
|             AlarmKlaxon.stop(context); | ||||
|             AlarmAlertActivity.alertActivity.finish(); | ||||
|             if (AlarmAlertActivity.alertActivity != null) { | ||||
|                 AlarmAlertActivity.alertActivity.finish(); | ||||
|             } | ||||
|             if (!alarmStatus.contentEquals(ALARM_DISMISSED)) { | ||||
|                 context.startService(notifyIntent); | ||||
|             } | ||||
| @@ -168,9 +157,7 @@ public class AlarmService extends Service { | ||||
|         alarmStatus = ALARM_DISMISSED; | ||||
|  | ||||
|         // Cancel the graceAlarm | ||||
|         Intent graceIntent = new Intent(context, GraceReceiver.class); | ||||
|         PendingIntent gracePendingIntent = PendingIntent.getBroadcast(context, MainActivity.GRACE_REQUEST, graceIntent, 0); | ||||
|         alarmManager.cancel(gracePendingIntent); | ||||
|         MainActivity.cancelGraceAlarm(context); | ||||
|  | ||||
|         // Stop this service, along with the alert and all notifications | ||||
|         context.stopService(alarmServiceIntent); | ||||
| @@ -208,6 +195,7 @@ public class AlarmService extends Service { | ||||
|         Log.d("AlarmService", "Setting alarm status to " + status); | ||||
|         alarmStatus = status; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public IBinder onBind(Intent intent) { | ||||
|         return null; | ||||
|   | ||||
| @@ -17,30 +17,25 @@ public class CancelAlarmReceiver extends BroadcastReceiver { | ||||
|     @Override | ||||
|     public void onReceive(Context context, Intent intent) { | ||||
|         SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); | ||||
|         String alarmTimeStr = sharedPref.getString(context.getString(R.string.AlarmTimePref), null); | ||||
|         String alarmTimeStr = sharedPref.getString(context.getString(R.string.AlarmTimePref), MainActivity.defaultTimeStr); | ||||
|  | ||||
|         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); | ||||
|         Intent alarmIntent = new Intent(context, AlarmReceiver.class); | ||||
|         PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(context, MainActivity.ALARM_REQUEST, alarmIntent, 0); | ||||
|         alarmManager.cancel(alarmPendingIntent); | ||||
|         Log.d("CancelAlarmReceiver", "Cancelled grace alarm"); | ||||
|         // Cancel alarm. This isn't technically necessary, as it'll happen in setAlarm | ||||
|         MainActivity.cancelAlarm(context); | ||||
|  | ||||
|         // Reset for tomorrow. setAlarm will also advance the day, but | ||||
|         // make it explicit here. | ||||
|         Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr); | ||||
|         cal.add(Calendar.DAY_OF_MONTH, 1); | ||||
|  | ||||
|         // Reset alarm for tomorrow | ||||
|  | ||||
|         // Reset for tomorrow; as of API 19, setRepeating() is inexact, so we use setExact() | ||||
|         Calendar cal = MainActivity.TimeStringToCalendar(alarmTimeStr); | ||||
|         // Set for tomorrow | ||||
|         cal.add(Calendar.DAY_OF_MONTH, 1); | ||||
|         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("CancelAlarmReceiver", "Resetting alarm for " + MainActivity.debugDate(cal)); | ||||
|         MainActivity.setAlarm(context, cal); | ||||
|  | ||||
|         // Display toast | ||||
|         Toast.makeText(context, context.getString(R.string.alarmCancelToast), Toast.LENGTH_LONG).show(); | ||||
|  | ||||
|         // Stop any snoozed/existing alarms that may have started | ||||
|         context.stopService(new Intent(context, AlarmService.class)); | ||||
|  | ||||
|         // Remove notification | ||||
|         context.stopService(new Intent(context, PreAlarmNotify.class)); | ||||
|  | ||||
|   | ||||
| @@ -11,20 +11,13 @@ import android.widget.Toast; | ||||
| public class CancelGraceReceiver extends BroadcastReceiver { | ||||
|     @Override | ||||
|     public void onReceive(Context context, Intent intent) { | ||||
|         AlarmManager graceManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); | ||||
|         Intent graceIntent = new Intent(context, GraceReceiver.class); | ||||
|         PendingIntent gracePendingIntent = PendingIntent.getBroadcast(context, MainActivity.GRACE_REQUEST, graceIntent, 0); | ||||
|         graceManager.cancel(gracePendingIntent); | ||||
|         Log.d("CancelGraceReceiver", "Cancelled grace alarm"); | ||||
|  | ||||
|         // Ensure that any snoozes that are pending never happen. | ||||
|         AlarmService.setAlarmStatus(AlarmService.ALARM_DISMISSED); | ||||
|         context.stopService(new Intent(context, AlarmService.class)); | ||||
|  | ||||
|         // Remove notification | ||||
|         context.stopService(new Intent(context, AlarmNotify.class)); | ||||
|         MainActivity.cancelGraceAlarm(context); | ||||
|  | ||||
|         // Display toast | ||||
|         Toast.makeText(context, context.getString(R.string.alarmCancelToast), Toast.LENGTH_LONG).show(); | ||||
|         Toast.makeText(context, context.getString(R.string.graceCancelToast), Toast.LENGTH_LONG).show(); | ||||
|     } | ||||
| } | ||||
| @@ -30,7 +30,7 @@ public class GraceReceiver extends BroadcastReceiver { | ||||
|     @Override | ||||
|     public void onReceive(final Context context, Intent intent) { | ||||
|         SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); | ||||
|         Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), true); | ||||
|         Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), MainActivity.defaultActive); | ||||
|         phoneNumber = sharedPref.getString(context.getString(R.string.PhoneNumberPref), null); | ||||
|         message = sharedPref.getString(context.getString(R.string.MessagePref), context.getString(R.string.defaultMessage)); | ||||
|  | ||||
| @@ -70,17 +70,23 @@ public class GraceReceiver extends BroadcastReceiver { | ||||
|                 ); | ||||
|                 locationClient.connect(); | ||||
|             } else { | ||||
|                 Log.e("GraceReceiver", "No Google Play Services. Sending text message anyway."); | ||||
|                 Log.e("GraceReceiver", "Google Play Services is not available. Sending text message anyway."); | ||||
|                 sendText(context); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     private void sendText(Context context) { | ||||
|         SmsManager sms = SmsManager.getDefault(); | ||||
|         if (!MainActivity.HYPOALARM_DEBUG) { | ||||
|             sms.sendTextMessage(phoneNumber, null, message, null, null); | ||||
|         if (phoneNumber == null || phoneNumber.isEmpty()) { | ||||
|             message = "You have not specified a phone number. No text message will be sent."; | ||||
|             Toast.makeText(context, message, Toast.LENGTH_LONG).show(); | ||||
|             Log.e("GraceReceiver", "ERROR: " + message); | ||||
|         } else { | ||||
|             if (!MainActivity.HYPOALARM_DEBUG) { | ||||
|                 sms.sendTextMessage(phoneNumber, null, message, null, null); | ||||
|             } | ||||
|             Toast.makeText(context, message, Toast.LENGTH_LONG).show(); | ||||
|             Log.d("GraceReceiver", "Sending sms to " + phoneNumber + " with message: " + message); | ||||
|         } | ||||
|         Toast.makeText(context, message, Toast.LENGTH_LONG).show(); | ||||
|         Log.d("GraceReceiver", "Sending sms to " + phoneNumber + " with message: " + message); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package za.org.treehouse.hypoalarm; | ||||
|  | ||||
| import android.app.ActivityManager; | ||||
| import android.app.AlarmManager; | ||||
| import android.app.AlertDialog; | ||||
| import android.app.Dialog; | ||||
| @@ -65,6 +66,9 @@ public class MainActivity extends ActionBarActivity { | ||||
|     public static final int CANCEL_ALARM_REQUEST = 5; | ||||
|     public static final int PHONE_NUMBER_REQUEST = 6; | ||||
|     public static final int RINGTONE_REQUEST = 7; | ||||
|     public static final String defaultTimeStr = "09:00"; | ||||
|     public static final int defaultGracePeriod = 60; | ||||
|     public static final Boolean defaultActive = true; | ||||
|  | ||||
|     public static final Boolean HYPOALARM_DEBUG = false; | ||||
|  | ||||
| @@ -98,7 +102,6 @@ public class MainActivity extends ActionBarActivity { | ||||
|             super.onStart(); | ||||
|  | ||||
|             // Set alarm time | ||||
|             final String defaultTimeStr = "09:00"; | ||||
|             String alarmTimeStr = verifyTimeString(sharedPref.getString(getString(R.string.AlarmTimePref), defaultTimeStr)); | ||||
|             final Button alarmTimeButton = (Button) getActivity().findViewById(R.id.alarm_time); | ||||
|  | ||||
| @@ -119,7 +122,7 @@ public class MainActivity extends ActionBarActivity { | ||||
|             }); | ||||
|  | ||||
|             // Allow alarm to activate | ||||
|             Boolean alarmActive = sharedPref.getBoolean(getString(R.string.AlarmActivePref), true); | ||||
|             Boolean alarmActive = sharedPref.getBoolean(getString(R.string.AlarmActivePref), defaultActive); | ||||
|             final CompoundButton alarmActiveSwitch = (CompoundButton) getActivity().findViewById(R.id.alarm_active_switch); | ||||
|             alarmActiveSwitch.setChecked(alarmActive); | ||||
|             alarmActiveSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | ||||
| @@ -130,23 +133,24 @@ public class MainActivity extends ActionBarActivity { | ||||
|                     editor.commit(); | ||||
|  | ||||
|                     if (!active) { | ||||
|                         // Stop any snoozed alerts, and cancel any alarms | ||||
|                         getActivity().stopService(new Intent(getActivity(), AlarmService.class)); | ||||
|                         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); | ||||
|                         setAlarm(getActivity(), cal); | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             // Activate the time (after setting alarmActive) when starting the app. | ||||
|             // Activate the time (after setting alarmActive) when starting the app (but don't cancel any existing grace period alarms) | ||||
|             Calendar cal = TimeStringToCalendar(alarmTimeStr); | ||||
|             resetAlarm(getActivity(), cal); | ||||
|             setAlarm(getActivity(), cal); | ||||
|  | ||||
|             // Set grace period | ||||
|             final int defaultGrace = 60; | ||||
|             int gracePeriod = sharedPref.getInt(getString(R.string.GracePeriodPref), defaultGrace); | ||||
|             int gracePeriod = sharedPref.getInt(getString(R.string.GracePeriodPref), defaultGracePeriod); | ||||
|             final Spinner gracePeriodSpinner = (Spinner) getActivity().findViewById(R.id.grace_period); | ||||
|  | ||||
|             gracePeriodSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { | ||||
| @@ -251,6 +255,14 @@ public class MainActivity extends ActionBarActivity { | ||||
|                     imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             // Set time change and boot receiver, so alarm restarts on boot | ||||
|             ComponentName bootReceiver = new ComponentName(getActivity(), AlarmChangeReceiver.class); | ||||
|             PackageManager pm = getActivity().getPackageManager(); | ||||
|             pm.setComponentEnabledSetting(bootReceiver, | ||||
|                     PackageManager.COMPONENT_ENABLED_STATE_ENABLED, | ||||
|                     PackageManager.DONT_KILL_APP); | ||||
|             Log.d("MainActivity", "Setting boot receiver"); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
| @@ -276,7 +288,13 @@ public class MainActivity extends ActionBarActivity { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void cancelAllAlarms(Context context) { | ||||
|     /** | ||||
|      * Cancel main alarm, but not grace alarm. | ||||
|      * This should be run whenever the alarm is set. | ||||
|      * | ||||
|      * @param context | ||||
|      */ | ||||
|     public static void cancelAlarm(Context context) { | ||||
|         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); | ||||
|  | ||||
|         // Cancel any current alarm | ||||
| @@ -284,30 +302,63 @@ public class MainActivity extends ActionBarActivity { | ||||
|         PendingIntent alarmPendingIntent = PendingIntent.getBroadcast(context, ALARM_REQUEST, alarmIntent, 0); | ||||
|         alarmManager.cancel(alarmPendingIntent); | ||||
|  | ||||
|         // Cancel any pre-alarm notification | ||||
|         // Cancel any pre-alarm notification that may fire | ||||
|         Intent preNotifyIntent = new Intent(context, PreAlarmReceiver.class); | ||||
|         PendingIntent preNotifyPendingIntent = PendingIntent.getBroadcast(context, PRE_NOTIFY_REQUEST, preNotifyIntent, 0); | ||||
|         alarmManager.cancel(preNotifyPendingIntent); | ||||
|  | ||||
|         // Stop any existing pre-alarm notification that has already fired | ||||
|         context.stopService(new Intent(context, PreAlarmNotify.class)); | ||||
|  | ||||
|         Log.d("MainActivity", "Alarm cancelled"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Cancel grace alarm and notifications | ||||
|      * | ||||
|      * @param context | ||||
|      */ | ||||
|     public static void cancelGraceAlarm(Context context) { | ||||
|         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); | ||||
|  | ||||
|         // 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 | ||||
|         // Stop any notification of grace period expiry | ||||
|         context.stopService(new Intent(context, AlarmNotify.class)); | ||||
|         context.stopService(new Intent(context, PreAlarmNotify.class)); | ||||
|  | ||||
|         Log.d("MainActivity", "Alarms cancelled"); | ||||
|         // Stop any active/snoozed alarms | ||||
|         context.stopService(new Intent(context, AlarmService.class)); | ||||
|  | ||||
|         Log.d("MainActivity", "Grace alarm cancelled"); | ||||
|     } | ||||
|     /** | ||||
|      * Cancels main alarm and grace alarm | ||||
|      * This should only be run when we're disabling the alarm entirely. | ||||
|      * | ||||
|      * @param context | ||||
|      */ | ||||
|     public static void cancelAllAlarms(Context context) { | ||||
|         cancelAlarm(context); | ||||
|         cancelGraceAlarm(context); | ||||
|         Log.d("MainActivity", "All alarms cancelled"); | ||||
|     } | ||||
|  | ||||
|     public static void resetAlarm(Context context, Calendar cal) { | ||||
|     /** | ||||
|      * Set the alarm. | ||||
|      * | ||||
|      * @param context  Context | ||||
|      * @param cal      Time at which to fire alarm | ||||
|      */ | ||||
|     public static void setAlarm(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); | ||||
|         Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), defaultActive); | ||||
|  | ||||
|         cancelAllAlarms(context); | ||||
|         cancelAlarm(context); | ||||
|  | ||||
|         // Advance cal to tomorrow if setting a time earlier than now | ||||
|         if (cal.before(Calendar.getInstance())) { | ||||
| @@ -318,7 +369,6 @@ public class MainActivity extends ActionBarActivity { | ||||
|             // 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 | ||||
| @@ -329,9 +379,9 @@ public class MainActivity extends ActionBarActivity { | ||||
|             } | ||||
|             Log.d("MainActivity", "Setting alarm for " + MainActivity.debugDate(cal)); | ||||
|  | ||||
|             // Set an alarm for the pre-alarm notification, half an hour before the alarm | ||||
|             // Set an alarm for the pre-alarm notification, an hour before the alarm | ||||
|             Calendar preNotifyCal = (Calendar) cal.clone(); | ||||
|             preNotifyCal.add(Calendar.MINUTE, -30); | ||||
|             preNotifyCal.add(Calendar.MINUTE, -60); | ||||
|             Intent preNotifyIntent = new Intent(context, PreAlarmReceiver.class); | ||||
|             preNotifyPendingIntent = PendingIntent.getBroadcast(context, PRE_NOTIFY_REQUEST, preNotifyIntent, 0); | ||||
|             // Set or reset alarm | ||||
| @@ -342,14 +392,35 @@ public class MainActivity extends ActionBarActivity { | ||||
|             } | ||||
|             Log.d("MainActivity", "Setting pre-alarm for " + MainActivity.debugDate(preNotifyCal)); | ||||
|  | ||||
|             // Set time change and boot receiver, so alarm restarts on boot | ||||
|             ComponentName bootReceiver = new ComponentName(context, AlarmChangeReceiver.class); | ||||
|             PackageManager pm = context.getPackageManager(); | ||||
|             pm.setComponentEnabledSetting(bootReceiver, | ||||
|                     PackageManager.COMPONENT_ENABLED_STATE_ENABLED, | ||||
|                     PackageManager.DONT_KILL_APP); | ||||
|             Log.d("MainActivity", "Setting boot receiver"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set the grace alarm, to fire at the end of the grace period and send a text message. | ||||
|      * | ||||
|      * @param context | ||||
|      */ | ||||
|     public static void setGraceAlarm(Context context) { | ||||
|         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); | ||||
|         SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); | ||||
|         Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), defaultActive); | ||||
|         int gracePeriod = sharedPref.getInt(context.getString(R.string.GracePeriodPref), MainActivity.defaultGracePeriod); | ||||
|  | ||||
|         cancelGraceAlarm(context); | ||||
|  | ||||
|         if (alarmActive) { | ||||
|             // Set a grace period alarm to send SMS | ||||
|             Calendar graceCal = Calendar.getInstance(); | ||||
|             graceCal.set(Calendar.SECOND, 0); | ||||
|             graceCal.add(Calendar.MINUTE, gracePeriod); | ||||
|             Intent graceIntent = new Intent(context, GraceReceiver.class); | ||||
|             PendingIntent gracePendingIntent = PendingIntent.getBroadcast(context, MainActivity.GRACE_REQUEST, graceIntent, 0); | ||||
|             if (Build.VERSION.SDK_INT >= 19) { | ||||
|                 alarmManager.setExact(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent); | ||||
|             } else { | ||||
|                 alarmManager.set(AlarmManager.RTC_WAKEUP, graceCal.getTimeInMillis(), gracePendingIntent); | ||||
|             } | ||||
|             Log.d("MainActivity", "Setting grace alarm for " + MainActivity.debugDate(graceCal)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -388,8 +459,10 @@ public class MainActivity extends ActionBarActivity { | ||||
|             Button alarm_time = (Button) getActivity().findViewById(R.id.alarm_time); | ||||
|             alarm_time.setText(alarmStr); | ||||
|  | ||||
|             // Cancel any snoozed alerts | ||||
|             getActivity().stopService(new Intent(getActivity(), AlarmService.class)); | ||||
|             // Set actual alarm | ||||
|             resetAlarm(getActivity(), cal); | ||||
|             setAlarm(getActivity(), cal); | ||||
|  | ||||
|             // Display toast | ||||
|             CharSequence text = getString(R.string.alarmSetToast) + " " + CalendarToTimeString(cal); | ||||
| @@ -562,6 +635,15 @@ public class MainActivity extends ActionBarActivity { | ||||
|         return remMinutes + minStr; | ||||
|     } | ||||
|  | ||||
|     // TODO remove this function? | ||||
|     public static Calendar minutesAgo(int minutes) { | ||||
|         // Negate number to get minutes in the past. | ||||
|         minutes = minutes * -1; | ||||
|         Calendar cal = Calendar.getInstance(); | ||||
|         cal.add(Calendar.MINUTE, minutes); | ||||
|         return cal; | ||||
|     } | ||||
|  | ||||
|     public static String debugDate(Calendar cal) { | ||||
|         SimpleDateFormat print = new SimpleDateFormat("dd-MM-yyyy HH:mm:ssZ"); | ||||
|         return print.format(cal.getTime()); | ||||
|   | ||||
| @@ -40,7 +40,7 @@ public class PreAlarmNotify extends Service { | ||||
|         Log.d("PreAlarmNotify", "Pre-notification started."); | ||||
|  | ||||
|         // Get alarm time, and convert it into something readable. | ||||
|         String alarmTimeStr = sharedPref.getString(getString(R.string.AlarmTimePref), null); | ||||
|         String alarmTimeStr = sharedPref.getString(getString(R.string.AlarmTimePref), MainActivity.defaultTimeStr); | ||||
|         Calendar alarmCal = MainActivity.TimeStringToCalendar(alarmTimeStr); | ||||
|         alarmTimeStr = MainActivity.formattedTime(getApplicationContext(), alarmCal); | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,7 @@ public class PreAlarmReceiver extends BroadcastReceiver { | ||||
|     @Override | ||||
|     public void onReceive(final Context context, Intent intent) { | ||||
|         SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); | ||||
|         Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), true); | ||||
|         Boolean alarmActive = sharedPref.getBoolean(context.getString(R.string.AlarmActivePref), MainActivity.defaultActive); | ||||
|  | ||||
|         if (alarmActive) { | ||||
|             // Create notification | ||||
|   | ||||
| @@ -53,7 +53,9 @@ | ||||
|  | ||||
|     <string name="alarmSetToast">HypoAlarm set to </string> | ||||
|  | ||||
|     <string name="alarmCancelToast">HypoAlarm text message cancelled</string> | ||||
|     <string name="alarmCancelToast">HypoAlarm cancelled</string> | ||||
|  | ||||
|     <string name="graceCancelToast">HypoAlarm text message cancelled</string> | ||||
|  | ||||
|     <string name="defaultMessage">Hi, I haven\'t responded to my alarm today. Please contact me to make sure I\'m awake.</string> | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user