diff --git a/app/build.gradle b/app/build.gradle index 9dfab4cb..cd5c2ece 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "projects.medicationtracker" minSdkVersion 26 targetSdkVersion 33 - versionCode 2 - versionName "0.7.12" + versionCode 3 + versionName "0.7.13" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/projects/medicationtracker/Fragments/MedicationScheduleFragment.java b/app/src/main/java/projects/medicationtracker/Fragments/MedicationScheduleFragment.java index 76c85bde..38aa633e 100644 --- a/app/src/main/java/projects/medicationtracker/Fragments/MedicationScheduleFragment.java +++ b/app/src/main/java/projects/medicationtracker/Fragments/MedicationScheduleFragment.java @@ -239,8 +239,6 @@ private void sortMedicationCheckBoxes(LinearLayoutCompat parentLayout) CheckBox child1 = (CheckBox) parentLayout.getChildAt(j); CheckBox child2 = (CheckBox) parentLayout.getChildAt(j + 1); - System.out.println(child1.getText().toString()); - Pair child1Pair = (Pair) child1.getTag(); Pair child2Pair = (Pair) child2.getTag(); @@ -252,12 +250,15 @@ private void sortMedicationCheckBoxes(LinearLayoutCompat parentLayout) CheckBox temp = new CheckBox(parentLayout.getContext()); temp.setText(child1.getText()); temp.setTag(child1.getTag()); + temp.setChecked(child1.isChecked()); child1.setText(child2.getText()); child1.setTag(child2.getTag()); + child1.setChecked(child2.isChecked()); child2.setText(temp.getText()); child2.setTag(temp.getTag()); + child2.setChecked(temp.isChecked()); } } } diff --git a/app/src/main/java/projects/medicationtracker/Helpers/DBHelper.java b/app/src/main/java/projects/medicationtracker/Helpers/DBHelper.java index d678f663..f99ef313 100644 --- a/app/src/main/java/projects/medicationtracker/Helpers/DBHelper.java +++ b/app/src/main/java/projects/medicationtracker/Helpers/DBHelper.java @@ -578,7 +578,7 @@ public boolean isInMedicationTracker(Medication medication, LocalDateTime time) String dateTime = TimeFormatting.localDateTimeToString(time); String query = "SELECT * FROM " + MEDICATION_TRACKER_TABLE + " WHERE " + MED_ID + " = " + - medication.getMedId() + " AND " + DOSE_TIME + " = \"" + dateTime + "\""; + medication.getMedId() + " AND " + DOSE_TIME + " = ''" + dateTime + "'"; int count = 0; diff --git a/app/src/main/java/projects/medicationtracker/Helpers/NotificationHelper.java b/app/src/main/java/projects/medicationtracker/Helpers/NotificationHelper.java index 7953ef0a..3c0c09ad 100644 --- a/app/src/main/java/projects/medicationtracker/Helpers/NotificationHelper.java +++ b/app/src/main/java/projects/medicationtracker/Helpers/NotificationHelper.java @@ -3,7 +3,6 @@ import static android.content.Context.ALARM_SERVICE; import static android.os.Build.VERSION.SDK_INT; -import android.annotation.SuppressLint; import android.app.AlarmManager; import android.app.NotificationChannel; import android.app.NotificationManager; @@ -35,12 +34,11 @@ public class NotificationHelper * @param time Time the notification will be set. * @param notificationId ID for the PendingIntent that stores data for the notification. */ - @SuppressLint("UnspecifiedImmutableFlag") public static void scheduleNotification(Context notificationContext, Medication medication, LocalDateTime time, long notificationId) { // Loops to increase time, prevents notification bombardment when editing time. - while (time.isBefore(LocalDateTime.now().minusSeconds(1))) + while (time.isBefore(LocalDateTime.now())) { time = time.plusMinutes(medication.getMedFrequency()); } @@ -58,9 +56,47 @@ public static void scheduleNotification(Context notificationContext, Medication notificationIntent.putExtra(DOSE_TIME, time); notificationIntent.putExtra(MEDICATION_ID, medication.getMedId()); - alarmIntent = PendingIntent.getBroadcast(notificationContext, (int) notificationId, + alarmIntent = PendingIntent.getBroadcast( + notificationContext, + (int) notificationId, notificationIntent, - SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT + SDK_INT >= Build.VERSION_CODES.S ? + PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT + ); + + alarmManager = (AlarmManager) notificationContext.getSystemService(ALARM_SERVICE); + alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTimeMillis, alarmIntent); + } + + /** + * Sets an alarm to create a notification in 15 minutes. + * @param notificationContext Context for the alarm. + * @param medication Medication form which the user will be notified. + * @param time Time the notification will be set. + * @param notificationId ID for the PendingIntent that stores data for the notification. + */ + public static void scheduleIn15Minutes(Context notificationContext, Medication medication, + LocalDateTime time, long notificationId) + { + PendingIntent alarmIntent; + AlarmManager alarmManager; + + ZonedDateTime zdt = LocalDateTime.now().plusMinutes(1).atZone(ZoneId.systemDefault()); + long alarmTimeMillis = zdt.toInstant().toEpochMilli(); + + Intent notificationIntent = new Intent(notificationContext, NotificationReceiver.class); + + notificationIntent.putExtra(NOTIFICATION_ID, notificationId); + notificationIntent.putExtra(MESSAGE, createMedicationReminderMessage(medication)); + notificationIntent.putExtra(DOSE_TIME, time); + notificationIntent.putExtra(MEDICATION_ID, medication.getMedId()); + + alarmIntent = PendingIntent.getBroadcast( + notificationContext, + (int) notificationId, + notificationIntent, + SDK_INT >= Build.VERSION_CODES.S ? + PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT ); alarmManager = (AlarmManager) notificationContext.getSystemService(ALARM_SERVICE); @@ -114,7 +150,6 @@ public static void createNotificationChannel(Context context) * @param notificationId ID of the notification to be deleted * @param context Pending intent's context */ - @SuppressLint("UnspecifiedImmutableFlag") public static void deletePendingNotification(long notificationId, Context context) { Intent intent = new Intent(context, NotificationReceiver.class); diff --git a/app/src/main/java/projects/medicationtracker/Receivers/EventReceiver.java b/app/src/main/java/projects/medicationtracker/Receivers/EventReceiver.java index 79d22d2b..1c1435dd 100644 --- a/app/src/main/java/projects/medicationtracker/Receivers/EventReceiver.java +++ b/app/src/main/java/projects/medicationtracker/Receivers/EventReceiver.java @@ -2,6 +2,7 @@ import static projects.medicationtracker.Helpers.NotificationHelper.MEDICATION_ID; import static projects.medicationtracker.Helpers.NotificationHelper.NOTIFICATION_ID; +import static projects.medicationtracker.Services.NotificationService.SNOOZE_ACTION; import android.app.NotificationManager; import android.content.BroadcastReceiver; @@ -36,7 +37,22 @@ public void onReceive(Context context, Intent intent) context, intent.getLongExtra(NOTIFICATION_ID + medId, 0), intent.getLongExtra(MEDICATION_ID + medId, 0), - intent.getStringExtra(NotificationHelper.DOSE_TIME + medId) + intent.getStringExtra(NotificationHelper.DOSE_TIME + medId), + db + ); + + return; + } + else if (intent.getAction().contains(SNOOZE_ACTION)) + { + String medId = "_" + intent.getAction().split("_")[1]; + + snoozeFor15( + context, + intent.getLongExtra(NOTIFICATION_ID + medId, 0), + intent.getLongExtra(MEDICATION_ID + medId, 0), + intent.getStringExtra(NotificationHelper.DOSE_TIME + medId), + db ); return; @@ -46,6 +62,8 @@ public void onReceive(Context context, Intent intent) { prepareNotification(context, db, medication); } + + db.close(); } /** @@ -73,9 +91,17 @@ private void prepareNotification(Context context, DBHelper db, Medication medica } } - private void markDoseTaken(Context context, long notificationId, long medId, String doseTimeString) + /** + * Marks a dose as taken from the notification + * @param context Application context + * @param notificationId Id of notification to cancel + * @param medId ID of medication taken + * @param doseTimeString Dose time for DB. + */ + private void markDoseTaken( + Context context, long notificationId, long medId, String doseTimeString, DBHelper db + ) { - DBHelper db = new DBHelper(context); Medication med; LocalDateTime doseTime = LocalDateTime.parse(doseTimeString); NotificationManager notificationManager = @@ -92,6 +118,8 @@ private void markDoseTaken(Context context, long notificationId, long medId, Str med = db.getMedication(medId); + System.out.println(med.getMedName()); + long doseId = db.isInMedicationTracker(med, doseTime) ? db.getDoseId(med.getMedId(), TimeFormatting.localDateTimeToString(doseTime)) : db.addToMedicationTracker(med, doseTime); @@ -101,5 +129,37 @@ private void markDoseTaken(Context context, long notificationId, long medId, Str ); notificationManager.cancel((int) notificationId); + db.close(); + } + + private void snoozeFor15( + Context context, long notificationId, long medId, String doseTimeString, DBHelper db + ) + { + Medication med; + LocalDateTime doseTime = LocalDateTime.parse(doseTimeString); + NotificationManager notificationManager = + (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + + if (notificationId == 0 || medId == 0) + { + Toast.makeText( + context, "Medication could not be determined", Toast.LENGTH_LONG + ).show(); + + return; + } + + med = db.getMedication(medId); + + NotificationHelper.scheduleIn15Minutes( + context, + med, + doseTime, + notificationId + ); + + notificationManager.cancel((int) notificationId); + db.close(); } } diff --git a/app/src/main/java/projects/medicationtracker/Receivers/NotificationReceiver.java b/app/src/main/java/projects/medicationtracker/Receivers/NotificationReceiver.java index bd57317f..f21d9821 100644 --- a/app/src/main/java/projects/medicationtracker/Receivers/NotificationReceiver.java +++ b/app/src/main/java/projects/medicationtracker/Receivers/NotificationReceiver.java @@ -51,5 +51,7 @@ public void onReceive(Context context, Intent intent) // Fire notification if enabled if (db.getNotificationEnabled()) context.startService(service); + + db.close(); } } diff --git a/app/src/main/java/projects/medicationtracker/Services/NotificationService.java b/app/src/main/java/projects/medicationtracker/Services/NotificationService.java index 0f88fa19..934347e4 100644 --- a/app/src/main/java/projects/medicationtracker/Services/NotificationService.java +++ b/app/src/main/java/projects/medicationtracker/Services/NotificationService.java @@ -26,6 +26,7 @@ public class NotificationService extends IntentService { public static String MARK_AS_TAKEN_ACTION = "markAsTaken"; + public static String SNOOZE_ACTION = "snooze15"; public NotificationService() { @@ -62,6 +63,7 @@ private Notification createNotification( String message, String doseTime, long notificationId, long medId) { Intent markTakenIntent = new Intent(this.getApplicationContext(), EventReceiver.class); + Intent snoozeIntent = new Intent(this.getApplicationContext(), EventReceiver.class); String embeddedMedId = "_" + medId; markTakenIntent.setAction(MARK_AS_TAKEN_ACTION + embeddedMedId); @@ -69,6 +71,11 @@ private Notification createNotification( markTakenIntent.putExtra(NOTIFICATION_ID + embeddedMedId, notificationId); markTakenIntent.putExtra(DOSE_TIME + embeddedMedId, doseTime); + snoozeIntent.setAction(SNOOZE_ACTION + embeddedMedId); + snoozeIntent.putExtra(MEDICATION_ID + embeddedMedId, medId); + snoozeIntent.putExtra(NOTIFICATION_ID + embeddedMedId, notificationId); + snoozeIntent.putExtra(DOSE_TIME + embeddedMedId, doseTime); + PendingIntent markAsTakenPendingIntent = PendingIntent.getBroadcast( this.getApplicationContext(), @@ -78,6 +85,15 @@ private Notification createNotification( PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT ); + PendingIntent snoozePendingIntent = + PendingIntent.getBroadcast( + getApplicationContext(), + 0, + snoozeIntent, + SDK_INT >= Build.VERSION_CODES.S ? + PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT + ); + NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle(getString(R.string.app_name)) @@ -87,9 +103,14 @@ private Notification createNotification( .setGroup(GROUP_KEY) .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL) .addAction( - R.drawable.mt_icon, + 0, getString(R.string.mark_as_taken), markAsTakenPendingIntent + ) + .addAction( + 0, + getString(R.string.snooze_message), + snoozePendingIntent ); Intent resIntent = @@ -102,7 +123,8 @@ private Notification createNotification( PendingIntent resPendingIntent = stackBuilder.getPendingIntent( 0, - SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT + SDK_INT >= Build.VERSION_CODES.S ? + PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT ); builder.setContentIntent(resPendingIntent); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bc68c772..4a04086c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -170,6 +170,7 @@ Taken at Unit of Time Mark as taken + Remind me in 15 minutes Options License MediTrak is a free and open source (FOSS) application designed to help you keep track of your medications, so you can more easily answer the question \"did I take my medication yesterday?\"