Skip to content

ericli3690/gsoc-ankidroid-report

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 

Repository files navigation

GSoC Logo AnkiDroid Logo

Google Summer of Code (GSoC) 2025
AnkiDroid
Review Reminders
Song "Eric" Yu Li (ericli3690)
 

Click here to jump to the project!

Table of Contents 📃

About Me 🙂

Hi, I'm Eric! As of writing, I'm a Computer Science student at the University of Waterloo in Canada. Feel free to reach out!

Website | LinkedIn | GitHub

My Mentors 🙏

Thanks to my mentors for guiding me, reviewing my code, and being super supportive for the entire summer!

Extra shoutout to the other maintainers of AnkiDroid, too. Even though they weren't formally my mentors, they also helped guide and support me, and for that I am eternally grateful.

About GSoC ☀️ and AnkiDroid ⭐

Learn more about GSoC here.

See AnkiDroid on GitHub!

You may have heard of Anki, one of the most popular spaced-repetition flashcards apps in the world. AnkiDroid is the official open-source Android mobile port of Anki, with over ten million downloads on Google Play. I personally have been using Anki and AnkiDroid for years to study for school, learn Chinese characters, etc.

Project Goals 🎯

See my original project proposal document.

For my GSoC project, I proposed adding review reminders to AnkiDroid, as the current notifications system is completely broken and has been for multiple years.

"Notifications have been broken for 5/6 years and are one of the most common complaints about our app on Google Play [...] They're one of our few issues which have a dedicated label"

~ David Allison, one of AnkiDroid's principal maintainers

Quoting from my proposal (with emojis added to indicate which features I completed):

In summary, my key goals are as follows:

  1. Be able to create deck-specific reminders which fire once per day ✅
  2. Be able to view reminders in a specific deck ✅
  3. Be able to view reminders app-wide on a single screen ✅
  4. Be able to receive notifications in a timely manner ✅
  5. Be able to edit the time a reminder is sent at ✅
  6. Be able to delete reminders ✅
  7. Be able to ask the user for notification permissions ✅
  8. Be able to create global, app-wide notifications ✅

If possible, I also plan to implement the following:

  1. Be able to view previews of cards in notifications ❎ (not met because, after a maintainer debate, we decided it was better off as an add-on feature rather than one that should be included in the vanilla app)
  2. Be able to create persistent notifications that have a defined start and end ✅ (met in a different way than originally planned: we decided creating two types of review reminders (single and persistent) was too confusing. Instead, I added two simple snooze buttons to the review reminder notifications)
  3. Be able to modify special options for notifications, such as including subdecks when counting cards for the card trigger threshold ✅ (this specific advanced option was removed for adding unnecessary complexity, but other advanced options were implemented)

For more details about how my project changed from the initial proposal, see Plan Changes.

Project Results ✨

GIFs

Here's a demonstration of how the new review reminders feature allows you to schedule, view, edit, and delete review reminders:


Deleting a deck also deletes the corresponding review reminders:

Images

When you receive reminder notifications, they look like this:

Review reminder notifications


Clicking snooze dismisses the notification and causes it to come back after the selected time interval. Clicking on the notification opens the corresponding deck and allows you to begin reviewing.

Here are some images of the main UI screens:

UI screens for the review reminder feature


I also created dialogs and screens for explaining to the user why AnkiDroid needs the notification permission:

UI screens explaining why AnkiDroid needs notification permissions


There are multiple ways to access the review reminders screen to ensure new users don't get stuck looking for it:

Bell icon entry point for the review reminders screen

New settings button for accessing the review reminders screen


I also added a few advanced review reminder configuration settings:

Review reminder advanced settings
  1. Count new cards / cards in learning / cards in review: For example, if a user only wants to get notifications when they have a lot of cards to review, but otherwise does not care if they have only new cards to learn, then they can un-check the "count new cards when checking card threshold" advanced option.

  2. Only notify me if no reviews have been done today: If a user dislikes receiving notifications and only wants to receive them if they are about to forget a review, they can toggle this advanced setting on.

One thing I struggled with during this project was deprecating the old notifications system. Previous attempts at creating review reminders were still sitting around in the codebase in a broken state. I had to sieve through the code to figure out what parts were safe to keep and which parts had to be removed. Here's a mind map I created while mapping out which parts of the codebase were broken:

Mind map of the old notifications system

Architecture ⚒️

Diagram of my code's organization

Pull Requests 🧑‍💻

While I filed other PRs during the summer, the following are the ones which are directly related to the review reminders feature. As of writing, a few stragglers are still awaiting review: see Next Steps for more information. Key PRs that added new features are bolded!

  1. feat(reminders): entry points
  2. feat(reminders): developer option
  3. feat(reminders): ReviewRemindersDatabase and ReviewReminder
  4. style: improve docstrings
  5. refactor: prefs for entry points
  6. refactor: ReviewReminderScope
  7. refactor: remove granular snooze settings
  8. refactor: clean up ReviewReminderScope.DeckSpecific.getDeckName
  9. refactor: make DeckDropDownAdapter SubtitleListener cast safe
  10. refactor: delete bulk deletion, use separate prefs file
  11. feat(reminders): add ScheduleReminders DeckSpinner init method
  12. feat(reminders): RecyclerView XML
  13. feat(reminders): ReviewReminder schema migration
  14. feat(reminders): make ReviewReminder Parcelable
  15. refactor: prepare BootService for review reminders
  16. refactor: prepare AnkiDroidApp, widget, and day-rollover for review reminders
  17. feat(reminders): review reminders RecyclerView
  18. improvement: permission explanations
  19. refactor: prepare AnkiActivity for review reminders
  20. feat(reminders): handle deck deletion
  21. feat(reminders): AddEditReminderDialog
  22. refactor: delete ReminderService
  23. feat(reminders): create global scope helper
  24. refactor(reminders): create allDecksCounts
  25. feat(reminders): create notification channel
  26. feat(reminders): AlarmManagerService and NotificationService
  27. feat(reminders): set alarms from ScheduleReminders
  28. improvement: delete TiramisuPermissionsFragment and streamline PermissionsItem
  29. feat(reminders): threshold filters
  30. feat(reminders): only notify if no reviews
  31. feat(reminders): request notification permissions

Most of my work is located in the reviewreminders directory, services, or ui/windows/permissions.

Highlights 💭

One of the major highlights of this project for me was handling ReviewReminder schema migration: basically, making sure the app wouldn't crash if a future developer decided to change the fields of the ReviewReminder data class stored in user devices. There were many unanticipated things I coded which I didn't expect to implement back in May, but this was the biggest unanticipated feature of the bunch. Nonetheless, I'm very happy with the way I solved the problem, complete with unit tests, and I hope that it will help future developers work with the code I've written.

It took a lot of time to get the UI for the AddEditReminderDialog right, especially because I ran into multiple bugs with implementing the MaterialUI TimePicker, but I eventually figured it all out. I'm very happy with the final visual result.

I learned a lot about writing good documentation while working on this project. With all the back-and-forth involved with reviewing code in an open source project, I'm quite confident this is some of the highest quality code I've ever written in my life.

Plan Changes 🔁

The project changed a bit from the initial plan as I worked on the code and discussed with my mentors regarding which features I should implement and which features were unnecessary.

  • Criteria 9 was not met because, after a maintainer debate, we decided it was better off as an add-on feature rather than one that should be included in the vanilla app.
  • Criteria 10 was met in a different way than originally planned: we decided creating two types of review reminders (single and persistent) was too confusing. Instead, I added two simple snooze buttons to the review reminder notifications. This feature changed a lot over the course of the summer. At various points in June and July, we were planning to have snooze settings for each individual reminder, an app-wide snooze setting...
  • The UI for the main review reminder editing screen was simplified and unnecessary features like multi-select deletion were removed. The UI for the AddEditReminderDialog was greatly simplified and streamlined so that users can easily edit which deck a review reminder is associated with, move review reminders around, etc.
  • Regarding Criteria 11: some of the advanced options, such as "Include cards from subdecks", were removed for being overly confusing. We decided to focus on providing clean defaults rather than allowing for infinite customizability.
  • Instead of adding Preferences Datastore as a new import to store review reminders, we decided to use the raw Preferences system instead, avoiding the introduction of a new dependency.
  • Snoozing was accomplished via AlarmManager instead of WorkManager as originally planned due to AlarmManager's scheduling behaviour being more predictable.

Next Steps ➡️

While I've fulfilled all of the things I set forth in my original project proposal, there's still a few things I've thought of over the course of this summer and which I still would like to add:

  1. Add a button in the toolbar of ScheduleReminders linking to the OS permissions screen
  2. Refactor ScheduleReminders to use a PermissionsActivity instead of SingleFragmentActivity to minimize the use of new Activities
  3. Clean up the strings and move them into the resource files to facilitate translation
  4. Set up a logging service to help with bug reports
  5. Write some instrumented tests
  6. Handle locale changes for notification channels to address this recently-opened issue
  7. Maybe create a "are you having trouble with notifications" page to help people who aren't receiving notifications troubleshoot what's going wrong.

And of course, some of my PRs are still awaiting being merged. Over the next few months, I hope to revise them and fully merge my changes into main, implement the above features, and patch any bugs that show up in my code during beta testing.

Overall, I'm super proud of what I've accomplished this summer. Looking forward to getting review reminders into a stable release and pushing it out to all of AnkiDroid's users! 🚀

If you're looking to learn more about me, connect with me on LinkedIn or check out my website. Have a great day!

About

Final Google Summer of Code 2025 Report - AnkiDroid

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published