From 0c3249fa4b576152675c589eead2d402b984363e Mon Sep 17 00:00:00 2001 From: Dark98 Date: Thu, 2 Jul 2026 04:39:33 +0100 Subject: [PATCH] Refactor android-builder into command scripts --- BUGS_TODO.md | 13 ++ bin/android-builder | 380 ++--------------------------------------- lib/commands/build.sh | 24 +++ lib/commands/doctor.sh | 19 +++ lib/commands/export.sh | 60 +++++++ lib/commands/help.sh | 12 ++ lib/commands/new.sh | 53 ++++++ lib/commands/setup.sh | 74 ++++++++ lib/common.sh | 173 +++++++++++++++++++ 9 files changed, 438 insertions(+), 370 deletions(-) create mode 100644 BUGS_TODO.md create mode 100755 lib/commands/build.sh create mode 100755 lib/commands/doctor.sh create mode 100755 lib/commands/export.sh create mode 100755 lib/commands/help.sh create mode 100755 lib/commands/new.sh create mode 100755 lib/commands/setup.sh create mode 100644 lib/common.sh diff --git a/BUGS_TODO.md b/BUGS_TODO.md new file mode 100644 index 0000000..bb73857 --- /dev/null +++ b/BUGS_TODO.md @@ -0,0 +1,13 @@ +# Bugs / TODO + +## Bugs + +- `install.sh` defaults `ANDROID_BUILDER_REPO` to `http://192.168.1.46:8085/Dark98/Termux-Android-Builder.git`, which only works on the local LAN setup. If this repo is meant to be portable, the default should point to a stable remote or be documented as LAN-only. +- The generated `gradlew` wrapper just forwards to the system `gradle` package. That is convenient in Termux, but it means builds are not pinned to a project-specific Gradle wrapper version. +- The generated app pins Android Gradle Plugin `8.5.2` without pinning a compatible Gradle wrapper version. That can break when the installed Gradle package changes or is incompatible with that plugin version. +- The CLI is now split into a dispatcher plus per-command scripts under `lib/commands/`, which improves readability but adds more files to maintain. + +## TODO + +- Decide whether the default repo URL in `install.sh` should stay LAN-specific or be replaced with a public canonical URL. +- Consider generating a real Gradle wrapper for new projects instead of relying on `gradle` from Termux. diff --git a/bin/android-builder b/bin/android-builder index 4266c72..36ea698 100755 --- a/bin/android-builder +++ b/bin/android-builder @@ -1,378 +1,18 @@ #!/data/data/com.termux/files/usr/bin/bash set -e -AB_HOME="${ANDROID_BUILDER_HOME:-$HOME/android-builder}" -SDK="$HOME/android-sdk" -PLATFORM="${ANDROID_BUILDER_PLATFORM:-android-33}" - -get_project_name() { - if [ -f settings.gradle ]; then - DETECTED_NAME="$(grep -E '^rootProject.name[[:space:]]*=' settings.gradle \ - | sed -E 's/.*=[[:space:]]*["'\'']?([^"'\'' ]+)["'\'']?.*/\1/' \ - | head -n 1)" - - [ -n "$DETECTED_NAME" ] && echo "$DETECTED_NAME" && return - fi - - basename "$PWD" -} - -get_build_type() { - echo "${ANDROID_BUILDER_BUILD_TYPE:-debug}" -} - -get_apk_path() { - case "$(get_build_type)" in - debug) echo "app/build/outputs/apk/debug/app-debug.apk" ;; - release) echo "app/build/outputs/apk/release/app-release.apk" ;; - *) return 1 ;; - esac -} - -setup() { - echo "==> Installing packages" - pkg update -y - pkg install -y git curl wget unzip zip nano \ - openjdk-21 gradle aapt2 apksigner d8 dx android-tools - - echo "==> Configuring Java" - JAVA_BIN="$(command -v java)" - JAVA_HOME_DETECTED="$(dirname "$(dirname "$(readlink -f "$JAVA_BIN")")")" - export JAVA_HOME="$JAVA_HOME_DETECTED" - export PATH="$JAVA_HOME/bin:$PATH" - - touch "$HOME/.bashrc" - grep -q 'ANDROID_BUILDER_JAVA_HOME' "$HOME/.bashrc" || cat >> "$HOME/.bashrc" < Installing Android SDK cmdline-tools" - mkdir -p "$SDK/cmdline-tools" - cd "$SDK/cmdline-tools" - - if [ ! -d latest ]; then - wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdline-tools.zip - unzip -q cmdline-tools.zip - mv cmdline-tools latest - rm cmdline-tools.zip - fi - - export ANDROID_HOME="$SDK" - export ANDROID_SDK_ROOT="$SDK" - export PATH="$SDK/cmdline-tools/latest/bin:$PATH" - - grep -q 'ANDROID_HOME' "$HOME/.bashrc" || cat >> "$HOME/.bashrc" <<'EOF2' - -# AndroidBuilder SDK environment -export ANDROID_HOME=$HOME/android-sdk -export ANDROID_SDK_ROOT=$ANDROID_HOME -export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$PATH -EOF2 - - echo "==> Accepting Android SDK licenses" - mkdir -p "$SDK/licenses" - cat > "$SDK/licenses/android-sdk-license" <<'EOF2' -24333f8a63b6825ea9c5514f83c2829b004d1fee -d56f5187479451eabf01fb78af6dfcb131a6481e -8933bad161af4178b1185d1a37fbf41ea5269c55 -EOF2 - - echo "==> Installing SDK platform: $PLATFORM" - sdkmanager "platforms;$PLATFORM" - - echo "==> Writing Gradle config" - mkdir -p "$HOME/.gradle" - cat > "$HOME/.gradle/gradle.properties" < "$NAME/settings.gradle" < "$NAME/build.gradle" <<'EOF2' -// Root build file intentionally minimal. -EOF2 - - cat > "$NAME/gradle.properties" < "$NAME/local.properties" < "$NAME/app/build.gradle" < "$NAME/app/src/main/AndroidManifest.xml" <<'EOF2' - - - - - - - - - - -EOF2 - - cat > "$NAME/app/src/main/res/values/strings.xml" < - $NAME - -EOF2 - - cat > "$NAME/app/src/main/res/values/styles.xml" <<'EOF2' - - - -EOF2 - - cat > "$NAME/app/src/main/java/$PACKAGE_PATH/MainActivity.java" < "$NAME/gradlew" <<'EOF2' -#!/data/data/com.termux/files/usr/bin/bash -set -e -exec gradle "$@" -EOF2 - - chmod +x "$NAME/gradlew" - - echo "Created project: $NAME" - echo - echo "Next:" - echo " cd $NAME" - echo " android-builder build" - echo " android-builder export" -} - -build() { - test -f local.properties || echo "sdk.dir=$SDK" > local.properties - - if [ -f ./gradlew ]; then - chmod +x ./gradlew - ./gradlew assembleDebug - else - gradle assembleDebug - fi -} - -export_apk() { - APK="$(get_apk_path)" - BUILD_TYPE="$(get_build_type)" - - if [ ! -f "$APK" ]; then - echo "No $BUILD_TYPE APK found." - echo - echo "Run:" - echo " android-builder build" - exit 1 - fi - - if [ ! -d "$HOME/storage" ]; then - echo "==> Termux storage has not been configured." - echo "==> Requesting storage permission..." - echo - - termux-setup-storage - - echo - echo "Please grant storage permission, then run:" - echo " android-builder export" - exit 0 - fi - - EXPORT_DIR="$HOME/storage/documents" - mkdir -p "$EXPORT_DIR" - - PROJECT_NAME="$(get_project_name)" - DEST="$EXPORT_DIR/${PROJECT_NAME}.apk" - - echo "==> Exporting APK..." - - cp -f "$APK" "$DEST" - sync - - SIZE="$(du -h "$DEST" | cut -f1)" - - echo - echo "✓ Export complete!" - echo - echo "Project:" - echo " $PROJECT_NAME" - echo - echo "Build:" - echo " $BUILD_TYPE" - echo - echo "Size:" - echo " $SIZE" - echo - echo "Location:" - echo " $DEST" - echo - echo "Open your file manager, browse to Documents," - echo "then tap ${PROJECT_NAME}.apk to install or share it." -} - -help() { - echo "AndroidBuilder" - echo - echo "Usage:" - echo " android-builder setup" - echo " android-builder doctor" - echo " android-builder new MyApp" - echo " android-builder new MyApp --template empty" - echo " android-builder build" - echo " android-builder export" -} - -COMMAND="$1" -shift || true +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +COMMAND="${1:-help}" +TARGET="$COMMAND" case "$COMMAND" in - setup) setup "$@" ;; - doctor) doctor "$@" ;; - new) new_project "$@" ;; - build) build "$@" ;; - export) export_apk "$@" ;; - help|-h|--help|"") help ;; + setup|doctor|new|build|export|help|-h|--help) + case "$COMMAND" in + -h|--help) TARGET="help" ;; + esac + shift || true + exec "$ROOT_DIR/lib/commands/$TARGET.sh" "$@" + ;; *) echo "Unknown command: $COMMAND" echo "Run: android-builder help" diff --git a/lib/commands/build.sh b/lib/commands/build.sh new file mode 100755 index 0000000..90cb7c3 --- /dev/null +++ b/lib/commands/build.sh @@ -0,0 +1,24 @@ +#!/data/data/com.termux/files/usr/bin/bash +set -e + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +source "$ROOT_DIR/lib/common.sh" + +test -f local.properties || echo "sdk.dir=$SDK" > local.properties + +BUILD_TYPE="$(get_build_type)" +case "$BUILD_TYPE" in + debug) TASK="assembleDebug" ;; + release) TASK="assembleRelease" ;; + *) + echo "Unknown build type: $BUILD_TYPE" + exit 1 + ;; +esac + +if [ -f ./gradlew ]; then + chmod +x ./gradlew + ./gradlew "$TASK" +else + gradle "$TASK" +fi diff --git a/lib/commands/doctor.sh b/lib/commands/doctor.sh new file mode 100755 index 0000000..a030d20 --- /dev/null +++ b/lib/commands/doctor.sh @@ -0,0 +1,19 @@ +#!/data/data/com.termux/files/usr/bin/bash +set -e + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +source "$ROOT_DIR/lib/common.sh" + +echo "AndroidBuilder Doctor" +echo + +java -version +echo +gradle -v | grep Gradle +echo +aapt2 version +echo + +test -f "$SDK/platforms/$PLATFORM/android.jar" \ + && echo "android.jar: found" \ + || echo "android.jar: missing" diff --git a/lib/commands/export.sh b/lib/commands/export.sh new file mode 100755 index 0000000..a87d8cd --- /dev/null +++ b/lib/commands/export.sh @@ -0,0 +1,60 @@ +#!/data/data/com.termux/files/usr/bin/bash +set -e + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +source "$ROOT_DIR/lib/common.sh" + +APK="$(get_apk_path)" +BUILD_TYPE="$(get_build_type)" + +if [ ! -f "$APK" ]; then + echo "No $BUILD_TYPE APK found." + echo + echo "Run:" + echo " android-builder build" + exit 1 +fi + +if [ ! -d "$HOME/storage" ]; then + echo "==> Termux storage has not been configured." + echo "==> Requesting storage permission..." + echo + + termux-setup-storage + + echo + echo "Please grant storage permission, then run:" + echo " android-builder export" + exit 0 +fi + +EXPORT_DIR="$HOME/storage/documents" +mkdir -p "$EXPORT_DIR" + +PROJECT_NAME="$(get_project_name)" +DEST="$EXPORT_DIR/${PROJECT_NAME}.apk" + +echo "==> Exporting APK..." + +cp -f "$APK" "$DEST" +sync + +SIZE="$(du -h "$DEST" | cut -f1)" + +echo +echo "✓ Export complete!" +echo +echo "Project:" +echo " $PROJECT_NAME" +echo +echo "Build:" +echo " $BUILD_TYPE" +echo +echo "Size:" +echo " $SIZE" +echo +echo "Location:" +echo " $DEST" +echo +echo "Open your file manager, browse to Documents," +echo "then tap ${PROJECT_NAME}.apk to install or share it." diff --git a/lib/commands/help.sh b/lib/commands/help.sh new file mode 100755 index 0000000..9d249fb --- /dev/null +++ b/lib/commands/help.sh @@ -0,0 +1,12 @@ +#!/data/data/com.termux/files/usr/bin/bash +set -e + +echo "AndroidBuilder" +echo +echo "Usage:" +echo " android-builder setup" +echo " android-builder doctor" +echo " android-builder new MyApp" +echo " android-builder new MyApp --template empty" +echo " android-builder build" +echo " android-builder export" diff --git a/lib/commands/new.sh b/lib/commands/new.sh new file mode 100755 index 0000000..18e3f6c --- /dev/null +++ b/lib/commands/new.sh @@ -0,0 +1,53 @@ +#!/data/data/com.termux/files/usr/bin/bash +set -e + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +source "$ROOT_DIR/lib/common.sh" + +NAME="" +TEMPLATE="hello" + +while [ $# -gt 0 ]; do + case "$1" in + --template|-t) + if [ $# -lt 2 ] || [ -z "${2:-}" ] || [ "${2#-}" != "$2" ]; then + echo "Error: --template requires a value" + exit 1 + fi + TEMPLATE="$2" + shift 2 + ;; + --template=*) + TEMPLATE="${1#*=}" + shift + ;; + -*) + echo "Unknown option: $1" + exit 1 + ;; + *) + if [ -z "$NAME" ]; then + NAME="$1" + else + echo "Unknown argument: $1" + exit 1 + fi + shift + ;; + esac +done + +if [ -z "$NAME" ]; then + echo "Usage: android-builder new MyApp [--template hello|empty]" + exit 1 +fi + +case "$TEMPLATE" in + hello) create_base_project "$NAME" "Hello, World!" ;; + empty) create_base_project "$NAME" "" ;; + *) + echo "Unknown template: $TEMPLATE" + echo "Available templates: hello, empty" + exit 1 + ;; +esac diff --git a/lib/commands/setup.sh b/lib/commands/setup.sh new file mode 100755 index 0000000..d097086 --- /dev/null +++ b/lib/commands/setup.sh @@ -0,0 +1,74 @@ +#!/data/data/com.termux/files/usr/bin/bash +set -e + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +source "$ROOT_DIR/lib/common.sh" + +ensure_termux + +echo "==> Installing packages" +pkg update -y +pkg install -y git curl wget unzip zip nano \ + openjdk-21 gradle aapt2 apksigner d8 dx android-tools + +echo "==> Configuring Java" +JAVA_BIN="$(command -v java)" +JAVA_HOME_DETECTED="$(dirname "$(dirname "$(readlink -f "$JAVA_BIN")")")" +export JAVA_HOME="$JAVA_HOME_DETECTED" +export PATH="$JAVA_HOME/bin:$PATH" + +touch "$HOME/.bashrc" +grep -q 'ANDROID_BUILDER_JAVA_HOME' "$HOME/.bashrc" || cat >> "$HOME/.bashrc" < Installing Android SDK cmdline-tools" +mkdir -p "$SDK/cmdline-tools" +cd "$SDK/cmdline-tools" + +if [ ! -d latest ]; then + wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdline-tools.zip + unzip -q cmdline-tools.zip + mv cmdline-tools latest + rm cmdline-tools.zip +fi + +export ANDROID_HOME="$SDK" +export ANDROID_SDK_ROOT="$SDK" +export PATH="$SDK/cmdline-tools/latest/bin:$PATH" + +grep -q 'ANDROID_HOME' "$HOME/.bashrc" || cat >> "$HOME/.bashrc" <<'EOF2' + +# AndroidBuilder SDK environment +export ANDROID_HOME=$HOME/android-sdk +export ANDROID_SDK_ROOT=$ANDROID_HOME +export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$PATH +EOF2 + +echo "==> Accepting Android SDK licenses" +mkdir -p "$SDK/licenses" +cat > "$SDK/licenses/android-sdk-license" <<'EOF2' +24333f8a63b6825ea9c5514f83c2829b004d1fee +d56f5187479451eabf01fb78af6dfcb131a6481e +8933bad161af4178b1185d1a37fbf41ea5269c55 +EOF2 + +echo "==> Installing SDK platform: $PLATFORM" +sdkmanager "platforms;$PLATFORM" + +echo "==> Writing Gradle config" +mkdir -p "$HOME/.gradle" +cat > "$HOME/.gradle/gradle.properties" < "$NAME/settings.gradle" < "$NAME/build.gradle" <<'EOF2' +// Root build file intentionally minimal. +EOF2 + + cat > "$NAME/gradle.properties" < "$NAME/local.properties" < "$NAME/app/build.gradle" < "$NAME/app/src/main/AndroidManifest.xml" <<'EOF2' + + + + + + + + + + +EOF2 + + cat > "$NAME/app/src/main/res/values/strings.xml" < + $NAME + +EOF2 + + cat > "$NAME/app/src/main/res/values/styles.xml" <<'EOF2' + + + +EOF2 + + cat > "$NAME/app/src/main/java/$PACKAGE_PATH/MainActivity.java" < "$NAME/gradlew" <<'EOF2' +#!/data/data/com.termux/files/usr/bin/bash +set -e +exec gradle "$@" +EOF2 + + chmod +x "$NAME/gradlew" + + echo "Created project: $NAME" + echo + echo "Next:" + echo " cd $NAME" + echo " android-builder build" + echo " android-builder export" +}