Skip to content

Update Android SDK and other dependencies - #802

Merged
mickael-menu merged 31 commits into
readium:developfrom
stevenzeck:sdk-dependency-updates
Sep 11, 2026
Merged

mickael-menu merged 31 commits into
readium:developfrom
stevenzeck:sdk-dependency-updates

Conversation

@stevenzeck

@stevenzeck stevenzeck commented Jun 17, 2026 •

Copy link
Copy Markdown
Contributor

Leaving in draft until Kotlin Multiplatform supports Android Gradle Plugin 9.1.1, since SDK 37 requires that.

Changes

  1. Android target and compile SDK set to 37.
  2. Updates Kotlin to 2.4.20.
  3. Updates Android Gradle Plugin to 9.3.1.
  4. Updates room to room3.
  5. Updates other dependencies.
  6. Addresses deprecations from said updates.
  7. Updates code to use backing fields introduced in Kotlin 2.4.0.

Notes

  1. Android Studio will show errors for the backing fields. It's a known issue, but harmless and builds fine. You can add freeCompilerArgs.add("-XXLanguage:+ExplicitBackingFields") to the kotlin > compilerOptions block in gradle to suppress it.
  2. Need to test LCP passphrases that are already saved prior to this update to ensure no issues with room to room3.

@stevenzeck

Copy link
Copy Markdown
Contributor Author

Going to split this up into a few PRs.

@stevenzeck stevenzeck closed this Sep 1, 2026
@stevenzeck stevenzeck reopened this Sep 2, 2026
@stevenzeck

stevenzeck commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor Author

On second thought, things are too intertwined, especially with newer Jetpack releases requiring minSdk 24 and/or AGP versions.

@stevenzeck
stevenzeck marked this pull request as ready for review September 8, 2026 15:09
@stevenzeck
stevenzeck marked this pull request as draft September 8, 2026 15:11
@stevenzeck
stevenzeck marked this pull request as ready for review September 8, 2026 15:11
Comment thread buildSrc/src/main/kotlin/readium.library-conventions.gradle.kts

- name: Publish to Maven Central
run: ./gradlew publishToMavenCentral --no-configuration-cache
run: ./gradlew publishToMavenCentral

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you change this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0.34.0 added support for configuration cache. I thought that was there because it wasn't compatible with publishToMavenCentral at the time. Can remove it if you want.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be, from: https://kotlinlang.org/docs/multiplatform/multiplatform-publish-libraries-to-maven.html#add-a-github-actions-workflow-to-your-project

Image

The linked issue is still marked as open, but the changelog you shared seems to contradict it. Let's try without and see if it works during the next release.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I read in that issue, it was because of publishing to the older Sonatype Nexus. Since they no longer publish there, the blocker from gradle/gradle#22779 no longer applied.

Comment thread readium/lcp/build.gradle.kts Outdated
Comment thread readium/lcp/build.gradle.kts
Comment thread test-app/build.gradle.kts Outdated
@mickael-menu
mickael-menu requested a lite review from Copilot September 11, 2026 16:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical compilation errors remain, along with WebView null-safety and Room 3 compatibility issues.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Updates the Android SDK/toolchain, migrates persistence to Room 3, and applies related Kotlin and API compatibility changes.

Changes:

  • Raises Android SDK, Kotlin, AGP, Gradle, and dependency versions.
  • Migrates test-app and LCP databases to Room 3.
  • Updates UUIDs, backing fields, WebView handling, tests, workflows, and documentation.
File summaries
File Summary Findings
test-app/src/main/java/org/readium/r2/testapp/utils/FileSystem.kt Uses Kotlin UUIDs for temporary files. —
test-app/src/main/java/org/readium/r2/testapp/utils/extensions/Uri.kt Uses Kotlin UUIDs for copied files. —
test-app/src/main/java/org/readium/r2/testapp/reader/VisualReaderFragment.kt Updates IME dismissal. —
test-app/src/main/java/org/readium/r2/testapp/reader/ReaderViewModel.kt Updates search state handling. critical (2 votes): searchLocators is read-only as exposed and its writes cannot compile; retain a private MutableStateFlow.
test-app/src/main/java/org/readium/r2/testapp/domain/PublicationRetriever.kt Uses Kotlin UUIDs for imported files. —
test-app/src/main/java/org/readium/r2/testapp/domain/CoverStorage.kt Uses Kotlin UUIDs for covers. —
test-app/src/main/java/org/readium/r2/testapp/data/model/Highlight.kt Migrates Room annotations. —
test-app/src/main/java/org/readium/r2/testapp/data/model/Catalog.kt Migrates Room annotations. —
test-app/src/main/java/org/readium/r2/testapp/data/model/Bookmark.kt Migrates Room annotations. —
test-app/src/main/java/org/readium/r2/testapp/data/model/Book.kt Migrates Room annotations. —
test-app/src/main/java/org/readium/r2/testapp/data/db/CatalogDao.kt Migrates DAO annotations. —
test-app/src/main/java/org/readium/r2/testapp/data/db/BooksDao.kt Migrates DAO annotations. —
test-app/src/main/java/org/readium/r2/testapp/data/db/AppDatabase.kt Migrates database setup to Room 3. —
test-app/build.gradle.kts Configures Room 3 and Kotlin. —
settings.gradle.kts Updates plugin repositories. —
README.md Updates development requirements. —
readium/shared/src/main/java/org/readium/r2/shared/util/logging/WarningLogger.kt Uses explicit backing fields. critical (2 votes): warnings is exposed as List, so warnings.add() cannot compile; retain a mutable backing list.
readium/shared/src/main/java/org/readium/r2/shared/extensions/JSON.kt Handles null JSON values explicitly. —
readium/navigators/web/internals/src/main/kotlin/org/readium/navigator/web/internals/server/WebViewServer.kt Updates CORS header handling. moderate (1 vote): responseHeaders may be null; preserve the null fallback before adding the CORS header.
readium/navigators/web/internals/src/main/kotlin/org/readium/navigator/web/internals/server/WebViewClient.kt Updates WebView imports. nit (3 votes): Remove the unused import or implement the intended callback.
readium/navigators/media/tts/src/main/java/org/readium/navigator/media/tts/TtsEngineFacade.kt Uses Kotlin UUIDs. —
readium/navigators/media/tts/src/main/java/org/readium/navigator/media/tts/session/TtsTimeline.kt Uses Kotlin UUIDs for timeline IDs. —
readium/navigators/media/tts/src/main/java/org/readium/navigator/media/tts/android/AndroidTtsEngine.kt Updates settings state storage. critical (3 votes): settings.value is read-only through StateFlow; use a private MutableStateFlow. nit (1 vote): Remove the stale asStateFlow import.
readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfNavigatorViewModel.kt Updates locator state storage. critical (2 votes): currentLocator.value cannot be assigned through StateFlow; retain a private mutable flow. nit (1 vote): Remove the stale asStateFlow import.
readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2FXLPageFragment.kt Updates WebView imports. nit (3 votes): Remove the unused import or implement the intended callback.
readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2EpubPageFragment.kt Updates loading state storage. critical (2 votes): isLoaded.value cannot be assigned through StateFlow; use a private mutable flow. nit (3 votes): Remove the unused import.
readium/navigator/src/main/java/org/readium/r2/navigator/image/ImageNavigatorFragment.kt Updates locator state storage. critical (2 votes): currentLocator.value cannot be assigned through StateFlow; expose a private mutable backing flow.
readium/navigator/src/main/java/org/readium/r2/navigator/epub/WebViewServer.kt Updates CORS header handling. moderate (1 vote): responseHeaders may be null; preserve the null fallback when adding the CORS header.
readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorViewModel.kt Updates settings state storage. critical (2 votes): settings.value cannot be assigned through StateFlow; use a private MutableStateFlow.
readium/navigator/build.gradle.kts Enables Kotlin language features. —
readium/lcp/src/test/java/org/readium/r2/lcp/service/CRLServiceTest.kt Pins the Robolectric SDK. —
readium/lcp/src/test/java/org/readium/r2/lcp/LcpDecryptorTest.kt Pins the Robolectric SDK. —
readium/lcp/src/main/java/org/readium/r2/lcp/service/DeviceService.kt Uses Kotlin UUIDs for device IDs. —
readium/lcp/src/main/java/org/readium/r2/lcp/persistence/Passphrase.kt Migrates Room annotations. —
readium/lcp/src/main/java/org/readium/r2/lcp/persistence/License.kt Migrates Room annotations. —
readium/lcp/src/main/java/org/readium/r2/lcp/persistence/LcpDatabase.kt Migrates database APIs to Room 3. moderate (1 vote): Add a migration test verifying existing passphrases and licenses remain accessible.
readium/lcp/src/main/java/org/readium/r2/lcp/persistence/LcpDao.kt Migrates DAO annotations. —
readium/lcp/src/main/java/org/readium/r2/lcp/license/container/ContentZipLicenseContainer.kt Uses Kotlin UUIDs. —
readium/lcp/build.gradle.kts Updates Room and Kotlin dependencies. —
readium/adapters/pspdfkit/navigator/src/main/java/org/readium/adapter/pspdfkit/navigator/PsPdfKitDocumentFragment.kt Updates page-index state storage. critical (3 votes): pageIndex.value cannot be assigned through StateFlow; retain a private mutable flow. nit (1 vote): Remove the stale asStateFlow import.
readium/adapters/pspdfkit/document/src/main/java/org/readium/adapter/pspdfkit/document/ResourceDataProvider.kt Uses Kotlin UUIDs. —
readium/adapters/pdfium/navigator/src/test/resources/robolectric.properties Pins the Robolectric SDK. —
readium/adapters/pdfium/navigator/src/main/java/org/readium/adapter/pdfium/navigator/PdfiumDocumentFragment.kt Updates page-index state storage. critical (3 votes): pageIndex.value cannot be assigned through StateFlow; retain a private mutable flow. nit (1 vote): Remove the stale asStateFlow import.
readium/adapters/exoplayer/audio/src/main/java/org/readium/adapter/exoplayer/audio/ExoPlayerEngine.kt Updates playback state storage. critical (3 votes): playback.value cannot be assigned through StateFlow; retain a private mutable flow. nit (1 vote): Remove the stale asStateFlow import.
MAINTAINING.md Updates publishing instructions. —
gradle/wrapper/gradle-wrapper.properties Updates the Gradle wrapper. —
gradle/libs.versions.toml Updates dependency and plugin versions. nit (3 votes): The catalog selects Kotlin 2.4.20, AGP 9.3.1, and Gradle 9.7.0, conflicting with the stated Kotlin 2.4.10 and AGP 9.1.1; reconcile them before merging.
gradle.properties Raises Android SDK levels. —
demos/navigator/src/main/java/org/readium/demo/navigator/decorations/HighlightsManager.kt Updates immutable collection APIs. —
demos/navigator/build.gradle.kts Enables Kotlin language features. —
CHANGELOG.md Documents the minimum Android API change. —
buildSrc/src/main/kotlin/readium.library-conventions.gradle.kts Updates Kotlin and publishing configuration. —
.idea/kotlinc.xml Updates IDE Kotlin settings. —
.github/workflows/publish.yml Updates the publishing command. —
.github/workflows/checks.yml Updates pull request workflow triggers. —
Review details

Files not reviewed (1)

  • .idea/kotlinc.xml: Generated file

Suppressed comments (8)

readium/adapters/exoplayer/audio/src/main/java/org/readium/adapter/exoplayer/audio/ExoPlayerEngine.kt:236

  • Replacing both asStateFlow() projections here leaves the file's existing asStateFlow import unused. Since CI runs ktlintCheck, remove that stale import.
    override val playback: StateFlow<AudioEngine.Playback>
        field = MutableStateFlow(exoPlayer.playback)

    override val settings: StateFlow<ExoPlayerSettings>
        field = MutableStateFlow(settingsResolver.settings(initialPreferences))

readium/adapters/pdfium/navigator/src/main/java/org/readium/adapter/pdfium/navigator/PdfiumDocumentFragment.kt:155

  • Replacing _pageIndex.asStateFlow() here leaves the file's existing asStateFlow import unused. Since CI runs ktlintCheck, remove that stale import.
    override val pageIndex: StateFlow<Int>
        field = MutableStateFlow(initialPageIndex)

readium/adapters/pspdfkit/navigator/src/main/java/org/readium/adapter/pspdfkit/navigator/PsPdfKitDocumentFragment.kt:237

  • Replacing _pageIndex.asStateFlow() here leaves the file's existing asStateFlow import unused. Since CI runs ktlintCheck, remove that stale import.
    override val pageIndex: StateFlow<Int>
        field = MutableStateFlow(initialPageIndex)

readium/lcp/src/main/java/org/readium/r2/lcp/persistence/LcpDatabase.kt:40

  • This switches the production LCP database implementation from Room 2 to Room 3 while keeping the existing on-device database at version 2, but the test suite has no migration test that opens a pre-upgrade database and verifies saved passphrases and licenses. Add a compatibility test before approving this change; otherwise an incompatibility in the Room 3 identity/schema handling can make existing data inaccessible.
            val MIGRATION_1_2 = object : Migration(1, 2) {
                override suspend fun migrate(connection: SQLiteConnection) {
                    connection.execSQL(

readium/navigator/src/main/java/org/readium/r2/navigator/epub/WebViewServer.kt:262

  • responseHeaders can be null for responses returned by WebViewAssetLoader (the asset handler uses the constructor without headers). Calling + directly on it can throw before the CORS header is set, breaking asset requests. Preserve the null fallback when constructing the new map.
        responseHeaders = responseHeaders + mapOf("Access-Control-Allow-Origin" to "*")

readium/navigator/src/main/java/org/readium/r2/navigator/pdf/PdfNavigatorViewModel.kt:41

  • After replacing both asStateFlow() projections, this declaration leaves the existing asStateFlow import unused. Since CI runs ktlintCheck, remove the stale import or the lint job will fail.
    readium/navigators/media/tts/src/main/java/org/readium/navigator/media/tts/android/AndroidTtsEngine.kt:271
  • The old read-only asStateFlow() projection is removed here, but the asStateFlow import remains unused. Since CI runs ktlintCheck, remove that stale import.
    readium/navigators/web/internals/src/main/kotlin/org/readium/navigator/web/internals/server/WebViewServer.kt:228
  • responseHeaders can be null for responses returned by WebViewAssetLoader (the asset handler uses the constructor without headers). Calling + directly on it can throw before the CORS header is set, breaking asset requests. Preserve the null fallback when constructing the new map.
  • Files reviewed: 54/55 changed files
  • Comments generated: 14
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread gradle/libs.versions.toml
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

@mickael-menu mickael-menu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @stevenzeck

@mickael-menu
mickael-menu merged commit f1fce0e into readium:develop Sep 11, 2026
4 checks passed
@mickael-menu
mickael-menu deleted the sdk-dependency-updates branch September 11, 2026 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants