diff --git a/README.md b/README.md index d408870fb..8ab63a16a 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,21 @@ -PdfBox-Android +PdfBox-Android (Maintained Fork) ============== -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.tom-roush/pdfbox-android/badge.svg?style=flat)](https://maven-badges.herokuapp.com/maven-central/com.tom-roush/pdfbox-android/) -[![Build Status](https://github.com/TomRoush/PdfBox-Android/actions/workflows/android-ci.yml/badge.svg?branch=master)](https://github.com/TomRoush/PdfBox-Android/actions) + + + -A port of Apache's PdfBox library to be usable on Android. Most features should be implemented by now. Feature requests can be added to the issue tracker. Stable releases can be added as a Gradle dependency from Maven Central. +This is a maintained fork of [TomRoush/PdfBox-Android](https://github.com/TomRoush/PdfBox-Android), which is a port of Apache's PdfBox library to be usable on Android. The original project has not received updates in over 2 years, so I've taken on maintenance to keep dependencies up to date. + +## Purpose and Maintenance Focus + +I maintain this fork primarily for form filling functionality in mobile applications. My focus areas are: + +- **Dependency updates**: Keeping BouncyCastle and other dependencies current +- **Java version compatibility**: Supporting latest Android/Java versions +- **Form filling features**: Maintaining and improving PDF form manipulation capabilities +- **Basic maintenance**: Bug fixes and compatibility updates + +**Note**: I may not actively monitor or implement other PDF features beyond form filling. Pull requests for additional features are welcome, but my primary focus remains on dependency maintenance and form-related functionality. The main code of this project is licensed under the Apache 2.0 License, found at http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/build.gradle b/build.gradle index bed855e79..d2c89fc6a 100644 --- a/build.gradle +++ b/build.gradle @@ -5,10 +5,11 @@ buildscript { repositories { mavenCentral() google() - jcenter() // jp2-android + // TODO: JCenter removed - jp2-android dependency unavailable after JCenter shutdown + // jcenter() // jp2-android } dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' + classpath 'com.android.tools.build:gradle:8.11.1' } } @@ -20,7 +21,8 @@ allprojects { // maven { url "https://s01.oss.sonatype.org/content/repositories/snapshots/" } mavenCentral() google() - jcenter() + // TODO: JCenter removed - jp2-android dependency unavailable after JCenter shutdown + // jcenter() } // Show more warnings if desired diff --git a/gradle.properties b/gradle.properties index dad4641be..4f79a4ce5 100755 --- a/gradle.properties +++ b/gradle.properties @@ -10,15 +10,15 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m +# org.gradle.jvmargs=-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx2048m org.gradle.parallel=true VERSION_NAME=2.0.27.1-SNAPSHOT VERSION_CODE=1 ANDROID_BUILD_MIN_SDK_VERSION=14 -ANDROID_BUILD_TARGET_SDK_VERSION=33 -ANDROID_BUILD_SDK_VERSION=33 +ANDROID_BUILD_TARGET_SDK_VERSION=35 +ANDROID_BUILD_SDK_VERSION=35 android.useAndroidX=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7e62b17ac..9bb857a04 100755 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/library/build.gradle b/library/build.gradle index c23a2afee..b526b1102 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -9,13 +9,13 @@ ext { } android { - compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION) + compileSdk = Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION) compileOptions.encoding = 'UTF-8' defaultConfig { testInstrumentationRunnerArguments notAnnotation: 'androidx.test.filters.FlakyTest' - minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION) - targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION) + minSdk = Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION) + targetSdk = Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION) testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles 'consumer-proguard-rules.txt' } @@ -40,17 +40,17 @@ android { } } lint { - abortOnError false + abortOnError = false } - namespace 'com.tom_roush.pdfbox' + namespace = 'com.tom_roush.pdfbox' compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } // Rename the output aars - android.libraryVariants.all { variant -> + android.libraryVariants.configureEach { variant -> variant.outputs.all { output -> if (outputFileName.endsWith('.aar')) { outputFileName = "pdfbox-android-${variant.name}-${defaultConfig.versionName}.aar" @@ -63,30 +63,30 @@ android { import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent -tasks.withType(Test) { +tasks.withType(Test).configureEach { // Performance improvements for tests maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 - reports.html.enabled = false - reports.junitXml.enabled = false + reports.html.required = false + reports.junitXml.required = false testLogging { // set options for log level LIFECYCLE events TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED, TestLogEvent.STANDARD_OUT, TestLogEvent.STANDARD_ERROR - showExceptions true - exceptionFormat TestExceptionFormat.FULL - showCauses true - showStackTraces true + showExceptions = true + exceptionFormat = TestExceptionFormat.FULL + showCauses = true + showStackTraces = true info.events = debug.events info.exceptionFormat = debug.exceptionFormat + } - afterSuite { desc, result -> - if (!desc.parent) { // will match the outermost suite - def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)" - def startItem = '| ', endItem = ' |' - def repeatLength = startItem.length() + output.length() + endItem.length() - println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength)) - } + afterSuite { desc, result -> + if (!desc.parent) { // will match the outermost suite + def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)" + def startItem = '| ', endItem = ' |' + def repeatLength = startItem.length() + output.length() + endItem.length() + println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength)) } } } @@ -96,7 +96,10 @@ dependencies { api "org.bouncycastle:bcpkix-jdk15to18:1.73" api "org.bouncycastle:bcutil-jdk15to18:1.73" // for jpeg2000 decode/encode - compileOnly 'com.gemalto.jp2:jp2-android:1.0.3' + // TODO: JPX/JPEG-2000 support removed due to dependency unavailability + // See issue #1 for reimplementation: https://github.com/muddxyii/PdfBox-Android/issues/1 + // Original dependency: com.gemalto.jp2:jp2-android:1.0.3 (JCenter shutdown) + // compileOnly 'com.gemalto.jp2:jp2-android:1.0.3' // Test dependencies testImplementation 'junit:junit:4.13.2' diff --git a/library/maven-publish.gradle b/library/maven-publish.gradle index c34745ba3..aee7e62ae 100644 --- a/library/maven-publish.gradle +++ b/library/maven-publish.gradle @@ -3,8 +3,8 @@ apply plugin: 'signing' ext.isReleaseVersion = !version.endsWith("SNAPSHOT") -task androidJavadocs(type: Javadoc) { - failOnError false +tasks.register('androidJavadocs', Javadoc) { + failOnError = false source = android.sourceSets.main.java.sourceFiles classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) @@ -25,18 +25,17 @@ task androidJavadocs(type: Javadoc) { exclude '**/R.java' } -afterEvaluate { - androidJavadocs.classpath += files(android.libraryVariants.collect { variant -> - variant.javaCompileProvider.get().classpath.files - }) +android.libraryVariants.configureEach { variant -> + androidJavadocs.classpath += variant.javaCompileProvider.get().classpath } -task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { +tasks.register('androidJavadocsJar', Jar) { + dependsOn androidJavadocs archiveClassifier.set('javadoc') from androidJavadocs.destinationDir } -task androidSourcesJar(type: Jar) { +tasks.register('androidSourcesJar', Jar) { archiveClassifier.set('sources') from android.sourceSets.main.java.srcDirs } @@ -84,9 +83,9 @@ project.afterEvaluate { artifact androidJavadocsJar artifact androidSourcesJar - groupId project.PUBLISH_GROUP_ID - artifactId project.PUBLISH_ARTIFACT_ID - version project.PUBLISH_VERSION + groupId = project.PUBLISH_GROUP_ID + artifactId = project.PUBLISH_ARTIFACT_ID + version = project.PUBLISH_VERSION pom.withXml { def root = asNode() diff --git a/library/src/main/java/com/tom_roush/pdfbox/filter/JPXFilter.java b/library/src/main/java/com/tom_roush/pdfbox/filter/JPXFilter.java index be006da3a..3acf10188 100644 --- a/library/src/main/java/com/tom_roush/pdfbox/filter/JPXFilter.java +++ b/library/src/main/java/com/tom_roush/pdfbox/filter/JPXFilter.java @@ -26,8 +26,11 @@ import java.io.InputStream; import java.io.OutputStream; -import com.gemalto.jp2.JP2Decoder; -import com.gemalto.jp2.JP2Encoder; +// TODO: JPX/JPEG-2000 support removed due to dependency unavailability +// See issue #1 for reimplementation: https://github.com/muddxyii/PdfBox-Android/issues/1 +// Original dependency: com.gemalto.jp2:jp2-android:1.0.3 (JCenter shutdown) +// import com.gemalto.jp2.JP2Decoder; +// import com.gemalto.jp2.JP2Encoder; import com.tom_roush.pdfbox.cos.COSDictionary; import com.tom_roush.pdfbox.cos.COSName; import com.tom_roush.pdfbox.io.IOUtils; @@ -37,8 +40,10 @@ * Decompress data encoded using the wavelet-based JPEG 2000 standard, * reproducing the original data. * - * Requires the JP2ForAndroid library to be available from com.gemalto.jp2:jp2-android:1.0.3, see - * JP2ForAndroid. + * NOTE: JPX/JPEG-2000 support temporarily removed due to dependency unavailability. + * The required JP2ForAndroid library (com.gemalto.jp2:jp2-android:1.0.3) is no longer + * available after JCenter shutdown. See issue #1 for reimplementation plans: + * https://github.com/muddxyii/PdfBox-Android/issues/1 * * @author John Hewson * @author Timo Boehme @@ -90,9 +95,19 @@ public DecodeResult decode(InputStream encoded, OutputStream decoded, return decode(encoded, decoded, parameters, index, DecodeOptions.DEFAULT); } - // try to read using JP2ForAndroid + // JPX/JPEG-2000 decoding - graceful degradation private Bitmap readJPX(InputStream input, DecodeOptions options, DecodeResult result) throws IOException { + // TODO: JPX/JPEG-2000 support removed due to dependency unavailability + // See issue #1 for reimplementation: https://github.com/muddxyii/PdfBox-Android/issues/1 + // Original dependency: com.gemalto.jp2:jp2-android:1.0.3 (JCenter shutdown) + throw new MissingImageReaderException( + "JPX/JPEG-2000 image support is temporarily unavailable. " + + "The required JP2ForAndroid library is no longer accessible after JCenter shutdown. " + + "See https://github.com/muddxyii/PdfBox-Android/issues/1 for reimplementation progress."); + + // Original implementation preserved for reference: + /* try { Class.forName("com.gemalto.jp2.JP2Decoder"); @@ -108,7 +123,9 @@ private Bitmap readJPX(InputStream input, DecodeOptions options, DecodeResult re // decoder.setSourceRegion(options.getSourceRegion()); Bitmap image = decoder.decode(); + */ + /* COSDictionary parameters = result.getParameters(); // "If the image stream uses the JPXDecode filter, this entry is optional @@ -135,6 +152,7 @@ private Bitmap readJPX(InputStream input, DecodeOptions options, DecodeResult re } return image; + */ } /** @@ -144,9 +162,20 @@ private Bitmap readJPX(InputStream input, DecodeOptions options, DecodeResult re protected void encode(InputStream input, OutputStream encoded, COSDictionary parameters) throws IOException { + // TODO: JPX/JPEG-2000 support removed due to dependency unavailability + // See issue #1 for reimplementation: https://github.com/muddxyii/PdfBox-Android/issues/1 + // Original dependency: com.gemalto.jp2:jp2-android:1.0.3 (JCenter shutdown) + throw new IOException( + "JPX/JPEG-2000 image encoding is temporarily unavailable. " + + "The required JP2ForAndroid library is no longer accessible after JCenter shutdown. " + + "See https://github.com/muddxyii/PdfBox-Android/issues/1 for reimplementation progress."); + + // Original implementation preserved for reference: + /* Bitmap bitmap = BitmapFactory.decodeStream(input); byte[] jpeBytes = new JP2Encoder(bitmap).encode(); IOUtils.copy(new ByteArrayInputStream(jpeBytes), encoded); encoded.flush(); + */ } } diff --git a/sample/build.gradle b/sample/build.gradle index abc4e1e6e..82f70ed86 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,15 +1,15 @@ apply plugin: 'com.android.application' android { - compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION) + compileSdk = Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION) defaultConfig { applicationId 'com.tom_roush.pdfbox.sample' - minSdkVersion 14 - targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION) + minSdk = 14 + targetSdk = Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION) versionName project.VERSION_NAME versionCode Integer.parseInt(project.VERSION_CODE) - multiDexEnabled true + multiDexEnabled = true } buildTypes { @@ -24,9 +24,9 @@ android { targetCompatibility JavaVersion.VERSION_1_8 } lint { - abortOnError false + abortOnError = false } - namespace 'com.tom_roush.pdfbox.sample' + namespace = 'com.tom_roush.pdfbox.sample' } dependencies { @@ -38,5 +38,8 @@ dependencies { // Optional dependencies // Read JPX images - implementation 'com.gemalto.jp2:jp2-android:1.0.3' + // TODO: JPX/JPEG-2000 support removed due to dependency unavailability + // See issue #1 for reimplementation: https://github.com/muddxyii/PdfBox-Android/issues/1 + // Original dependency: com.gemalto.jp2:jp2-android:1.0.3 (JCenter shutdown) + // implementation 'com.gemalto.jp2:jp2-android:1.0.3' }