From ba225285e884511fe64e510b7f5d7669b28a6b7c Mon Sep 17 00:00:00 2001 From: Keith Holliday Date: Sun, 29 May 2016 17:13:58 -0500 Subject: [PATCH 01/14] Added notifications for todos --- Habitica/AndroidManifest.xml | 8 + .../receivers/TaskAlarmBootReceiver.java | 22 ++ .../habitica/receivers/TodoReceiver.java | 56 +++++ .../ui/activities/TaskFormActivity.java | 8 + .../habitica/ui/helpers/TaskAlarmManager.java | 224 ++++++++++++++++++ 5 files changed, 318 insertions(+) create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/receivers/TaskAlarmBootReceiver.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/receivers/TodoReceiver.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/TaskAlarmManager.java diff --git a/Habitica/AndroidManifest.xml b/Habitica/AndroidManifest.xml index 734f1b000..0f0b9910b 100644 --- a/Habitica/AndroidManifest.xml +++ b/Habitica/AndroidManifest.xml @@ -17,6 +17,7 @@ + + + + + + + + tagCheckBoxList; + private TaskAlarmManager taskAlarmManager; + @BindView(R.id.task_value_edittext) EditText taskValue; @@ -215,6 +221,8 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem return; } + taskAlarmManager = TaskAlarmManager.getInstance(this); + dueDateListener = new DateEditTextListener(dueDatePickerText); startDateListener = new DateEditTextListener(startDatePickerText); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/TaskAlarmManager.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/TaskAlarmManager.java new file mode 100644 index 000000000..6b8c2ed7d --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/TaskAlarmManager.java @@ -0,0 +1,224 @@ +package com.habitrpg.android.habitica.ui.helpers; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; + +import com.google.gson.Gson; +import com.habitrpg.android.habitica.events.TaskCreatedEvent; +import com.habitrpg.android.habitica.events.TaskUpdatedEvent; +import com.habitrpg.android.habitica.receivers.TodoReceiver; +import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task; + + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.json.JSONObject; + +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by keithholliday on 5/29/16. + */ +public class TaskAlarmManager { + private static TaskAlarmManager instance = null; + + private Context context; + private Map savedAlarms; + + public static final String TASK_ALARMS_PREFERENCE_KEY = "TaskAlarms"; + public static final String TASK_ALARMS_KEY = "task_alarms"; + public static final String TASK_ID_INTENT_KEY = "TASK_ID"; + public static final String TASK_NAME_INTENT_KEY = "TASK_NAME"; + + private class TaskAlarm { + private String taskId; + private int alarmId; + private String taskText; + private Date taskDueDate; + + public TaskAlarm(String taskId, int alarmId) { + this.taskId = taskId; + this.alarmId = alarmId; + } + + public void setTaskId (String taskId) { + this.taskId = taskId; + } + + public String getTaskId () { + return this.taskId; + } + + public void setTaskText (String taskText) { + this.taskText = taskText; + } + + public String getTaskText () { + return this.taskText; + } + + public void setTaskDueDate (Date taskDueDate) { + this.taskDueDate = taskDueDate; + } + + public Date getTaskDueDate () { + return this.taskDueDate; + } + + public void setAlarmId (int alarmId) { + this.alarmId = alarmId; + } + + public int getAlarmId () { + return this.alarmId; + } + + public String toStirng() { + Gson gson = new Gson(); + String json = gson.toJson(this); + return json; + } + } + + private TaskAlarmManager(Context context) { + this.context = context; + this.savedAlarms = this.loadAlarmsFromPreferences(); + this.savedAlarms = new HashMap(); + this.saveAlarmsToPreferences(this.savedAlarms); + EventBus.getDefault().register(this); + } + + public static TaskAlarmManager getInstance(Context context){ + if(instance == null) + { + instance = new TaskAlarmManager(context); + } + return instance; + } + + @Subscribe + public void onEvent(TaskCreatedEvent evnt) { + Task task = (Task) evnt.task; + Calendar cal = Calendar.getInstance(); + cal.setTime(task.getDueDate()); + + this.addAlarmForTask(task, cal); + } + + @Subscribe + public void onEvent(TaskUpdatedEvent evnt) { + Task task = (Task) evnt.task; + Calendar cal = Calendar.getInstance(); + cal.setTime(task.getDueDate()); + + this.addAlarmForTask(task, cal); + } + + public void addAlarmForTask(Task task, Calendar cal) { + if (task.getType().equals("todo")) { + this.addAlarmForTodo(task, cal); + } + } + + public void removeAlarmForTask(String taskId) { + String taskAlarmJson = this.savedAlarms.get(taskId); + if (taskAlarmJson != null) { + this.savedAlarms.remove(taskId); + this.saveAlarmsToPreferences(this.savedAlarms); + } + } + + private void addAlarmForTodo(Task task, Calendar cal) { + cal.add(Calendar.SECOND, 60); + Intent intent = new Intent(context, TodoReceiver.class); + intent.putExtra(TASK_NAME_INTENT_KEY, task.getText()); + intent.putExtra(TASK_ID_INTENT_KEY, task.getId()); + + String taskAlarmJson = this.savedAlarms.get(task.getId()); + + int _id; + if (taskAlarmJson == null) { + _id = (int) System.currentTimeMillis(); + TaskAlarm taskAlarm = new TaskAlarm(task.getId(), _id); + taskAlarm.setTaskText((task.getText())); + taskAlarm.setTaskDueDate(task.getDueDate()); + this.savedAlarms.put(task.getId(), taskAlarm.toStirng()); + } else { + Gson gson = new Gson(); + TaskAlarm taskAlarm = gson.fromJson(taskAlarmJson, TaskAlarm.class); + taskAlarm.setTaskDueDate(task.getDueDate()); + _id = taskAlarm.getAlarmId(); + } + + PendingIntent sender = PendingIntent.getBroadcast(context, _id, intent, PendingIntent.FLAG_UPDATE_CURRENT); + + AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender); + + this.saveAlarmsToPreferences(this.savedAlarms); + } + + public void scheduleAllSavedAlarms() { + Iterator it = this.savedAlarms.entrySet().iterator(); + Gson gson = new Gson(); + Calendar cal = Calendar.getInstance(); + + while (it.hasNext()) { + Map.Entry pair = (Map.Entry) it.next(); + + TaskAlarm taskAlarm = gson.fromJson(pair.getValue().toString(), TaskAlarm.class); + int _id = taskAlarm.getAlarmId(); + + Intent intent = new Intent(context, TodoReceiver.class); + intent.putExtra(TASK_NAME_INTENT_KEY, taskAlarm.getTaskText()); + intent.putExtra(TASK_ID_INTENT_KEY, taskAlarm.getTaskId()); + + PendingIntent sender = PendingIntent.getBroadcast(context, _id, intent, PendingIntent.FLAG_UPDATE_CURRENT); + + AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + cal.setTime(taskAlarm.getTaskDueDate()); + am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender); + + it.remove(); // avoids a ConcurrentModificationException + } + } + + private void saveAlarmsToPreferences(Map inputMap) { + SharedPreferences pSharedPref = context.getApplicationContext().getSharedPreferences(TASK_ALARMS_PREFERENCE_KEY, Context.MODE_PRIVATE); + if (pSharedPref != null){ + JSONObject jsonObject = new JSONObject(inputMap); + String jsonString = jsonObject.toString(); + SharedPreferences.Editor editor = pSharedPref.edit(); + editor.remove(TASK_ALARMS_KEY).commit(); + editor.putString(TASK_ALARMS_KEY, jsonString); + editor.commit(); + } + } + + private Map loadAlarmsFromPreferences() { + Map outputMap = new HashMap(); + SharedPreferences pSharedPref = context.getApplicationContext().getSharedPreferences(TASK_ALARMS_PREFERENCE_KEY, Context.MODE_PRIVATE); + try{ + if (pSharedPref != null){ + String jsonString = pSharedPref.getString(TASK_ALARMS_KEY, (new JSONObject()).toString()); + JSONObject jsonObject = new JSONObject(jsonString); + Iterator keysItr = jsonObject.keys(); + while(keysItr.hasNext()) { + String key = keysItr.next(); + String value = (String) jsonObject.get(key); + outputMap.put(key, value); + } + } + }catch(Exception e){ + e.printStackTrace(); + } + return outputMap; + } +} From c74296c38d3f83ab5630833511c2df5de257a120 Mon Sep 17 00:00:00 2001 From: Keith Holliday Date: Thu, 2 Jun 2016 14:17:10 -0500 Subject: [PATCH 02/14] Added task reminders interface and model --- Habitica/res/layout/activity_task_form.xml | 44 ++++++ Habitica/res/layout/reminder_item.xml | 20 +++ Habitica/res/values/strings.xml | 1 + .../android/habitica/HabitDatabase.java | 2 +- .../ui/activities/TaskFormActivity.java | 81 +++++++++++ .../ui/adapter/tasks/RemindersAdapter.java | 129 ++++++++++++++++++ .../habitica/ui/helpers/TaskAlarmManager.java | 27 ++-- .../lib/models/tasks/RemindersItem.java | 81 +++++++++++ .../lib/models/tasks/Task.java | 40 ++++++ 9 files changed, 415 insertions(+), 10 deletions(-) create mode 100644 Habitica/res/layout/reminder_item.xml create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RemindersAdapter.java create mode 100644 Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/tasks/RemindersItem.java diff --git a/Habitica/res/layout/activity_task_form.xml b/Habitica/res/layout/activity_task_form.xml index d96b87ac6..f92d2ed2d 100644 --- a/Habitica/res/layout/activity_task_form.xml +++ b/Habitica/res/layout/activity_task_form.xml @@ -344,6 +344,50 @@ + + + + + + + + + + +