version: '3' includes: common: ../Taskfile.yml vars: APP_ID: '{{.APP_ID | default "com.wails.app"}}' MIN_SDK: '21' TARGET_SDK: '34' NDK_VERSION: 'r26d' tasks: install:deps: summary: Check and install Android development dependencies cmds: - go run build/android/scripts/deps/install_deps.go env: TASK_FORCE_YES: '{{if .YES}}true{{else}}false{{end}}' prompt: This will check and install Android development dependencies. Continue? build: summary: Creates a build of the application for Android deps: - task: common:go:mod:tidy - task: generate:android:bindings vars: BUILD_FLAGS: ref: .BUILD_FLAGS - task: common:build:frontend vars: BUILD_FLAGS: ref: .BUILD_FLAGS PRODUCTION: ref: .PRODUCTION - task: common:generate:icons cmds: - echo "Building Android app {{.APP_NAME}}..." - task: compile:go:shared vars: ARCH: '{{.ARCH | default "arm64"}}' vars: BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production,android -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-tags android,debug -buildvcs=false -gcflags=all="-l"{{end}}' env: PRODUCTION: '{{.PRODUCTION | default "false"}}' compile:go:shared: summary: Compile Go code to shared library (.so) cmds: - | NDK_ROOT="${ANDROID_NDK_HOME:-$ANDROID_HOME/ndk/{{.NDK_VERSION}}}" if [ ! -d "$NDK_ROOT" ]; then echo "Error: Android NDK not found at $NDK_ROOT" echo "Please set ANDROID_NDK_HOME or install NDK {{.NDK_VERSION}} via Android Studio" exit 1 fi # Determine toolchain based on host OS case "$(uname -s)" in Darwin) HOST_TAG="darwin-x86_64" ;; Linux) HOST_TAG="linux-x86_64" ;; *) echo "Unsupported host OS"; exit 1 ;; esac TOOLCHAIN="$NDK_ROOT/toolchains/llvm/prebuilt/$HOST_TAG" # Set compiler based on architecture case "{{.ARCH}}" in arm64) export CC="$TOOLCHAIN/bin/aarch64-linux-android{{.MIN_SDK}}-clang" export CXX="$TOOLCHAIN/bin/aarch64-linux-android{{.MIN_SDK}}-clang++" export GOARCH=arm64 JNI_DIR="arm64-v8a" ;; amd64|x86_64) export CC="$TOOLCHAIN/bin/x86_64-linux-android{{.MIN_SDK}}-clang" export CXX="$TOOLCHAIN/bin/x86_64-linux-android{{.MIN_SDK}}-clang++" export GOARCH=amd64 JNI_DIR="x86_64" ;; *) echo "Unsupported architecture: {{.ARCH}}" exit 1 ;; esac export CGO_ENABLED=1 export GOOS=android mkdir -p {{.BIN_DIR}} mkdir -p build/android/app/src/main/jniLibs/$JNI_DIR go build -buildmode=c-shared {{.BUILD_FLAGS}} \ -o build/android/app/src/main/jniLibs/$JNI_DIR/libwails.so vars: BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production,android -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-tags android,debug -buildvcs=false -gcflags=all="-l"{{end}}' compile:go:all-archs: summary: Compile Go code for all Android architectures (fat APK) cmds: - task: compile:go:shared vars: ARCH: arm64 - task: compile:go:shared vars: ARCH: amd64 package: summary: Packages a production build of the application into an APK deps: - task: build vars: PRODUCTION: "true" cmds: - task: assemble:apk package:fat: summary: Packages a production build for all architectures (fat APK) cmds: - task: compile:go:all-archs - task: assemble:apk assemble:apk: summary: Assembles the APK using Gradle cmds: - | cd build/android ./gradlew assembleDebug cp app/build/outputs/apk/debug/app-debug.apk "../../{{.BIN_DIR}}/{{.APP_NAME}}.apk" echo "APK created: {{.BIN_DIR}}/{{.APP_NAME}}.apk" assemble:apk:release: summary: Assembles a release APK using Gradle cmds: - | cd build/android ./gradlew assembleRelease cp app/build/outputs/apk/release/app-release-unsigned.apk "../../{{.BIN_DIR}}/{{.APP_NAME}}-release.apk" echo "Release APK created: {{.BIN_DIR}}/{{.APP_NAME}}-release.apk" generate:android:bindings: internal: true summary: Generates bindings for Android sources: - "**/*.go" - go.mod - go.sum generates: - frontend/bindings/**/* cmds: - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true env: GOOS: android CGO_ENABLED: 1 GOARCH: '{{.ARCH | default "arm64"}}' ensure-emulator: internal: true summary: Ensure Android Emulator is running silent: true cmds: - | # Check if an emulator is already running if adb devices | grep -q "emulator"; then echo "Emulator already running" exit 0 fi # Get first available AVD AVD_NAME=$(emulator -list-avds | head -1) if [ -z "$AVD_NAME" ]; then echo "No Android Virtual Devices found." echo "Create one using: Android Studio > Tools > Device Manager" exit 1 fi echo "Starting emulator: $AVD_NAME" emulator -avd "$AVD_NAME" -no-snapshot-load & # Wait for emulator to boot (max 60 seconds) echo "Waiting for emulator to boot..." adb wait-for-device for i in {1..60}; do BOOT_COMPLETED=$(adb shell getprop sys.boot_completed 2>/dev/null | tr -d '\r') if [ "$BOOT_COMPLETED" = "1" ]; then echo "Emulator booted successfully" exit 0 fi sleep 1 done echo "Emulator boot timeout" exit 1 preconditions: - sh: command -v adb msg: "adb not found. Please install Android SDK and add platform-tools to PATH" - sh: command -v emulator msg: "emulator not found. Please install Android SDK and add emulator to PATH" deploy-emulator: summary: Deploy to Android Emulator deps: [package] cmds: - adb uninstall {{.APP_ID}} 2>/dev/null || true - adb install "{{.BIN_DIR}}/{{.APP_NAME}}.apk" - adb shell am start -n {{.APP_ID}}/.MainActivity run: summary: Run the application in Android Emulator deps: - task: ensure-emulator - task: build vars: ARCH: x86_64 cmds: - task: assemble:apk - adb uninstall {{.APP_ID}} 2>/dev/null || true - adb install "{{.BIN_DIR}}/{{.APP_NAME}}.apk" - adb shell am start -n {{.APP_ID}}/.MainActivity logs: summary: Stream Android logcat filtered to this app cmds: - adb logcat -v time | grep -E "(Wails|{{.APP_NAME}})" logs:all: summary: Stream all Android logcat (verbose) cmds: - adb logcat -v time clean: summary: Clean build artifacts cmds: - rm -rf {{.BIN_DIR}} - rm -rf build/android/app/build - rm -rf build/android/app/src/main/jniLibs/*/libwails.so - rm -rf build/android/.gradle