From 29195ff5eca4689457a44b3b69ef8f1e86c7a7e6 Mon Sep 17 00:00:00 2001 From: wildan-m Date: Wed, 17 Jun 2026 23:54:02 +0700 Subject: [PATCH 1/3] Honor AlreadyClosedBehavior in openPage/openTextPage These were the only PdfDocument methods using an unconditional check(!isClosed) instead of handleAlreadyClosed(), so a configured AlreadyClosedBehavior.IGNORE never reached them. A render that lands on a just-closed document threw IllegalStateException on the renderer thread (PdfiumCore.renderPageBitmap -> openPage), which the barteksc RenderingHandler does not catch, crashing the app. Now they route through handleAlreadyClosed() like every sibling method and, when IGNORE is set, return a page bound to the closed document so all further ops no-op via the existing doc.isClosed guards. --- .../io/legere/pdfiumandroid/PdfDocument.kt | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/pdfiumandroid/src/main/java/io/legere/pdfiumandroid/PdfDocument.kt b/pdfiumandroid/src/main/java/io/legere/pdfiumandroid/PdfDocument.kt index 4107903..0bd5194 100644 --- a/pdfiumandroid/src/main/java/io/legere/pdfiumandroid/PdfDocument.kt +++ b/pdfiumandroid/src/main/java/io/legere/pdfiumandroid/PdfDocument.kt @@ -141,7 +141,18 @@ class PdfDocument( */ fun openPage(pageIndex: Int): PdfPage { synchronized(PdfiumCore.lock) { - check(!isClosed) { "Already closed" } + // Honor the configured AlreadyClosedBehavior instead of always throwing. + // Every other PdfDocument method routes its closed-state check through + // handleAlreadyClosed(); openPage/openTextPage were the only ones that did + // not, so AlreadyClosedBehavior.IGNORE never reached the exact call that + // crashes when a render lands on a just-closed document (see openPage in + // PdfiumCore.renderPageBitmap). When IGNORE is configured we return a page + // bound to this (closed) document; every PdfPage operation already guards on + // doc.isClosed via handleAlreadyClosed(), so the render is silently dropped + // with no native call instead of throwing on the renderer thread. + if (handleAlreadyClosed(isClosed)) { + return PdfPage(this, pageIndex, INVALID_PAGE_PTR, pageMap) + } if (pageMap.containsKey(pageIndex)) { pageMap[pageIndex]?.let { it.count++ @@ -376,7 +387,11 @@ class PdfDocument( @Deprecated("Use PdfPage.openTextPage instead", ReplaceWith("page.openTextPage()")) fun openTextPage(page: PdfPage): PdfTextPage { synchronized(PdfiumCore.lock) { - check(!isClosed) { "Already closed" } + // See openPage(): honor AlreadyClosedBehavior.IGNORE instead of throwing so a + // text-page open that races with document teardown is dropped, not fatal. + if (handleAlreadyClosed(isClosed)) { + return PdfTextPage(this, page.pageIndex, INVALID_PAGE_PTR, textPageMap) + } if (textPageMap.containsKey(page.pageIndex)) { textPageMap[page.pageIndex]?.let { it.count++ @@ -483,6 +498,12 @@ class PdfDocument( companion object { private val TAG = PdfDocument::class.java.name + // Sentinel native pointer used for the no-op PdfPage/PdfTextPage returned when a + // page is opened on an already-closed document under AlreadyClosedBehavior.IGNORE. + // It is never dereferenced: every PdfPage/PdfTextPage operation short-circuits via + // handleAlreadyClosed(doc.isClosed) before touching the native pointer. + private const val INVALID_PAGE_PTR = -1L + const val FPDF_INCREMENTAL = 1 const val FPDF_NO_INCREMENTAL = 2 const val FPDF_REMOVE_SECURITY = 3 From fcfe6948b335e74df9a1806336ef2e46550a1906 Mon Sep 17 00:00:00 2001 From: wildan-m Date: Thu, 18 Jun 2026 00:00:58 +0700 Subject: [PATCH 2/3] Add jitpack.yml: build only :pdfiumandroid on JDK 17 --- jitpack.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 jitpack.yml diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..f46b941 --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,4 @@ +jdk: + - openjdk17 +install: + - ./gradlew :pdfiumandroid:publishToMavenLocal -x test From e6c06c2905d1adf8b76f28c7440a2006033ca4c8 Mon Sep 17 00:00:00 2001 From: wildan-m Date: Thu, 18 Jun 2026 00:05:03 +0700 Subject: [PATCH 3/3] jitpack: accept Android SDK/NDK licenses before build --- jitpack.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jitpack.yml b/jitpack.yml index f46b941..1cfbcfe 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,4 +1,7 @@ jdk: - openjdk17 +before_install: + - yes | "${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager" --licenses > /dev/null 2>&1 || true + - yes | sdkmanager --licenses > /dev/null 2>&1 || true install: - - ./gradlew :pdfiumandroid:publishToMavenLocal -x test + - ./gradlew :pdfiumandroid:publishToMavenLocal -x test --no-daemon