ankidroid / Anki-Android

AnkiDroid: Anki flashcards on Android. Your secret trick to achieve superhuman information retention.
GNU General Public License v3.0
8.64k stars 2.24k forks source link

[BUG]: CardContentProvider uses the wrong authority uri in parallel builds #17309

Open iamllama opened 1 week ago

iamllama commented 1 week ago

Checked for duplicates?

Does it also happen in the desktop version?

What are the steps to reproduce this bug?

  1. Follow the instructions in https://github.com/ankidroid/Anki-Android/wiki/AnkiDroid-API, namely Gradle dependency and Manifest changes required on Android SDK 30+, while replacing com.ichi2.anki with com.ichi2.anki.a (or another parallel build)
  2. Execute a query with the content resolver, e.g.
val res: Cursor? = contentResolver.query(
    FlashCardsContract.Note.CONTENT_URI_V2,
    FlashCardsContract.Note.DEFAULT_PROJECTION,
    null,
    null,
    "${FlashCardsContract.Note._ID} desc"
);

Expected behaviour

A non-null Cursor is expected. Instead, the following error message is logged: Failed to find provider info for com.ichi2.anki.flashcards

This is because AnkiDroid.A's manifest has set CardContentProvider's authority uri to ${applicationId}.flashcards, which in the parallel build expands to com.ichi2.anki.a.flashcards. https://github.com/ankidroid/Anki-Android/blob/17748efe929a60ac4b1308b9a27358ae20f8a6e6/AnkiDroid/src/main/AndroidManifest.xml#L659-L666

If I try using that instead of FlashCardsContract.Note.CONTENT_URI_V2, i.e.

val res: Cursor? = contentResolver.query(
    Uri.parse("content://com.ichi2.anki.a.flashcards/notes_v2"),
    FlashCardsContract.Note.DEFAULT_PROJECTION,
    null,
    null,
    "${FlashCardsContract.Note._ID} desc"
);

the following exception is thrown:

FATAL EXCEPTION: main
Process: com.blah.app, PID: 15508
java.lang.IllegalArgumentException: uri content://com.ichi2.anki.a.flashcards/notes_v2 is not supported
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
    at android.content.ContentProviderProxy.query(ContentProviderNative.java:481)
    at android.content.ContentResolver.query(ContentResolver.java:1226)
    at android.content.ContentResolver.query(ContentResolver.java:1158)
    at android.content.ContentResolver.query(ContentResolver.java:1114)
    at com.blah.app.MainActivity.stuff(MainActivity.kt:33)
        ...

The parallel build's content provider now responds, but since it still matches on the incorrect FlashCardsContract.AUTHORITY, the uri is deemed invalid https://github.com/ankidroid/Anki-Android/blob/e9fe00726a48f7d347081379de8cb2334fbd80a6/AnkiDroid/src/main/java/com/ichi2/anki/provider/CardContentProvider.kt#L397

Debug info

AnkiDroid Version = 2.19beta6 (638d0e29cd91c49d6ca672ebc2494997751160ac)

Backend Version = 0.1.42-anki24.06.3 (24.06.3 d678e39350a2d243242a69f4e22f5192b04398f2)

Android Version = 12 (SDK 31)

(Optional) Anything else you want to share?

One way might be to have CardContentProvider construct its own copy of FlashCardsContract.AUTHORITY using R.string.applicationId BuildConfig.APPLICATION_ID, before passing it to the matcher https://github.com/ankidroid/Anki-Android/blob/e9fe00726a48f7d347081379de8cb2334fbd80a6/AnkiDroid/src/main/java/com/ichi2/anki/provider/CardContentProvider.kt#L141

Research

welcome[bot] commented 1 week ago

Hello! 👋 Thanks for logging this issue. Please remember we are all volunteers here, so some patience may be required before we can get to the issue. Also remember that the fastest way to get resolution on an issue is to propose a change directly, https://github.com/ankidroid/Anki-Android/wiki/Contributing