Recently Written · git

subread-android

SubRead for Android: times an audiobook against its ebook on the device

git clone https://github.com/equwal/subread-android

Log | Files | Refs


commit 0cb36e153c78018ada6123b28416195b5fae4155
equwal <truex@equwal.com>
2026-09-26 14:54:27 -0700

Turn on R8, build the speech library the same on each machine, and set the version to 0.9.2

F-Droid asks for R8 and for a reproducible build. The ggml sources put their file paths in the library (__FILE__), and ggml records the git state of the checkout. CMakeLists.txt now maps the paths of the checkout and of the NDK to fixed names, writes / on Windows too, and turns off the git lookup, so the library does not depend on the machine or the path. The recipe names the signed APK on GitHub (Binaries) and its key (AllowedAPKSigningKeys), and the category is Audiobook.

 app/build.gradle.kts                              | 11 +++++++----
 app/src/main/cpp/CMakeLists.txt                   | 14 ++++++++++++++
 fastlane/metadata/android/en-US/changelogs/12.txt |  1 +
 fdroid/space.subread.app.yml                      | 15 +++++++++------
 4 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index fa9f36a..ba9a8e6 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -28,8 +28,8 @@ android {
         minSdk = 26
         targetSdk = 36
         // Plain numbers, in this file: F-Droid reads them from here to find a new release.
-        versionCode = 11
-        versionName = "0.9.1"
+        versionCode = 12
+        versionName = "0.9.2"
         testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
 
         // A link to the Ko-fi page. Google Play is not given it (-PplayStore=true): its
@@ -61,8 +61,11 @@ android {
     buildTypes {
         debug { applicationIdSuffix = ".debug" }
         release {
-            // Not shrunk yet: R8 rules want a device to be verified against.
-            isMinifyEnabled = false
+            // R8 removes unused code and resources. F-Droid asks for it. The JNI
+            // methods of Whisper keep their names through the default rules.
+            isMinifyEnabled = true
+            isShrinkResources = true
+            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
             if (signingReady) signingConfig = signingConfigs.getByName("release")
         }
     }
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index e3f86f2..b5de705 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -12,6 +12,20 @@ endif ()
 
 set(WHISPER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../third_party/whisper.cpp)
 
+# Reproducible build: F-Droid builds this library again, on Linux and at another
+# path, and compares it with the signed APK. The maps remove the paths of the
+# build machine from the __FILE__ strings of ggml. -ffile-reproducible writes "/"
+# in them on Windows too. An empty GIT_EXE stops ggml from recording the git state
+# of the checkout, which the F-Droid scanner changes.
+get_filename_component(SUBREAD_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../.." ABSOLUTE)
+get_filename_component(SUBREAD_TOOLCHAIN_BIN "${CMAKE_C_COMPILER}" DIRECTORY)
+get_filename_component(SUBREAD_TOOLCHAIN_ROOT "${SUBREAD_TOOLCHAIN_BIN}" DIRECTORY)
+add_compile_options(
+    -ffile-reproducible
+    "-ffile-prefix-map=${SUBREAD_ROOT}=."
+    "-ffile-prefix-map=${SUBREAD_TOOLCHAIN_ROOT}=toolchain")
+set(GIT_EXE "" CACHE FILEPATH "Not used: the build records no git state" FORCE)
+
 set(BUILD_SHARED_LIBS      OFF CACHE BOOL "" FORCE)
 set(WHISPER_BUILD_TESTS    OFF CACHE BOOL "" FORCE)
 set(WHISPER_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
diff --git a/fastlane/metadata/android/en-US/changelogs/12.txt b/fastlane/metadata/android/en-US/changelogs/12.txt
new file mode 100644
index 0000000..10d4e4b
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/12.txt
@@ -0,0 +1 @@
+The settings end with links to the other apps of the author. The app is smaller: R8 removes code that it does not use. F-Droid can now check that its build is the same as the signed APK on GitHub.
diff --git a/fdroid/space.subread.app.yml b/fdroid/space.subread.app.yml
index 0f75437..b069257 100644
--- a/fdroid/space.subread.app.yml
+++ b/fdroid/space.subread.app.yml
@@ -1,5 +1,5 @@
 Categories:
-  - Multimedia
+  - Audiobook
   - Reading
 License: AGPL-3.0-only
 AuthorName: equwal
@@ -13,11 +13,12 @@ AutoName: SubRead
 
 RepoType: git
 Repo: https://github.com/equwal/subread-android.git
+Binaries: https://github.com/equwal/subread-android/releases/download/v%v/SubRead-%v.apk
 
 Builds:
-  - versionName: 0.9.1
-    versionCode: 11
-    commit: 2fdbdbb3e1585db5e0bc3468fe7fbefa72672428
+  - versionName: 0.9.2
+    versionCode: 12
+    commit: v0.9.2
     subdir: app
     submodules: true
     sudo:
@@ -34,6 +35,8 @@ Builds:
       - third_party/whisper.cpp/models
     ndk: 29.0.14206865
 
+AllowedAPKSigningKeys: e46f72ef28c79489cad0f1eee60cbf7fd3f29b5bff1bb1d82bab1e30427ff44f
+
 MaintainerNotes: |-
   app/src/main/assets/models/ggml-tiny-q8_0.bin is the OpenAI Whisper "tiny"
   speech model (MIT), converted to the ggml format with
@@ -45,5 +48,5 @@ MaintainerNotes: |-
 
 AutoUpdateMode: Version
 UpdateCheckMode: Tags
-CurrentVersion: 0.9.1
-CurrentVersionCode: 11
+CurrentVersion: 0.9.2
+CurrentVersionCode: 12