From 30088b1629a244f57e7bed314e423aaba8d4858d Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Wed, 4 Mar 2026 13:34:13 +0800 Subject: [PATCH 01/18] build: add animal-sniffer plugin with android signatures --- pom.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pom.xml b/pom.xml index faac1ff91..d511caa33 100644 --- a/pom.xml +++ b/pom.xml @@ -234,6 +234,19 @@ + + + org.codehaus.mojo + animal-sniffer-maven-plugin + 1.27 + + + com.toasttab.android + gummy-bears-api-26 + 0.12.0 + + + From 39fb6fb658582879a66be107e06a0337b56c338e Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Tue, 17 Mar 2026 14:43:38 +0800 Subject: [PATCH 02/18] add animal-sniffer-annotations --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index d511caa33..86774017a 100644 --- a/pom.xml +++ b/pom.xml @@ -501,6 +501,12 @@ 1.2.13 test + + org.codehaus.mojo + animal-sniffer-annotations + 1.27 + true + From 716b1eee8c8babdf73d390423725bbc4eca001b3 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Tue, 17 Mar 2026 14:44:44 +0800 Subject: [PATCH 03/18] add ci check --- .github/workflows/ci.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d691f59d..fb73a630a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,6 +45,20 @@ jobs: - name: spotless:check run: mvn --batch-mode --no-transfer-progress spotless:check + android-signatures: + name: Check Android signatures + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: 11 + java-package: jdk + cache: 'maven' + - name: animal-sniffer:check + run: mvn --batch-mode --no-transfer-progress compile animal-sniffer:check + test: name: test ${{ matrix.os }} jdk${{ matrix.java }} strategy: @@ -190,7 +204,7 @@ jobs: release: name: Deploy - needs: [ lint, test, test_multiarch, test_external_amalgamation, test_graalvm ] + needs: [ lint, android-signatures, test, test_multiarch, test_external_amalgamation, test_graalvm ] if: github.repository_owner == 'xerial' && github.ref == 'refs/heads/master' # only perform on latest master runs-on: ubuntu-latest steps: From a774e72e8191fb25cb1fcad04dba1af87b390729 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Tue, 17 Mar 2026 14:46:27 +0800 Subject: [PATCH 04/18] ignore some part of the code for android --- src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java | 2 ++ src/main/java9/module-info.java | 1 + src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java b/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java index 542f0b95b..c9357dc66 100644 --- a/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java +++ b/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java @@ -22,6 +22,7 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.Calendar; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; import org.sqlite.SQLiteConnection; import org.sqlite.core.CorePreparedStatement; import org.sqlite.core.DB; @@ -169,6 +170,7 @@ public String getParameterClassName(int param) throws SQLException { } /** @see java.sql.ParameterMetaData#getParameterTypeName(int) */ + @IgnoreJRERequirement public String getParameterTypeName(int pos) throws SQLException { checkIndex(pos); return JDBCType.valueOf(getParameterType(pos)).getName(); diff --git a/src/main/java9/module-info.java b/src/main/java9/module-info.java index 3d8fa102c..78e10fc24 100644 --- a/src/main/java9/module-info.java +++ b/src/main/java9/module-info.java @@ -4,6 +4,7 @@ requires transitive java.sql; requires transitive java.sql.rowset; requires static org.graalvm.nativeimage; + requires animal.sniffer.annotations; exports org.sqlite; exports org.sqlite.core; diff --git a/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java b/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java index 17082155c..03439073b 100644 --- a/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java +++ b/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java @@ -1,5 +1,6 @@ package org.sqlite.nativeimage; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.hosted.RuntimeClassInitialization; import org.graalvm.nativeimage.hosted.RuntimeJNIAccess; @@ -21,6 +22,7 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +@IgnoreJRERequirement public class SqliteJdbcFeature implements Feature { @Override From dc03889a9f8e55e59afacd898f7c5a3f7c5f5b5d Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Tue, 17 Mar 2026 14:46:40 +0800 Subject: [PATCH 05/18] inline methods for android --- .../java/org/sqlite/jdbc4/JDBC4ResultSet.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/sqlite/jdbc4/JDBC4ResultSet.java b/src/main/java/org/sqlite/jdbc4/JDBC4ResultSet.java index 9747b0d68..2db589ddf 100644 --- a/src/main/java/org/sqlite/jdbc4/JDBC4ResultSet.java +++ b/src/main/java/org/sqlite/jdbc4/JDBC4ResultSet.java @@ -325,7 +325,10 @@ public T getObject(int columnIndex, Class type) throws SQLException { if (type == LocalDate.class) { try { Date date = getDate(columnIndex); - if (date != null) return type.cast(date.toLocalDate()); + if (date != null) + return type.cast( + LocalDate.of( + date.getYear() + 1900, date.getMonth() + 1, date.getDate())); else return null; } catch (SQLException sqlException) { // If the FastDateParser failed, try parse it with LocalDate. @@ -336,7 +339,9 @@ public T getObject(int columnIndex, Class type) throws SQLException { if (type == LocalTime.class) { try { Time time = getTime(columnIndex); - if (time != null) return type.cast(time.toLocalTime()); + if (time != null) + return type.cast( + LocalTime.of(time.getHours(), time.getMinutes(), time.getSeconds())); else return null; } catch (SQLException sqlException) { // If the FastDateParser failed, try parse it with LocalTime. @@ -347,7 +352,16 @@ public T getObject(int columnIndex, Class type) throws SQLException { if (type == LocalDateTime.class) { try { Timestamp timestamp = getTimestamp(columnIndex); - if (timestamp != null) return type.cast(timestamp.toLocalDateTime()); + if (timestamp != null) + return type.cast( + LocalDateTime.of( + timestamp.getYear() + 1900, + timestamp.getMonth() + 1, + timestamp.getDate(), + timestamp.getHours(), + timestamp.getMinutes(), + timestamp.getSeconds(), + timestamp.getNanos())); else return null; } catch (SQLException e) { // If the FastDateParser failed, try parse it with LocalDateTime. From 389f457f4d3564e2ff60e39945031865cb3777ab Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Tue, 17 Mar 2026 14:46:58 +0800 Subject: [PATCH 06/18] fix BatchUpdateException constructor --- src/main/java/org/sqlite/core/DB.java | 3 ++- src/main/java/org/sqlite/jdbc3/JDBC3Statement.java | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/sqlite/core/DB.java b/src/main/java/org/sqlite/core/DB.java index bd204c34f..5555abec4 100644 --- a/src/main/java/org/sqlite/core/DB.java +++ b/src/main/java/org/sqlite/core/DB.java @@ -17,6 +17,7 @@ import java.sql.BatchUpdateException; import java.sql.SQLException; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -945,7 +946,7 @@ private synchronized long[] executeBatch( "batch entry " + i + ": query returns results", null, 0, - changes, + Arrays.stream(changes).mapToInt(l -> (int) l).toArray(), null); } throwex(rc); diff --git a/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java b/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java index 1af5694bd..a0d13f7a9 100644 --- a/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java +++ b/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java @@ -246,7 +246,11 @@ public long[] executeLargeBatch() throws SQLException { changes[i] = db.executeUpdate(this, null); } catch (SQLException e) { throw new BatchUpdateException( - "batch entry " + i + ": " + e.getMessage(), null, 0, changes, e); + "batch entry " + i + ": " + e.getMessage(), + null, + 0, + Arrays.stream(changes).mapToInt(l -> (int) l).toArray(), + e); } finally { if (pointer != null) pointer.close(); } From 289bd55ed55a98ef14999eed0b77dd676a27c382 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Tue, 17 Mar 2026 14:47:18 +0800 Subject: [PATCH 07/18] update documentation --- README.adoc | 2 +- USAGE.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 01c326be4..1bd127437 100644 --- a/README.adoc +++ b/README.adoc @@ -115,7 +115,7 @@ the following operating systems: |macOS | |✔ | | | |✔ | | |Linux (libc) |✔ |✔ |✔ |✔ |✔ |✔ |✔ |✔ |Linux (musl) |✔ |✔ | | | |✔ | | -|Android (API Level 24+) |✔ |✔ |✔ | | |✔ | | +|Android (API Level 26+) |✔ |✔ |✔ | | |✔ | | |FreeBSD |✔ |✔ | | | |✔ | | |=== diff --git a/USAGE.md b/USAGE.md index 258762d18..bf44bd68c 100644 --- a/USAGE.md +++ b/USAGE.md @@ -202,6 +202,9 @@ The name of directories in our jar and in Android Studio differ, here is a mappi | x86 | x86 | | x86_64 | x86_64 | +The following methods will not work in Android: +- `JDBC3PreparedStatement#getParameterTypeName` + ## How to load Run-Time Loadable Extensions ### Enable loadable extensions From e8a816c8c906559aedbfe40c8e67dc0b142d3931 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Tue, 17 Mar 2026 14:56:45 +0800 Subject: [PATCH 08/18] use internal annotation --- pom.xml | 9 +++------ .../java/org/sqlite/jdbc3/JDBC3PreparedStatement.java | 4 ++-- .../java/org/sqlite/util/AndroidSignatureIgnore.java | 10 ++++++++++ src/main/java9/module-info.java | 1 - .../org/sqlite/nativeimage/SqliteJdbcFeature.java | 10 +++++++--- 5 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 src/main/java/org/sqlite/util/AndroidSignatureIgnore.java diff --git a/pom.xml b/pom.xml index 86774017a..3cb5469a9 100644 --- a/pom.xml +++ b/pom.xml @@ -245,6 +245,9 @@ gummy-bears-api-26 0.12.0 + + org.sqlite.util.AndroidSignatureIgnore + @@ -501,12 +504,6 @@ 1.2.13 test - - org.codehaus.mojo - animal-sniffer-annotations - 1.27 - true - diff --git a/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java b/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java index c9357dc66..d36510b29 100644 --- a/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java +++ b/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java @@ -22,10 +22,10 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.Calendar; -import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; import org.sqlite.SQLiteConnection; import org.sqlite.core.CorePreparedStatement; import org.sqlite.core.DB; +import org.sqlite.util.AndroidSignatureIgnore; public abstract class JDBC3PreparedStatement extends CorePreparedStatement { @@ -170,7 +170,7 @@ public String getParameterClassName(int param) throws SQLException { } /** @see java.sql.ParameterMetaData#getParameterTypeName(int) */ - @IgnoreJRERequirement + @AndroidSignatureIgnore public String getParameterTypeName(int pos) throws SQLException { checkIndex(pos); return JDBCType.valueOf(getParameterType(pos)).getName(); diff --git a/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java b/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java new file mode 100644 index 000000000..08c8dd8c9 --- /dev/null +++ b/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java @@ -0,0 +1,10 @@ +package org.sqlite.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.FIELD}) +public @interface AndroidSignatureIgnore {} diff --git a/src/main/java9/module-info.java b/src/main/java9/module-info.java index 78e10fc24..3d8fa102c 100644 --- a/src/main/java9/module-info.java +++ b/src/main/java9/module-info.java @@ -4,7 +4,6 @@ requires transitive java.sql; requires transitive java.sql.rowset; requires static org.graalvm.nativeimage; - requires animal.sniffer.annotations; exports org.sqlite; exports org.sqlite.core; diff --git a/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java b/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java index 03439073b..f165b9de0 100644 --- a/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java +++ b/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java @@ -1,14 +1,18 @@ package org.sqlite.nativeimage; -import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.hosted.RuntimeClassInitialization; import org.graalvm.nativeimage.hosted.RuntimeJNIAccess; import org.graalvm.nativeimage.hosted.RuntimeResourceAccess; -import org.sqlite.*; +import org.sqlite.BusyHandler; +import org.sqlite.Collation; +import org.sqlite.Function; +import org.sqlite.ProgressHandler; +import org.sqlite.SQLiteJDBCLoader; import org.sqlite.core.DB; import org.sqlite.core.NativeDB; import org.sqlite.jdbc3.JDBC3DatabaseMetaData; +import org.sqlite.util.AndroidSignatureIgnore; import org.sqlite.util.LibraryLoaderUtil; import org.sqlite.util.OSInfo; import org.sqlite.util.ProcessRunner; @@ -22,7 +26,7 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -@IgnoreJRERequirement +@AndroidSignatureIgnore public class SqliteJdbcFeature implements Feature { @Override From 0e2bc2bd6055e2d12a2ddd0835158ae7809b3649 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 19 Mar 2026 09:48:09 +0800 Subject: [PATCH 09/18] add comments --- src/main/java/org/sqlite/core/DB.java | 2 ++ src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java | 2 +- src/main/java/org/sqlite/jdbc3/JDBC3Statement.java | 2 ++ src/main/java/org/sqlite/jdbc4/JDBC4ResultSet.java | 3 +++ src/main/java/org/sqlite/util/AndroidSignatureIgnore.java | 6 +++++- .../java9/org/sqlite/nativeimage/SqliteJdbcFeature.java | 2 +- 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/sqlite/core/DB.java b/src/main/java/org/sqlite/core/DB.java index 5555abec4..efd7dc28f 100644 --- a/src/main/java/org/sqlite/core/DB.java +++ b/src/main/java/org/sqlite/core/DB.java @@ -942,6 +942,8 @@ private synchronized long[] executeBatch( if (rc != SQLITE_DONE) { reset(stmt); if (rc == SQLITE_ROW) { + // don't use the constructor with long because of + // https://github.com/xerial/sqlite-jdbc/issues/1378 throw new BatchUpdateException( "batch entry " + i + ": query returns results", null, diff --git a/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java b/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java index d36510b29..3b8a08863 100644 --- a/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java +++ b/src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java @@ -170,7 +170,7 @@ public String getParameterClassName(int param) throws SQLException { } /** @see java.sql.ParameterMetaData#getParameterTypeName(int) */ - @AndroidSignatureIgnore + @AndroidSignatureIgnore(explanation = "Android does not support java.sql.JDBCType") public String getParameterTypeName(int pos) throws SQLException { checkIndex(pos); return JDBCType.valueOf(getParameterType(pos)).getName(); diff --git a/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java b/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java index a0d13f7a9..5a1c4d681 100644 --- a/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java +++ b/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java @@ -245,6 +245,8 @@ public long[] executeLargeBatch() throws SQLException { db.prepare(this); changes[i] = db.executeUpdate(this, null); } catch (SQLException e) { + // don't use the constructor with long because of + // https://github.com/xerial/sqlite-jdbc/issues/1378 throw new BatchUpdateException( "batch entry " + i + ": " + e.getMessage(), null, diff --git a/src/main/java/org/sqlite/jdbc4/JDBC4ResultSet.java b/src/main/java/org/sqlite/jdbc4/JDBC4ResultSet.java index 2db589ddf..146fe25e3 100644 --- a/src/main/java/org/sqlite/jdbc4/JDBC4ResultSet.java +++ b/src/main/java/org/sqlite/jdbc4/JDBC4ResultSet.java @@ -326,6 +326,7 @@ public T getObject(int columnIndex, Class type) throws SQLException { try { Date date = getDate(columnIndex); if (date != null) + // inlining of java.sql.Date.toLocateDate() for Android return type.cast( LocalDate.of( date.getYear() + 1900, date.getMonth() + 1, date.getDate())); @@ -340,6 +341,7 @@ public T getObject(int columnIndex, Class type) throws SQLException { try { Time time = getTime(columnIndex); if (time != null) + // inlining of java.sql.Date.toLocateTime() for Android return type.cast( LocalTime.of(time.getHours(), time.getMinutes(), time.getSeconds())); else return null; @@ -353,6 +355,7 @@ public T getObject(int columnIndex, Class type) throws SQLException { try { Timestamp timestamp = getTimestamp(columnIndex); if (timestamp != null) + // inlining of java.sql.Date.toLocateDateTime() for Android return type.cast( LocalDateTime.of( timestamp.getYear() + 1900, diff --git a/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java b/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java index 08c8dd8c9..4235c7a8b 100644 --- a/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java +++ b/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java @@ -1,10 +1,14 @@ package org.sqlite.util; +import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +@Documented @Retention(RetentionPolicy.CLASS) @Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.FIELD}) -public @interface AndroidSignatureIgnore {} +public @interface AndroidSignatureIgnore { + String explanation(); +} diff --git a/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java b/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java index f165b9de0..e6b278b14 100644 --- a/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java +++ b/src/main/java9/org/sqlite/nativeimage/SqliteJdbcFeature.java @@ -26,7 +26,7 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -@AndroidSignatureIgnore +@AndroidSignatureIgnore(explanation = "Used by GraalVM only") public class SqliteJdbcFeature implements Feature { @Override From eb57aabac80ce60189ab40e50c574a222170c479 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 19 Mar 2026 10:05:33 +0800 Subject: [PATCH 10/18] use coreLib2 signatures --- .github/workflows/ci.yml | 4 ++++ pom.xml | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb73a630a..1c559070e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,10 @@ jobs: java-version: 11 java-package: jdk cache: 'maven' + - name: Download and install signatures jar + run: | + curl -L -o ./signatures.jar ./ https://repo1.maven.org/maven2/com/toasttab/android/gummy-bears-api-24/0.12.0/gummy-bears-api-24-0.12.0-coreLib2.signature + mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile=./signatures.jar -DgroupId=org.sqlite.signatures -DartifactId=gummy-bears-api-24 -Dversion=0.1 -Dpackaging=signature - name: animal-sniffer:check run: mvn --batch-mode --no-transfer-progress compile animal-sniffer:check diff --git a/pom.xml b/pom.xml index 3cb5469a9..d3f59f3b6 100644 --- a/pom.xml +++ b/pom.xml @@ -240,10 +240,19 @@ animal-sniffer-maven-plugin 1.27 + + + + + + + + + - com.toasttab.android - gummy-bears-api-26 - 0.12.0 + org.sqlite.signatures + gummy-bears-api-24 + 0.1 org.sqlite.util.AndroidSignatureIgnore From 85a1f29511c9b5c18573ff8bb2b1b3a7b7e81c9f Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 19 Mar 2026 10:08:07 +0800 Subject: [PATCH 11/18] try fix ci --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c559070e..a85fec7bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,8 +58,8 @@ jobs: cache: 'maven' - name: Download and install signatures jar run: | - curl -L -o ./signatures.jar ./ https://repo1.maven.org/maven2/com/toasttab/android/gummy-bears-api-24/0.12.0/gummy-bears-api-24-0.12.0-coreLib2.signature - mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile=./signatures.jar -DgroupId=org.sqlite.signatures -DartifactId=gummy-bears-api-24 -Dversion=0.1 -Dpackaging=signature + wget -O signatures.jar https://repo1.maven.org/maven2/com/toasttab/android/gummy-bears-api-24/0.12.0/gummy-bears-api-24-0.12.0-coreLib2.signature + mvn --batch-mode --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile=./signatures.jar -DgroupId=org.sqlite.signatures -DartifactId=gummy-bears-api-24 -Dversion=0.1 -Dpackaging=signature - name: animal-sniffer:check run: mvn --batch-mode --no-transfer-progress compile animal-sniffer:check From 96d835dc23922d93e10ade8a0c1f9ad51a377766 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 19 Mar 2026 10:10:54 +0800 Subject: [PATCH 12/18] try fix ci --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a85fec7bf..b862ba803 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,8 +58,8 @@ jobs: cache: 'maven' - name: Download and install signatures jar run: | - wget -O signatures.jar https://repo1.maven.org/maven2/com/toasttab/android/gummy-bears-api-24/0.12.0/gummy-bears-api-24-0.12.0-coreLib2.signature - mvn --batch-mode --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile=./signatures.jar -DgroupId=org.sqlite.signatures -DartifactId=gummy-bears-api-24 -Dversion=0.1 -Dpackaging=signature + wget -O coreLib2.signature.jar https://repo1.maven.org/maven2/com/toasttab/android/gummy-bears-api-24/0.12.0/gummy-bears-api-24-0.12.0-coreLib2.signature + mvn --batch-mode --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile=./coreLib2.signature -DgroupId=org.sqlite.signatures -DartifactId=gummy-bears-api-24 -Dversion=0.1 -Dpackaging=signature - name: animal-sniffer:check run: mvn --batch-mode --no-transfer-progress compile animal-sniffer:check From d55c11621cbd0cc33df206befc59069a967be7e7 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 19 Mar 2026 10:11:02 +0800 Subject: [PATCH 13/18] spotless apply --- src/main/java/org/sqlite/util/AndroidSignatureIgnore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java b/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java index 4235c7a8b..846ce0765 100644 --- a/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java +++ b/src/main/java/org/sqlite/util/AndroidSignatureIgnore.java @@ -10,5 +10,5 @@ @Retention(RetentionPolicy.CLASS) @Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.FIELD}) public @interface AndroidSignatureIgnore { - String explanation(); + String explanation(); } From 368a331ce60cc47f3a2779a52e2cf9b009f071a4 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 19 Mar 2026 10:12:51 +0800 Subject: [PATCH 14/18] more ci fixes --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b862ba803..c98ef91cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,7 +58,7 @@ jobs: cache: 'maven' - name: Download and install signatures jar run: | - wget -O coreLib2.signature.jar https://repo1.maven.org/maven2/com/toasttab/android/gummy-bears-api-24/0.12.0/gummy-bears-api-24-0.12.0-coreLib2.signature + wget -O coreLib2.signature https://repo1.maven.org/maven2/com/toasttab/android/gummy-bears-api-24/0.12.0/gummy-bears-api-24-0.12.0-coreLib2.signature mvn --batch-mode --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile=./coreLib2.signature -DgroupId=org.sqlite.signatures -DartifactId=gummy-bears-api-24 -Dversion=0.1 -Dpackaging=signature - name: animal-sniffer:check run: mvn --batch-mode --no-transfer-progress compile animal-sniffer:check From 615457c0ad64cea52900a1e2bd004c7abbc81193 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 19 Mar 2026 10:14:03 +0800 Subject: [PATCH 15/18] remove dead code --- src/main/java/org/sqlite/util/ProcessRunner.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/org/sqlite/util/ProcessRunner.java b/src/main/java/org/sqlite/util/ProcessRunner.java index 977a80546..bea35fa8d 100644 --- a/src/main/java/org/sqlite/util/ProcessRunner.java +++ b/src/main/java/org/sqlite/util/ProcessRunner.java @@ -3,7 +3,6 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.util.concurrent.TimeUnit; public class ProcessRunner { String runAndWaitFor(String command) throws IOException, InterruptedException { @@ -13,14 +12,6 @@ String runAndWaitFor(String command) throws IOException, InterruptedException { return getProcessOutput(p); } - String runAndWaitFor(String command, long timeout, TimeUnit unit) - throws IOException, InterruptedException { - Process p = Runtime.getRuntime().exec(command); - p.waitFor(timeout, unit); - - return getProcessOutput(p); - } - static String getProcessOutput(Process process) throws IOException { try (InputStream in = process.getInputStream()) { int readLen; From e9bfc570ac94b79163af566619b0aa19da622096 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 19 Mar 2026 10:30:46 +0800 Subject: [PATCH 16/18] ignore sqlite loader for Android --- src/main/java/org/sqlite/SQLiteJDBCLoader.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/sqlite/SQLiteJDBCLoader.java b/src/main/java/org/sqlite/SQLiteJDBCLoader.java index cfd41abc8..f430dccac 100644 --- a/src/main/java/org/sqlite/SQLiteJDBCLoader.java +++ b/src/main/java/org/sqlite/SQLiteJDBCLoader.java @@ -40,6 +40,7 @@ import java.util.Properties; import java.util.UUID; import java.util.stream.Stream; +import org.sqlite.util.AndroidSignatureIgnore; import org.sqlite.util.LibraryLoaderUtil; import org.sqlite.util.Logger; import org.sqlite.util.LoggerFactory; @@ -57,6 +58,7 @@ * * @author leo */ +@AndroidSignatureIgnore(explanation = "The loader is not used on Android") public class SQLiteJDBCLoader { private static final Logger logger = LoggerFactory.getLogger(SQLiteJDBCLoader.class); From d7de3642fe1a17c47538088e290aecdfd4ad7e3e Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 19 Mar 2026 10:31:06 +0800 Subject: [PATCH 17/18] replace Files.copy with buffer copy --- src/main/java/org/sqlite/SQLiteConnection.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/sqlite/SQLiteConnection.java b/src/main/java/org/sqlite/SQLiteConnection.java index 9837bedf1..6fcb8f018 100644 --- a/src/main/java/org/sqlite/SQLiteConnection.java +++ b/src/main/java/org/sqlite/SQLiteConnection.java @@ -1,14 +1,14 @@ package org.sqlite; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -316,8 +316,16 @@ private static File extractResource(URL resourceAddr) throws IOException { URLConnection conn = resourceAddr.openConnection(); // Disable caches to avoid keeping unnecessary file references after the single-use copy conn.setUseCaches(false); - try (InputStream reader = conn.getInputStream()) { - Files.copy(reader, dbFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + try (InputStream reader = conn.getInputStream(); + OutputStream writer = new FileOutputStream(dbFile)) { + // Replace this code with buffer copy so we don't rely on java.nio package for Android + // compatibility + // Files.copy(reader, dbFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = reader.read(buffer)) != -1) { + writer.write(buffer, 0, bytesRead); + } return dbFile; } } From 43163153b3c734e720a9cc8fc5d6739ebe51e779 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 19 Mar 2026 10:35:28 +0800 Subject: [PATCH 18/18] update docs --- README.adoc | 2 +- USAGE.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 1bd127437..01c326be4 100644 --- a/README.adoc +++ b/README.adoc @@ -115,7 +115,7 @@ the following operating systems: |macOS | |✔ | | | |✔ | | |Linux (libc) |✔ |✔ |✔ |✔ |✔ |✔ |✔ |✔ |Linux (musl) |✔ |✔ | | | |✔ | | -|Android (API Level 26+) |✔ |✔ |✔ | | |✔ | | +|Android (API Level 24+) |✔ |✔ |✔ | | |✔ | | |FreeBSD |✔ |✔ | | | |✔ | | |=== diff --git a/USAGE.md b/USAGE.md index bf44bd68c..06e4c9c5a 100644 --- a/USAGE.md +++ b/USAGE.md @@ -202,6 +202,8 @@ The name of directories in our jar and in Android Studio differ, here is a mappi | x86 | x86 | | x86_64 | x86_64 | +Your project will need to integrate the [desugared core library](https://developer.android.com/studio/write/java11-default-support-table) (default). + The following methods will not work in Android: - `JDBC3PreparedStatement#getParameterTypeName`