Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
557bc67
refactor: remove KNearest OCR pipeline from core
283375 Aug 2, 2026
a4903d9
refactor: drop kNearestModel from OCR call chain
283375 Aug 2, 2026
c40f693
refactor: remove KNearest model dependency management
283375 Aug 2, 2026
87f786e
refactor: remove KNearest model UI
283375 Aug 2, 2026
f4f09b4
chore: remove KNearest model resources
283375 Aug 2, 2026
8c2c6a0
fix: add filesDir import to LegacyKnnModelCleanUpTask
283375 Aug 2, 2026
f378307
build(deps): bump opencv from 4.13.0 to 5.0.0.1
283375 Aug 2, 2026
b7e9f7c
fix(app.db): remove non-existent 3->4 AutoMigration
283375 Aug 2, 2026
f3fc0d5
chore: bump ocr model cache key to 1.0.3
283375 Aug 2, 2026
2fcfcea
refactor: use custom-built onnxruntime/opencv artifacts
283375 Aug 3, 2026
06bdf56
ci: fetch custom onnxruntime/opencv artifacts
283375 Aug 4, 2026
64fff6f
ci: verify APK bundles custom-built libs, soft-fail with job summary
283375 Aug 4, 2026
6de55b0
ci: extract maven setup and APK signing to scripts
283375 Aug 4, 2026
e7590f7
ci: verify custom libs by size with hash for reference
283375 Aug 4, 2026
f4dd262
ci: group verification summary by library
283375 Aug 4, 2026
d642718
chore: add README
283375 Aug 4, 2026
0e49dbe
feat(app.ui): add basic ocr performance evaluation page
283375 Aug 16, 2026
cf476b1
fix: unify parallel count source
283375 Aug 18, 2026
6758429
fix: add crnn model asset file check
283375 Aug 18, 2026
01a6eaa
fix: optimize memory usage of ocr benchmark page and ocr core
283375 Aug 18, 2026
5668ab5
chore: refining comments
283375 Aug 18, 2026
0c056d4
fix: remove FixRect leftovers
283375 Aug 18, 2026
39ca313
chore: optimize Mat initialization from image
283375 Aug 18, 2026
5d35948
fix: drastically optimize OCR performance
283375 Aug 18, 2026
45247f9
chore: suppress unused warning
283375 Aug 18, 2026
84ce469
fix: simplify Mat initialization
283375 Aug 18, 2026
87d04e2
refactor: move OCR queue parallelism defaults out of OcrQueuePreferences
283375 Aug 28, 2026
74925b1
feat: verify OCR model asset metadata against model_info.json
283375 Aug 28, 2026
51bc36b
chore: move OpenCV Mat `use` util package for readability
283375 Aug 28, 2026
44801ee
fix: Mat and stream releasing
283375 Aug 28, 2026
c4eac3c
fix: address review findings in OCR performance benchmark
283375 Aug 29, 2026
7dcce48
Merge branch 'master' into refactor/custom-libs
283375 Aug 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/actions/setup-custom-maven/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Setup Custom Maven Repo
description: Downloads custom-built onnxruntime/opencv maven artifacts from custom-lib-builds releases into maven-local/

runs:
using: composite
steps:
# Cache may not applicable for onnxruntime, as it may change its opset while
# not changing its version.
# Since GitHub Actions should have quite fast Internet access to its own
# release service, we don't set up caches here.
- name: Download and extract custom maven repo
run: bash .github/scripts/setup-custom-maven.sh
shell: bash
2 changes: 1 addition & 1 deletion .github/actions/setup-ocr-model/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ runs:
uses: actions/cache@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
with:
path: app/src/main/assets/ocr
key: ocr-models_crnn-1.0.2
key: ocr-models_crnn-1.0.3

- name: Ensure CRNN OCR model asset folder exists
if: steps.cache-ocr.outputs.cache-hit != 'true'
Expand Down
39 changes: 39 additions & 0 deletions .github/scripts/setup-custom-maven.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# setup-custom-maven.sh
#
# Downloads the custom-built onnxruntime/opencv maven artifacts from the
# custom-lib-builds stable release tags and extracts them into maven-local/.
# maven-local/ uses the same GAVs as the official artifacts, so Gradle
# resolves the custom builds first (settings.gradle.kts local repo block).
#
# Hard-fail: a download error aborts the build. Falling back to the official
# artifacts would ship an APK that differs from what was verified locally.
set -euo pipefail

# .github/scripts/ -> repo root
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
MAVEN_LOCAL="${MAVEN_LOCAL:-$ROOT/maven-local}"

# Stable tags, overwritten on publish (URL stays the same, content changes).
# No actions/cache: a version-based cache key would serve stale artifacts
# after a republish. GitHub Actions has fast access to its own releases,
# so we just re-download (~125MB) on every run.
ORT_TAG="${ORT_TAG:-onnxruntime-1.26.0}"
OPENCV_TAG="${OPENCV_TAG:-opencv-5.0.0}"
BASE_URL="https://github.com/ArcaeaOffline/custom-lib-builds/releases/download"

mkdir -p "$MAVEN_LOCAL"

download_and_extract() { # $1=tag, $2=local zip path
curl -fL -o "$2" "$BASE_URL/$1/maven_repo.zip"
unzip -q -o "$2" -d "$MAVEN_LOCAL"
rm -f "$2"
}

download_and_extract "$ORT_TAG" /tmp/ort-maven.zip
download_and_extract "$OPENCV_TAG" /tmp/opencv-maven.zip

# The two zips have com/ and org/ roots; they merge into maven-local/
# without conflicts. Verify the expected AARs actually landed.
test -f "$MAVEN_LOCAL/com/microsoft/onnxruntime/onnxruntime-android/1.26.0/onnxruntime-android-1.26.0.aar"
test -f "$MAVEN_LOCAL/org/opencv/opencv/5.0.0/opencv-5.0.0.aar"
21 changes: 21 additions & 0 deletions .github/scripts/verify-apk-signing.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
# verify-apk-signing.sh
#
# Verifies signatures of all unstableRelease APKs.
# Hard-fail: unsigned or invalidly signed APKs must abort the build.
set -euo pipefail

# Use the newest build-tools for this run
BUILD_TOOLS_VERSION="$(find "$ANDROID_HOME/build-tools" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort -V | tail -n 1)"
PATH="$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION:$PATH"

APK_DIR="${APK_DIR:-app/build/outputs/apk/unstable/release}"

for apk in \
"$APK_DIR/app-unstable-arm64-v8a-release.apk" \
"$APK_DIR/app-unstable-armeabi-v7a-release.apk" \
"$APK_DIR/app-unstable-x86_64-release.apk" \
"$APK_DIR/app-unstable-x86-release.apk" \
"$APK_DIR/app-unstable-universal-release.apk"; do
apksigner verify --verbose --min-sdk-version 24 "$apk"
done
99 changes: 99 additions & 0 deletions .github/scripts/verify-custom-libs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
# Verifies the built APKs use the custom-built onnxruntime/opencv
# from maven-local/ instead of silently falling back to the
# official artifacts.
#
# Size is the primary signal: the custom .so files are ~50% the size
# of the official ones, far outside the +/-10% tolerance.
# sha256 hashes are reported for reference only: release build may
# strip on the .so files, so hashes legitimately differ there.
#
# Soft-fail: mismatches are reported as warnings in the job summary,
# but don't terminate the build.
set -euo pipefail

# .github/scripts/ -> repo root
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
MAVEN_LOCAL="${MAVEN_LOCAL:-$ROOT/maven-local}"
APK_DIR="${APK_DIR:-$ROOT/app/build/outputs/apk/unstable/release}"

# <so name>|<AAR path relative to maven-local>
# Keep in sync with .github/actions/setup-custom-maven/action.yml
LIBS=(
"libonnxruntime.so|com/microsoft/onnxruntime/onnxruntime-android/1.26.0/onnxruntime-android-1.26.0.aar"
"libopencv_java5.so|org/opencv/opencv/5.0.0/opencv-5.0.0.aar"
)
# universal APK is the union of these four, so no special checks for it
ABIS=(arm64-v8a armeabi-v7a x86 x86_64)

# sha256 of a file inside a zip; empty output if the entry is missing
# $1=zip file, $2=path inside zip
file_in_zip_sha256() {
if ! unzip -l "$1" "$2" >/dev/null 2>&1; then
return 1
fi
unzip -p "$1" "$2" | sha256sum | cut -d' ' -f1
}

# size of a file inside a zip; empty output if the entry is missing
# $1=zip file, $2=path inside zip
file_in_zip_size() {
if ! unzip -l "$1" "$2" >/dev/null 2>&1; then
return 1
fi
unzip -p "$1" "$2" | wc -c
}

warnings=()

{
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
echo "## Custom build verification"
echo ""
fi
for entry in "${LIBS[@]}"; do
so="${entry%%|*}"
aar="$MAVEN_LOCAL/${entry#*|}"
echo "### $so"
echo ""
echo "| ABI | Size (maven-local, B) | Size (APK, B) | sha256 (maven-local) | sha256 (APK) | Result |"
echo "| --- | --- | --- | --- | --- | --- |"
for abi in "${ABIS[@]}"; do
apk="$APK_DIR/app-unstable-$abi-release.apk"
if [ ! -f "$apk" ]; then
warnings+=("missing APK: $apk")
echo "| $abi | - | - | - | - | APK missing |"
continue
fi
custom="$(file_in_zip_sha256 "$aar" "jni/$abi/$so" || true)"
packed="$(file_in_zip_sha256 "$apk" "lib/$abi/$so" || true)"
custom_size="$(file_in_zip_size "$aar" "jni/$abi/$so" || true)"
packed_size="$(file_in_zip_size "$apk" "lib/$abi/$so" || true)"

result="OK"
if [ -z "$custom" ] || [ -z "$custom_size" ]; then
warnings+=("$abi/$so: custom .so not found in $aar")
result="NOT FOUND"
elif [ -z "$packed" ] || [ -z "$packed_size" ]; then
warnings+=("$abi/$so: .so not found in APK")
result="NOT FOUND"
elif [ "$packed_size" -lt $((custom_size * 90 / 100)) ] || \
[ "$packed_size" -gt $((custom_size * 110 / 100)) ]; then
warnings+=("$abi/$so: size ${packed_size}B, expected ~${custom_size}B")
result="SIZE MISMATCH"
fi
echo "| $abi | ${custom_size:--} | ${packed_size:--} | ${custom:0:12}.. | ${packed:0:12}.. | $result |"
done
echo ""
done
} >>"${GITHUB_STEP_SUMMARY:-/dev/null}"

if [ "${#warnings[@]}" -gt 0 ]; then
for w in "${warnings[@]}"; do
echo "::warning::$w"
done
# Non-zero exit marks the step yellow; the workflow step uses
# continue-on-error so this never blocks artifact upload/release.
exit 1
fi
exit 0
19 changes: 8 additions & 11 deletions .github/workflows/build_unstable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ jobs:
- name: Setup Toolchain
uses: ./.github/actions/setup-toolchain

- name: Setup Custom Maven
uses: ./.github/actions/setup-custom-maven

- name: Release keystore file
run: base64 -d <<< "${{ secrets.KEYSTORE_FILE_BASE64 }}" > arcaea_offline.jks

Expand All @@ -39,17 +42,11 @@ jobs:
run: ./gradlew assembleUnstableRelease

- name: Verify APK signing
run: |
# Locate the latest build tools
BUILD_TOOLS_VERSION=$(ls $ANDROID_HOME/build-tools/ | sort -V | tail -n 1)
# Adding build tools to PATH for this step only
PATH=$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION:$PATH

apksigner verify --verbose --min-sdk-version 24 app/build/outputs/apk/unstable/release/app-unstable-arm64-v8a-release.apk
apksigner verify --verbose --min-sdk-version 24 app/build/outputs/apk/unstable/release/app-unstable-armeabi-v7a-release.apk
apksigner verify --verbose --min-sdk-version 24 app/build/outputs/apk/unstable/release/app-unstable-x86_64-release.apk
apksigner verify --verbose --min-sdk-version 24 app/build/outputs/apk/unstable/release/app-unstable-x86-release.apk
apksigner verify --verbose --min-sdk-version 24 app/build/outputs/apk/unstable/release/app-unstable-universal-release.apk
run: bash .github/scripts/verify-apk-signing.sh

- name: Verify custom-built libs in APK
continue-on-error: true
run: bash .github/scripts/verify-custom-libs.sh

- name: Upload build result artifact (arm64-v8a)
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ jobs:
- name: Setup Toolchain
uses: ./.github/actions/setup-toolchain

- name: Setup Custom Maven
uses: ./.github/actions/setup-custom-maven

- name: Release local.properties file
run: cp local.defaults.properties local.properties

Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/connected-android-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ jobs:
- name: Setup Toolchain
uses: ./.github/actions/setup-toolchain

- name: Setup Custom Maven
uses: ./.github/actions/setup-custom-maven

- name: Release local.properties file
run: cp local.defaults.properties local.properties

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ app/src/main/assets/ocr/model*.onnx
app/src/main/assets/ocr/model*.ort
app/src/main/assets/ocr/model_info.json

# Local maven repo (custom-built artifacts: onnxruntime, opencv)
/maven-local/

# Android Studio added
/.idea/caches
/.idea/libraries
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Arcaea Offline Android Client

## Custom Maven Repo (Optional)

To reduce APK size, this project builds custom ONNX Runtime and OpenCV in [ArcaeaOffline/custom-lib-builds](https://github.com/ArcaeaOffline/custom-lib-builds), with unused features removed.

`settings.gradle.kts` gives the local maven repo the highest priority, simply download the matching artifacts from the custom-lib-builds Releases and unpack them.

If the local maven repo does not exist, Gradle falls back to Maven Central. This only affects APK size, not functionality.

## License

[GPL-3.0](LICENSE)
Loading
Loading