Skip to content
This repository has been archived by the owner on Jan 10, 2024. It is now read-only.

Favorite Dish Notifications

Kordian Bruck edited this page Aug 9, 2017 · 1 revision

Introduction

A common situation known to every student is to be completely under/overwhelmed by the options of where to eat. Often this leads to blindly walking towards the food trucks outside of the campus, even though they often serve at higher prices. One way to solve this issue, lies in letting the app's user mark food as his/her favorite dish and sending notifications whenever this specific dish is served.

Alarms and Notifications

For making sure that an action gets repeated after a certain time interval, android Alarms were used. They provide a conveniant way of scheduling an action in the future. This allows us to fire a notification after a given period of time. The only open question remains: How to determine whether the app needs to trigger a notification or not?

Local Database and Synchronisation

The TCA app offers two local SQLite databases:

  • cafeterias_menus - holding the information about all served dishes in all cafeterias for the next two weeks
  • favorite_dishes - containing all the information about the user's favorite dishes, including where it was served

Both of them are accessed via a CafeteriaMenuManager object. Additionally it takes care of synchronising the cafeterias_menus database, at the very least every TIME_TO_SYNC seconds. Currently this value is set to an interval of one day. This means, every day there's sufficient data for constructing notifications for the next two weeks. This also means, that by adding the rescheduling to the daily synchronisation, automatic rescheduling can be achieved.

Previous State

In the previous state, an alarm was only scheduled after a user set a favorite food by clicking its star icon in the cafeteria activity. This led to the issue that reoccuring favorite dishes don't trigger notifications, if they are served more than two weeks in the future.

Current State

To solve that issue, it was necessary to keep track of the currently scheduled alarms. This way it is possible to prevent unnecessary rescheduling. Each of the alarms is set to the next serving date of an upcoming serving of a given dish. This allows the alarm to query the local database "cafeteria_menus" for the current day, to receive a complete overview about all the favorite dishes served. It is then possible to construct a notification with the help of the Notification Builder and the TCA's default notification channel. By using the data acquired by the previous query, it is then possible to fill the notification.

FavoriteDishAlarmScheduler

This class is responsible for setting alarms via the Android-SDK's Alarm Manager and responds to its own broadcast events, triggered by the activation of an alarm scheduled in the past.

FavoriteFoodAlarmStorage

The FavoriteFoodAlarmStorage is responsible for instantiating the FavoriteDishAlarmManager and provides methods to schedule on it. Whenever an alarm is to be scheduled (by calling the scheduleAlarm method), it first checks if there's actually a necessity to do so. This is done by steadily keeping all the currently scheduled dates in the sharedPreferences. By using the method cancelAlarm, it is also possible to remove a date from the sharedPreferences and to unschedule it on the AlarmManager. This method should therefore be called whenever there is no favorite dish left for a date, where there was a previous alarm scheduled for. This could happen when a user decides that a food is no longer a favorite. The alarm would still be set and it's possible that the constructed notification doesn't find any favorite dishes served at its triggering date anymore.

getServedFavoritesAtDate (dayMonthYear)

This method is implemented in the CafeteriaManager, and uses an innerjoin to determine the intersection of favorite food (from favorite_dishes) and its serving information (from cafeterias_menus) at the given date: "dayMonthYear". This way it is possible to construct a Hashmap with key-value pairs consisting of: MensaId(Key) and all corresponding (favorite) CafeteriaMenus accumulated in a HashSet (Value). This method is used by the FavoriteDishAlarmScheduler, which is responsible for both setting a FavoriteFoodAlarm as well as receiving the linked broadcast.

scheduleFoodAlarms

The actual scheduling occurs whenever there is a call to downloadFromExternal. By appending a call to scheduleFoodAlarms into the method's body, each synchronisation automatically triggers a full run of scheduling notifications. scheduleFoodAlarms is then able to do a complete rebuild of the scheduled alarms and does so for all the currently downloaded cafeterias_menus, which are set as a user's favorite food. Additionally this method gets called after toggling the favorite status of a food.

Additional Work

Since the only requirement was to add automatic rescheduling of alarms, the grouping of notifications as well as the additional CafeteriaNotificationSettingsActivity can be considered an extra, allowing the user to decide over his/hers preferred notification time. By clicking the "Save" - button, the user's notification time preference is stored to the shared preferences. This is done by instantiating an object of CafeteriaNotificationSettings. This object stores the preferred hour-minute tuple to the SharedPreferences for each workday (monday to friday). Its method saveWholeSchedule takes an arraylist as parameter consisting of Android SDK Pairs<Integer, Integer>, which contain the hour and the minute set by the user. The list's indices range from 0 (monday) to 4 (friday). This method is then called whenever the user clicks the "Save" button, sending the complete preferred schedule. It should be mentioned that this often leads to the rescheduling of all alarms. In case the user didn't actually change any preferred time, no rescheduling happens. The notifications and their settings can be seen here:

Clone this wiki locally