fix(android): repair buildozer build for Play Store AAB#1
Open
PhaedrusFlow wants to merge 12 commits into
Open
fix(android): repair buildozer build for Play Store AAB#1PhaedrusFlow wants to merge 12 commits into
PhaedrusFlow wants to merge 12 commits into
Conversation
- buildozer.spec: single-line requirements, NDK 25b pin, API 34, aab artifact - requirements-android.txt: drop desktop-only deps (faster-whisper, ctranslate2, ortools, numpy, pandas, geopy, pyproj, shapely, sounddevice) - core/geocoder.py: replace geopy with plain requests->Nominatim - mobile/screens/voice.py: guard ImportError when whisper/sounddevice unavailable on Android; show 'voice unavailable' notice - build.sh: clean/debug/release subcommands, ANDROIDNDK/ANDROIDAPI pins, JDK17 export - docs/ANDROID_BUILD.md: full Arch Linux runbook + Play Console steps Closes the Py_DEPRECATED(VERSION_UNUSED) cross-compile failure in pythonforandroid.toolchain create.
- 6a service account + Play Developer API one-time setup - 6b fastlane supply upload + track promotion - 6c pure-curl JWT->edit->bundle->track->commit flow - 6d app-content forms required before production promotion Uses real package coordinates com.tds.ontrack.ontrack@2.0.0 from buildozer.spec.
Kivy 2.3.1 ships pre-generated Cython C that calls _PyLong_AsByteArray
with 5 args. Python 3.14 added a 6th `with_exceptions` parameter, so
buildozer dies during the Cython extension compile with:
error: too few arguments to function call, expected 6, have 5
note: '_PyLong_AsByteArray' declared here (... 6 params)
The p4a project tracked this in kivy/python-for-android#3274 and shipped
the auto-resolve recipe in PR #3271; on the user side, the documented
fix is to use Kivy master (which is built with Cython >= 3.1 that emits
the new 6-arg call) plus p4a develop + API 36 + NDK r29.
Changes:
- buildozer.spec: kivy==2.3.0 -> kivy==master; android.api 34 -> 36;
android.ndk 25b -> 29; android.sdk 34 -> 36; comment block rewritten
to document the new tested combination.
- build.sh: auto-resolve ANDROIDNDK from $ANDROID_SDK_ROOT/ndk/29.*;
auto-detect buildozer in ~/venv_p4a_develop/bin first (the venv
Buildozer docs require for the Python 3.14 path); ANDROIDAPI 34 -> 36;
NDKAPI 21 -> 26; ANDROIDNDKVER 25b -> 29.
- docs/ANDROID_BUILD.md: rewrite \u00a71 (pre-flight) for the python3.14 venv
install; \u00a72 (SDK) for platform 36 / build-tools 36 / ndk r29; \u00a74
(build) to source the venv first; expanded troubleshooting table
with the _PyLong_AsByteArray entry and links to upstream issues.
Refs:
- https://buildozer.readthedocs.io/en/latest/installation/
- kivy/python-for-android#3271
- kivy/python-for-android#3274
A prior local commit on main tried to push a Crates.io token captured inside log.txt (`./build.sh release 2>&1 | tee log.txt`-style output). GitHub secret-scanning rejected the push, which is the correct behaviour, but the failure mode is easy to repeat. Block all build / runtime logs from being tracked at the repo level so nobody can accidentally commit a redirect of the buildozer/p4a output (which echoes $CARGO_REGISTRY_TOKEN, $PIP_INDEX_URL, etc.) again. Adds to .gitignore: - *.log - log.txt - buildozer_debug.log - .buildozer/ - bin/
p4a develop dropped the --feature CLI flag from the toolchain build
script:
python -m pythonforandroid.toolchain: error: unrecognized arguments:
--feature android.hardware.location
--feature android.hardware.location.gps
The new file build.py on the develop branch only registers
--uses-library, not --feature. Buildozer was still translating
'android.features = ...' into '--feature ...' for each value, so any
non-empty android.features blew up p4a's argparse.
Fix:
- Comment out android.features in buildozer.spec.
- Add android_manifest_extras.xml with the two <uses-feature> nodes
(android:required="false" so Wi-Fi-only devices can still install).
- Point buildozer at it with android.extra_manifest_xml. Buildozer
reads the file contents and passes them through --extra-manifest-xml,
which p4a still accepts.
- Add troubleshooting row in docs/ANDROID_BUILD.md.
Refs:
- kivy/python-for-android develop build.py (no --feature add_argument)
- kivy/buildozer android.py line ~1149 (still emits --feature)
…ilure Two issues from the latest build attempt: 1. 'bash: ~/venv_p4a_develop/bin/activate: No such file or directory' The Python 3.14 venv that build.sh expects was never created on this machine. Docs/ANDROID_BUILD.md §1 had the manual commands, but no single runnable script. Add scripts/setup-venv.sh: idempotent bootstrap that creates the venv at ~/venv_p4a_develop and installs buildozer (master), cython 0.29.34, legacy-cgi, setuptools, wheel. Supports --recreate to nuke and rebuild. build.sh's 'buildozer not found' message now points at this script. 2. 'gradlew clean bundleRelease failed' with no visible stack trace Buildozer hides subprocess stderr unless run with --verbose, so the actual Gradle error was lost. build.sh now invokes buildozer with --verbose automatically. Defensive cleanup: - Trim android_manifest_extras.xml to just the two <uses-feature> tags. The previous version had a multi-line XML comment that p4a passes verbatim into the template; some Jinja2 / AAPT2 combinations choke on comments-as-manifest-children. Bare tags are universally safe. Troubleshooting table in docs/ANDROID_BUILD.md gets three new rows: no-venv, no-buildozer (now points at setup script), silent gradle failure (run with --verbose).
Adds a second app variant 'FieldSnek' that ships from the same ONTrack
codebase under a separate Play Console listing (com.qompassai.fieldsnek).
The buildozer.spec for ONTrack is untouched; FieldSnek is driven by its
own spec so the two builds don't share bin_dir/build_dir and can iterate
independently.
New files:
- buildozer.fieldsnek.spec title=FieldSnek, package=com.qompassai.fieldsnek
bin_dir=/var/tmp/buildozer/fieldsnek/bin
- Gemfile + .bundle/config fastlane ~> 2.227, vendor/bundle (no system gems)
- fastlane/Appfile package_name=com.qompassai.fieldsnek,
reuses ~/.config/fastlane/google-play-ontrack.json
- fastlane/Fastfile lanes: closed (alpha), internal, check_auth, validate
glob-resolves the buildozer-generated AAB filename
and prints a bootstrap runbook on 'Package not found'
- fastlane/INIT.md one-time Play Console bootstrap runbook +
troubleshooting table + env var reference
- scripts/build-android.sh wrapper: 'aab|apk|both [ontrack|fieldsnek]'
with --help and mode/app validation
Updated:
- .gitignore allow buildozer.fieldsnek.spec through the *.spec
block, ignore vendor/bundle, fastlane reports
- docs/ANDROID_BUILD.md new \xc2\xa74b section on building + uploading FieldSnek
Usage on workstation:
source ~/venv_p4a_develop/bin/activate
bash scripts/build-android.sh aab fieldsnek # build for Play
bundle install --path vendor/bundle # first time
bundle exec fastlane android validate # dry-run upload
bundle exec fastlane android internal # real upload
The first AAB still has to be uploaded through the Play Console UI to
register the package_name with the API (Play Developer API v3 cannot
create apps); fastlane/INIT.md walks through the bootstrap.
The build script was passing 'buildozer --spec buildozer.fieldsnek.spec android release', but buildozer's argparse only accepts -v/--verbose, -h/--help, -p/--profile <name>, and --version (per buildozer/__init__.py::run_command). Anything else gets parsed as a target name, producing 'Unknown command/target buildozer.fieldsnek.spec'. Fix: scripts/build-android.sh now symlinks the chosen .spec to ./buildozer.spec for the duration of the build, then restores the original via an EXIT/INT/TERM trap. The wrapper validates the swap case where buildozer.spec is already a symlink, a regular file, or missing entirely, and never copies file contents. Also updates fastlane/INIT.md and the comment header of buildozer.fieldsnek.spec to remove the bogus --spec invocation references and document the symlink behavior + manual-bypass recipe.
Wholesale rebrand:
Text content (50 files):
ON-Track / ONTrack / OnTrack / Ontrack -> FieldSnek
ONTRACK_ env var prefix -> FIELDSNEK_
ONTRACK constant -> FIELDSNEK
ontrack -> fieldsnek
com.tds.ontrack package_name -> com.qompassai.fieldsnek
github.com/qompassai/ONTrack URLs -> github.com/qompassai/fieldsnek
Preserved verbatim:
ontrack-rs (sibling Rust repo, not this one)
File renames:
ontrack.spec -> fieldsnek.spec
installer/ontrack_installer.py -> installer/fieldsnek_installer.py
tools/scaffold_ontrack.py -> tools/scaffold_fieldsnek.py
assets/themes/ontrack.jsonc -> assets/themes/fieldsnek.jsonc
pipewire/51-ontrack-echo-cancel.conf -> pipewire/51-fieldsnek-echo-cancel.conf
Structural changes:
- buildozer.fieldsnek.spec merged into buildozer.spec; deleted variant.
There is now one canonical spec, package_name com.qompassai.fieldsnek.
- scripts/build-android.sh dropped the [ontrack|fieldsnek] app argument
and the spec-swap symlink dance (no longer needed with a single spec).
- fastlane/Fastfile dropped the FIELDSNEK_SPEC constant and the
'build-android.sh aab fieldsnek' invocation.
- .gitignore: removed the *.fieldsnek.spec exception; added .kivy/logs/.
- .kivy/logs/*.txt untracked (regenerated on every Kivy run).
Verified:
- python3 ast.parse on every modified .py file
- bash -n on every modified .sh file
- tomllib.loads on Cargo.toml, pyproject.toml, cliff.toml
- json.loads on .zenodo.json
- Zero residual 'ontrack' occurrences outside the protected 'ontrack-rs'
refs (which point to the sibling Rust repo).
Action item the user already started: GitHub repo renamed
qompassai/ONTrack -> qompassai/fieldsnek. Update your local remote:
git remote set-url origin https://github.com/qompassai/fieldsnek.git
Removes:
- Python comments (preserves docstrings)
- Shell comments (POSIX rule: # only after whitespace/SOL,
so ${#var}, $#, etc. are preserved)
- Ruby comments in Gemfile/Fastfile/Appfile (preserves "#{...}"
string interpolations)
- TOML/INI/.spec/YAML/.cff/Nix/.conf hash comments
- Rust/Kotlin/Java/JSONC // line and /* */ block comments
- Markdown HTML comments (<!-- ... -->)
- All emoji characters (Unicode pictograph + symbol ranges,
regional indicators, ZWJ, VS15/16)
Shebangs preserved. Two files (gui/components/address_table.py and
tests/test_platform_compat.py) had pre-existing syntax errors at
HEAD that are unaffected by this change.
Real bugs:
- mobile/app.py:63 — fix NameError: 'screen_nameame' typo (was
introduced in 2dd126d, way before this branch). The function
parameter is 'screen_name'; the doubled 'ame' suffix would
raise NameError on the first navigation call.
- gui/components/address_table.py:310 — fix SyntaxError: missing
'if lbl:' guard line. The body of the for-loop had a single
indented statement under `lbl = rw.get('addr')` with no
conditional, making the indentation unreachable.
- gui/components/address_table.py:22 — fix NameError: `ctk` was
used throughout the file (CTkFrame, CTkLabel, CTkFont,
CTkScrollableFrame) but customtkinter was never imported. The
unused `import tkinter as tk` is replaced with the correct
`import customtkinter as ctk`.
- tests/test_platform_compat.py:28 — fix SyntaxError: the
`_importable` helper had its `def` line missing, leaving an
orphan try/except at module scope. Restored the proper
definition; this is the helper called by every importability
test in the file.
- mobile/screens/voice.py:58 — remove duplicate, unguarded
`from core.voice import VoiceRecognizer` that defeated the
purpose of the preceding try/except guard.
Code quality:
- installer/fieldsnek_installer.py:43 — drop f-prefix on a
string with no placeholders (was `f"~/.local/share/fieldsnek"`).
- tests/test_voice.py:351 — drop unused `result =` assignment;
the test asserts on `elapsed`, not the value.
Comment cleanup follow-ups from previous strip pass:
- requirements.txt, requirements-android.txt, .env.example,
.gitignore — strip leftover `#` comments (pip requirements
files and .gitignore weren't covered by the previous pass).
Verified:
- python3 ast.parse on all 38 .py files — all parse
- pyflakes — no undefined names anywhere
- ruff F+E9 — zero real-bug findings (remaining noise is
"unused import" warnings)
- bash -n on all 6 .sh files
- tomllib on all .toml files
- json.loads on all .json + .jsonc files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Buildozer was failing on
pythonforandroid.toolchain createwith the cross-compile error:Three root causes were stacked:
requirements =inbuildozer.spec— mixed comma and newline separators caused python-for-android to parsefaster-whisper\nctranslate2\nrequestsas a single recipe name.faster-whisper,ctranslate2,ortools,geopy,numpy,pandas,pyproj,shapely,sounddevicehave no python-for-android recipe.Changes
buildozer.spec— single-line p4a-saferequirements, NDK 25b pin (android.ndk = 25b), API 34,android.release_artifact = aab.requirements-android.txt— rewritten to match.core/geocoder.py— replacedgeopy.geocoders.Nominatimwith a plainrequestscall to the Nominatim HTTP API (geopy isn't p4a-compatible).mobile/screens/voice.py— guardedfrom core.voice import VoiceRecognizerwithImportErrorcatch; renders a 'voice unavailable' notice on platforms wherefaster-whisper/sounddevicearen't installed.build.sh— addedclean/debug/releasesubcommands and exportedANDROIDNDK/ANDROIDAPI/NDKAPI/JAVA_HOMEpins.docs/ANDROID_BUILD.md— full Arch Linux pre-flight, SDK/NDK install, build reproduction, signing, and Play Console upload steps.Verifying locally (Arch)
./build.sh clean ./build.sh release # produces bin/ontrack-1.0-arm64-v8a-release.aabSee
docs/ANDROID_BUILD.mdfor the full runbook.