Anki-Android icon indicating copy to clipboard operation
Anki-Android copied to clipboard

CardContentProvider.answerCard cannot correctly handle non-top cards

Open xuanyue202 opened this issue 8 months ago • 3 comments

Checked for duplicates?

  • [x] This issue is not a duplicate

Does it also happen in the desktop version?

  • [x] This bug does not occur in the latest version of Anki Desktop

What are the steps to reproduce this bug?

  1. An external application uses the CardContentProvider to update the review status of a card via the content://com.ichi2.anki.flashcards/schedule URI.
  2. The target card, identified by NOTE_ID and CARD_ORD in the ContentValues, is not the currently active card in the AnkiDroid reviewer queue (i.e., not the topCard in the Scheduler.currentQueueState()).
  3. The external app calls update on the SCHEDULE URI, providing the card identifiers and an EASE value (e.g., FlashCardsContract.ReviewInfo.EASE).
  4. Buggy Behaviour: The previous implementation might incorrectly fetch the scheduling state of the current top card from the scheduler queue instead of the target card's actual state, or use a legacy answerCard method. This leads to the target card being reviewed with incorrect parameters, potentially messing up its scheduling interval.

Expected behaviour

When an external application updates a card's review status via the CardContentProvider (SCHEDULE URI):

  • The provider should determine if the target card matches the current top card in the scheduler's queue.
  • If it matches, the provider should use the readily available CurrentQueueState from the scheduler.
  • If it does not match (or the queue is empty), the provider must fetch the specific SchedulingStates for the target card.
  • In either case, the provider should use the correct card and its corresponding scheduling state to call the modern Scheduler.answerCard(info: CurrentQueueState, ease: Int) method.
  • This ensures the target card is always answered based on its own state and the provided ease level, resulting in the correct scheduling update.

Debug info

AnkiDroid 2.20.1 

(actually looked into the code, all versions has the same problem)
04-30 16:28:34.834 27079 27088 E AnkiDroid: ContentProvider/ answerCard - RuntimeException on answering card
04-30 16:28:34.834 27079 27088 E AnkiDroid: q7.d: card was modified: Normal(
04-30 16:28:34.834 27079 27088 E AnkiDroid:     Review(
04-30 16:28:34.834 27079 27088 E AnkiDroid:         ReviewState {
04-30 16:28:34.834 27079 27088 E AnkiDroid:             scheduled_days: 1,
04-30 16:28:34.834 27079 27088 E AnkiDroid:             elapsed_days: 10,
04-30 16:28:34.834 27079 27088 E AnkiDroid:             ease_factor: 2.5,
04-30 16:28:34.834 27079 27088 E AnkiDroid:             lapses: 0,
04-30 16:28:34.834 27079 27088 E AnkiDroid:             leeched: false,
04-30 16:28:34.834 27079 27088 E AnkiDroid:             memory_state: None,
04-30 16:28:34.834 27079 27088 E AnkiDroid:         },
04-30 16:28:34.834 27079 27088 E AnkiDroid:     ),
04-30 16:28:34.834 27079 27088 E AnkiDroid: ) Normal(
04-30 16:28:34.834 27079 27088 E AnkiDroid:     Review(
04-30 16:28:34.834 27079 27088 E AnkiDroid:         ReviewState {
04-30 16:28:34.834 27079 27088 E AnkiDroid:             scheduled_days: 2,
04-30 16:28:34.834 27079 27088 E AnkiDroid:             elapsed_days: 5,
04-30 16:28:34.834 27079 27088 E AnkiDroid:             ease_factor: 2.35,
04-30 16:28:34.834 27079 27088 E AnkiDroid:             lapses: 0,
04-30 16:28:34.834 27079 27088 E AnkiDroid:             leeched: false,
04-30 16:28:34.834 27079 27088 E AnkiDroid:             memory_state: None,
04-30 16:28:34.834 27079 27088 E AnkiDroid:         },
04-30 16:28:34.834 27079 27088 E AnkiDroid:     ),
04-30 16:28:34.834 27079 27088 E AnkiDroid: )
04-30 16:28:34.834 27079 27088 E AnkiDroid: 	at F8.i.b(SourceFile:362)
04-30 16:28:34.834 27079 27088 E AnkiDroid: 	at o7.a.i0(SourceFile:23)
04-30 16:28:34.834 27079 27088 E AnkiDroid: 	at Q4.g.a(SourceFile:52)
04-30 16:28:34.834 27079 27088 E AnkiDroid: 	at com.ichi2.anki.provider.CardContentProvider.update(SourceFile:566)
04-30 16:28:34.834 27079 27088 E AnkiDroid: 	at android.content.ContentProvider.update(ContentProvider.java:2074)
04-30 16:28:34.834 27079 27088 E AnkiDroid: 	at android.content.ContentProvider$Transport.update(ContentProvider.java:578)
04-30 16:28:34.834 27079 27088 E AnkiDroid: 	at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:243)
04-30 16:28:34.834 27079 27088 E AnkiDroid: 	at android.os.Binder.execTransactInternal(Binder.java:1409)
04-30 16:28:34.834 27079 27088 E AnkiDroid: 	at android.os.Binder.execTransact(Binder.java:1353)

(Optional) Anything else you want to share?

I can contribute to this one

Research

  • [x] I have checked the manual and the FAQ and could not find a solution to my issue
  • [x] (Optional) I have confirmed the issue is not resolved in the latest alpha release (instructions)

xuanyue202 avatar May 02 '25 04:05 xuanyue202

https://github.com/ankitects/anki/pull/3976
The PR above in Anki as a pre-requisite

xuanyue202 avatar May 02 '25 13:05 xuanyue202

  • Blocked on https://github.com/ankitects/anki/pull/3983

david-allison avatar Jun 03 '25 17:06 david-allison

Hello 👋, this issue has been opened for more than 3 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically

github-actions[bot] avatar Sep 01 '25 17:09 github-actions[bot]