`npx cap run android` runs `sync` by default, which regenerated `capacitor.plugins.json` and removed SafeArea and SharedImage entries after `restore-local-plugins.js` had already run. Use `--no-sync` in `build-android.sh` (auto-run) and `auto-run.sh` so the launch step does not overwrite the restored plugin list.
688 lines
25 KiB
Bash
Executable File
688 lines
25 KiB
Bash
Executable File
#!/bin/bash
|
|
# build-android.sh
|
|
# Author: Matthew Raymer
|
|
# Date: 2025-07-11
|
|
# Description: Android build script for TimeSafari application
|
|
# This script handles the complete Android build process including cleanup,
|
|
# web build, Capacitor build, Gradle build, and Android Studio launch.
|
|
#
|
|
# Usage:
|
|
# ./scripts/build-android.sh [options]
|
|
#
|
|
# Options:
|
|
# --dev, --development Build for development environment
|
|
# --test Build for testing environment
|
|
# --prod, --production Build for production environment
|
|
# --debug Build debug APK
|
|
# --release Build release APK
|
|
# --studio Open Android Studio after build
|
|
# --apk Build APK file
|
|
# --aab Build AAB (Android App Bundle)
|
|
# --clean Clean build artifacts only
|
|
# --sync Sync Capacitor only
|
|
# --assets Generate assets only
|
|
# --deploy Deploy APK to connected device
|
|
# --uninstall Uninstall app from connected device
|
|
# -h, --help Show this help message
|
|
# -v, --verbose Enable verbose logging
|
|
#
|
|
# Examples:
|
|
# ./scripts/build-android.sh --dev --studio # Development build + open studio
|
|
# ./scripts/build-android.sh --prod --apk # Production APK build
|
|
# ./scripts/build-android.sh --test --aab # Testing AAB build
|
|
# ./scripts/build-android.sh --clean # Clean only
|
|
# ./scripts/build-android.sh --sync # Sync only
|
|
#
|
|
# Exit Codes:
|
|
# 1 - Android cleanup failed
|
|
# 2 - Web build failed
|
|
# 3 - Capacitor build failed
|
|
# 4 - Gradle clean failed
|
|
# 5 - Gradle assemble failed
|
|
# 6 - Capacitor sync failed
|
|
# 7 - Asset generation failed
|
|
# 8 - Android Studio launch failed
|
|
# 9 - Android asset validation failed
|
|
|
|
# Exit on any error
|
|
set -e
|
|
|
|
# Source common utilities
|
|
source "$(dirname "$0")/common.sh"
|
|
|
|
# Function to validate critical dependencies
|
|
validate_dependencies() {
|
|
log_info "Validating critical dependencies..."
|
|
|
|
# Check if node_modules exists
|
|
if [ ! -d "node_modules" ]; then
|
|
log_error "node_modules directory not found. Please run 'npm install' first."
|
|
exit 1
|
|
fi
|
|
|
|
# Check if tsx is available
|
|
if [ ! -f "node_modules/.bin/tsx" ]; then
|
|
log_error "tsx dependency not found. Please run 'npm install' first."
|
|
exit 1
|
|
fi
|
|
|
|
# Check if capacitor-assets is available
|
|
if [ ! -f "node_modules/.bin/capacitor-assets" ]; then
|
|
log_error "capacitor-assets dependency not found. Please run 'npm install' first."
|
|
exit 1
|
|
fi
|
|
|
|
log_success "All critical dependencies validated successfully"
|
|
}
|
|
|
|
# Function to detect and set JAVA_HOME for Android builds
|
|
setup_java_home() {
|
|
log_info "Setting up Java environment..."
|
|
|
|
# If JAVA_HOME is already set and valid, use it
|
|
if [ -n "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then
|
|
log_debug "Using existing JAVA_HOME: $JAVA_HOME"
|
|
export JAVA_HOME
|
|
return 0
|
|
fi
|
|
|
|
# Try to find Java in Android Studio's bundled JBR
|
|
local android_studio_jbr="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
|
|
if [ -d "$android_studio_jbr" ] && [ -x "$android_studio_jbr/bin/java" ]; then
|
|
export JAVA_HOME="$android_studio_jbr"
|
|
log_info "Found Java in Android Studio: $JAVA_HOME"
|
|
if [ -x "$JAVA_HOME/bin/java" ]; then
|
|
log_debug "Java version: $(\"$JAVA_HOME/bin/java\" -version 2>&1 | head -1 || echo 'Unable to get version')"
|
|
fi
|
|
return 0
|
|
fi
|
|
|
|
# Try alternative Android Studio location (older versions)
|
|
local android_studio_jre="/Applications/Android Studio.app/Contents/jre/Contents/Home"
|
|
if [ -d "$android_studio_jre" ] && [ -x "$android_studio_jre/bin/java" ]; then
|
|
export JAVA_HOME="$android_studio_jre"
|
|
log_info "Found Java in Android Studio (legacy): $JAVA_HOME"
|
|
log_debug "Java version: $(\"$JAVA_HOME/bin/java\" -version 2>&1 | head -1)"
|
|
return 0
|
|
fi
|
|
|
|
# Try to use /usr/libexec/java_home on macOS
|
|
if [ "$(uname)" = "Darwin" ] && command -v /usr/libexec/java_home >/dev/null 2>&1; then
|
|
local java_home_output=$(/usr/libexec/java_home 2>/dev/null)
|
|
if [ -n "$java_home_output" ] && [ -x "$java_home_output/bin/java" ]; then
|
|
export JAVA_HOME="$java_home_output"
|
|
log_info "Found Java via java_home utility: $JAVA_HOME"
|
|
log_debug "Java version: $(\"$JAVA_HOME/bin/java\" -version 2>&1 | head -1)"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Try to find java in PATH
|
|
if command -v java >/dev/null 2>&1; then
|
|
local java_path=$(command -v java)
|
|
# Resolve symlinks to find actual Java home (portable approach)
|
|
local java_real="$java_path"
|
|
# Try different methods to resolve symlinks
|
|
if [ -L "$java_path" ]; then
|
|
if command -v readlink >/dev/null 2>&1; then
|
|
java_real=$(readlink "$java_path" 2>/dev/null || echo "$java_path")
|
|
elif command -v realpath >/dev/null 2>&1; then
|
|
java_real=$(realpath "$java_path" 2>/dev/null || echo "$java_path")
|
|
fi
|
|
fi
|
|
local java_home_candidate=$(dirname "$(dirname "$java_real")")
|
|
if [ -d "$java_home_candidate" ] && [ -x "$java_home_candidate/bin/java" ]; then
|
|
export JAVA_HOME="$java_home_candidate"
|
|
log_info "Found Java in PATH: $JAVA_HOME"
|
|
log_debug "Java version: $(\"$JAVA_HOME/bin/java\" -version 2>&1 | head -1)"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# If we get here, Java was not found
|
|
log_error "Java Runtime not found!"
|
|
log_error "Please ensure one of the following:"
|
|
log_error " 1. Android Studio is installed (includes bundled Java)"
|
|
log_error " 2. JAVA_HOME is set to a valid Java installation"
|
|
log_error " 3. Java is available in your PATH"
|
|
log_error ""
|
|
log_error "On macOS, Android Studio typically includes Java at:"
|
|
log_error " /Applications/Android Studio.app/Contents/jbr/Contents/Home"
|
|
return 1
|
|
}
|
|
|
|
# Function to detect and set ANDROID_HOME for Android builds
|
|
setup_android_home() {
|
|
log_info "Setting up Android SDK environment..."
|
|
|
|
# If ANDROID_HOME is already set and valid, use it
|
|
if [ -n "$ANDROID_HOME" ] && [ -d "$ANDROID_HOME" ]; then
|
|
log_debug "Using existing ANDROID_HOME: $ANDROID_HOME"
|
|
export ANDROID_HOME
|
|
return 0
|
|
fi
|
|
|
|
# Check for local.properties file in android directory
|
|
local local_props="android/local.properties"
|
|
if [ -f "$local_props" ]; then
|
|
local sdk_dir=$(grep "^sdk.dir=" "$local_props" 2>/dev/null | cut -d'=' -f2 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | sed "s|^file://||")
|
|
if [ -n "$sdk_dir" ] && [ -d "$sdk_dir" ]; then
|
|
export ANDROID_HOME="$sdk_dir"
|
|
log_info "Found Android SDK in local.properties: $ANDROID_HOME"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Try common macOS locations for Android SDK
|
|
local common_locations=(
|
|
"$HOME/Library/Android/sdk"
|
|
"$HOME/Android/Sdk"
|
|
"$HOME/.android/sdk"
|
|
)
|
|
|
|
for sdk_path in "${common_locations[@]}"; do
|
|
if [ -d "$sdk_path" ] && [ -d "$sdk_path/platform-tools" ]; then
|
|
export ANDROID_HOME="$sdk_path"
|
|
log_info "Found Android SDK: $ANDROID_HOME"
|
|
|
|
# Write to local.properties if it doesn't exist or doesn't have sdk.dir
|
|
if [ ! -f "$local_props" ] || ! grep -q "^sdk.dir=" "$local_props" 2>/dev/null; then
|
|
log_info "Writing Android SDK location to local.properties"
|
|
mkdir -p android
|
|
if [ -f "$local_props" ]; then
|
|
echo "" >> "$local_props"
|
|
echo "sdk.dir=$ANDROID_HOME" >> "$local_props"
|
|
else
|
|
echo "sdk.dir=$ANDROID_HOME" > "$local_props"
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
# If we get here, Android SDK was not found
|
|
log_error "Android SDK not found!"
|
|
log_error "Please ensure one of the following:"
|
|
log_error " 1. ANDROID_HOME is set to a valid Android SDK location"
|
|
log_error " 2. Android SDK is installed at one of these locations:"
|
|
log_error " - $HOME/Library/Android/sdk (macOS default)"
|
|
log_error " - $HOME/Android/Sdk"
|
|
log_error " 3. android/local.properties contains sdk.dir pointing to SDK"
|
|
log_error ""
|
|
log_error "You can find your SDK location in Android Studio:"
|
|
log_error " Preferences > Appearance & Behavior > System Settings > Android SDK"
|
|
return 1
|
|
}
|
|
|
|
# Function to validate Android assets and resources
|
|
validate_android_assets() {
|
|
log_info "Validating Android assets and resources..."
|
|
|
|
# Check if source assets exist
|
|
local missing_assets=()
|
|
|
|
if [ ! -f "resources/icon.png" ]; then
|
|
missing_assets+=("resources/icon.png")
|
|
fi
|
|
|
|
if [ ! -f "resources/splash.png" ]; then
|
|
missing_assets+=("resources/splash.png")
|
|
fi
|
|
|
|
if [ ! -f "resources/splash_dark.png" ]; then
|
|
missing_assets+=("resources/splash_dark.png")
|
|
fi
|
|
|
|
if [ ${#missing_assets[@]} -gt 0 ]; then
|
|
log_error "Missing source assets:"
|
|
for asset in "${missing_assets[@]}"; do
|
|
log_error " - $asset"
|
|
done
|
|
log_error "Please ensure all required assets are present in the resources/ directory."
|
|
return 1
|
|
fi
|
|
|
|
# Check if Android drawable resources exist
|
|
local missing_drawables=()
|
|
|
|
if [ ! -f "android/app/src/main/res/drawable/splash.png" ]; then
|
|
missing_drawables+=("drawable/splash.png")
|
|
fi
|
|
|
|
# Check if mipmap resources exist
|
|
local missing_mipmaps=()
|
|
local mipmap_dirs=("mipmap-mdpi" "mipmap-hdpi" "mipmap-xhdpi" "mipmap-xxhdpi" "mipmap-xxxhdpi")
|
|
|
|
for dir in "${mipmap_dirs[@]}"; do
|
|
if [ ! -f "android/app/src/main/res/$dir/ic_launcher.png" ]; then
|
|
missing_mipmaps+=("$dir/ic_launcher.png")
|
|
fi
|
|
if [ ! -f "android/app/src/main/res/$dir/ic_launcher_round.png" ]; then
|
|
missing_mipmaps+=("$dir/ic_launcher_round.png")
|
|
fi
|
|
done
|
|
|
|
# If any resources are missing, regenerate them
|
|
if [ ${#missing_drawables[@]} -gt 0 ] || [ ${#missing_mipmaps[@]} -gt 0 ]; then
|
|
log_warn "Missing Android resources detected:"
|
|
for resource in "${missing_drawables[@]}" "${missing_mipmaps[@]}"; do
|
|
log_warn " - $resource"
|
|
done
|
|
|
|
log_info "Regenerating Android assets..."
|
|
|
|
# Create assets directory if it doesn't exist
|
|
mkdir -p assets
|
|
|
|
# Copy source assets to assets directory for capacitor-assets
|
|
cp resources/icon.png assets/ 2>/dev/null || log_warn "Could not copy icon.png"
|
|
cp resources/splash.png assets/ 2>/dev/null || log_warn "Could not copy splash.png"
|
|
cp resources/splash_dark.png assets/ 2>/dev/null || log_warn "Could not copy splash_dark.png"
|
|
|
|
# Generate assets
|
|
if npx @capacitor/assets generate >/dev/null 2>&1; then
|
|
log_success "Android assets regenerated successfully"
|
|
|
|
# Clean up temporary assets
|
|
rm -f assets/icon.png assets/splash.png assets/splash_dark.png
|
|
|
|
# Verify the resources were created
|
|
local verification_failed=false
|
|
|
|
if [ ! -f "android/app/src/main/res/drawable/splash.png" ]; then
|
|
log_error "Failed to generate drawable/splash.png"
|
|
verification_failed=true
|
|
fi
|
|
|
|
for dir in "${mipmap_dirs[@]}"; do
|
|
if [ ! -f "android/app/src/main/res/$dir/ic_launcher.png" ]; then
|
|
log_error "Failed to generate $dir/ic_launcher.png"
|
|
verification_failed=true
|
|
fi
|
|
if [ ! -f "android/app/src/main/res/$dir/ic_launcher_round.png" ]; then
|
|
log_error "Failed to generate $dir/ic_launcher_round.png"
|
|
verification_failed=true
|
|
fi
|
|
done
|
|
|
|
if [ "$verification_failed" = true ]; then
|
|
log_error "Asset generation completed but some resources are still missing."
|
|
log_info "You may need to manually create the missing resources or check the asset generation process."
|
|
return 1
|
|
fi
|
|
else
|
|
log_error "Failed to generate Android assets"
|
|
log_info "You may need to manually create the missing resources:"
|
|
for resource in "${missing_drawables[@]}" "${missing_mipmaps[@]}"; do
|
|
log_info " - android/app/src/main/res/$resource"
|
|
done
|
|
return 1
|
|
fi
|
|
else
|
|
log_success "All Android assets and resources validated successfully"
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Default values
|
|
BUILD_MODE="development"
|
|
BUILD_TYPE="debug"
|
|
OPEN_STUDIO=false
|
|
BUILD_APK=false
|
|
BUILD_AAB=false
|
|
CLEAN_ONLY=false
|
|
SYNC_ONLY=false
|
|
ASSETS_ONLY=false
|
|
DEPLOY_APP=false
|
|
AUTO_RUN=false
|
|
UNINSTALL=false
|
|
CUSTOM_API_IP=""
|
|
|
|
# Function to parse Android-specific arguments
|
|
parse_android_args() {
|
|
local args=("$@")
|
|
local i=0
|
|
|
|
while [ $i -lt ${#args[@]} ]; do
|
|
local arg="${args[$i]}"
|
|
|
|
case $arg in
|
|
--dev|--development)
|
|
BUILD_MODE="development"
|
|
;;
|
|
--test)
|
|
BUILD_MODE="test"
|
|
;;
|
|
--prod|--production)
|
|
BUILD_MODE="production"
|
|
;;
|
|
--debug)
|
|
BUILD_TYPE="debug"
|
|
;;
|
|
--release)
|
|
BUILD_TYPE="release"
|
|
;;
|
|
--studio)
|
|
OPEN_STUDIO=true
|
|
;;
|
|
--apk)
|
|
BUILD_APK=true
|
|
;;
|
|
--aab)
|
|
BUILD_AAB=true
|
|
;;
|
|
--clean)
|
|
CLEAN_ONLY=true
|
|
;;
|
|
--sync)
|
|
SYNC_ONLY=true
|
|
;;
|
|
--assets|--assets-only)
|
|
ASSETS_ONLY=true
|
|
;;
|
|
--deploy)
|
|
DEPLOY_APP=true
|
|
;;
|
|
--auto-run)
|
|
AUTO_RUN=true
|
|
;;
|
|
--uninstall)
|
|
UNINSTALL=true
|
|
;;
|
|
--api-ip)
|
|
if [ $((i + 1)) -lt ${#args[@]} ]; then
|
|
CUSTOM_API_IP="${args[$((i + 1))]}"
|
|
i=$((i + 1)) # Skip the next argument
|
|
else
|
|
log_error "Error: --api-ip requires an IP address"
|
|
exit 1
|
|
fi
|
|
;;
|
|
--api-ip=*)
|
|
CUSTOM_API_IP="${arg#*=}"
|
|
;;
|
|
-h|--help)
|
|
print_android_usage
|
|
exit 0
|
|
;;
|
|
-v|--verbose)
|
|
set -x
|
|
;;
|
|
*)
|
|
log_warn "Unknown argument: $arg"
|
|
;;
|
|
esac
|
|
i=$((i + 1))
|
|
done
|
|
}
|
|
|
|
# Function to print Android-specific usage
|
|
print_android_usage() {
|
|
echo "Usage: $0 [options]"
|
|
echo ""
|
|
echo "Android Build Options:"
|
|
echo " --dev, --development Build for development environment"
|
|
echo " --test Build for testing environment"
|
|
echo " --prod, --production Build for production environment"
|
|
echo " --debug Build debug APK (default)"
|
|
echo " --release Build release APK"
|
|
echo " --studio Open Android Studio after build"
|
|
echo " --apk Build APK file"
|
|
echo " --aab Build AAB (Android App Bundle)"
|
|
echo " --clean Clean build artifacts only"
|
|
echo " --sync Sync Capacitor only"
|
|
echo " --assets Generate assets only"
|
|
echo " --deploy Deploy APK to connected device"
|
|
echo " --auto-run Auto-run app after build"
|
|
echo " --uninstall Uninstall app from connected device"
|
|
echo " --api-ip <ip> Custom IP address for claim API (defaults to 10.0.2.2)"
|
|
echo ""
|
|
echo "Common Options:"
|
|
echo " -h, --help Show this help message"
|
|
echo " -v, --verbose Enable verbose logging"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " $0 --dev --studio # Development build + open studio"
|
|
echo " $0 --prod --apk # Production APK build"
|
|
echo " $0 --test --aab # Testing AAB build"
|
|
echo " $0 --test --auto-run # Test build + auto-run"
|
|
echo " $0 --clean # Clean only"
|
|
echo " $0 --sync # Sync only"
|
|
echo " $0 --deploy # Build and deploy to device"
|
|
echo " $0 --uninstall # Uninstall app from device"
|
|
echo " $0 --dev # Dev build with default 10.0.2.2"
|
|
echo " $0 --dev --api-ip 192.168.1.100 # Dev build with custom API IP"
|
|
echo ""
|
|
}
|
|
|
|
# Parse command line arguments
|
|
parse_android_args "$@"
|
|
|
|
# Print build header
|
|
print_header "TimeSafari Android Build Process"
|
|
|
|
# Validate dependencies before proceeding
|
|
validate_dependencies
|
|
|
|
# Setup Java environment for Gradle
|
|
setup_java_home || {
|
|
log_error "Failed to setup Java environment. Cannot proceed with Android build."
|
|
exit 1
|
|
}
|
|
|
|
# Setup Android SDK environment for Gradle
|
|
setup_android_home || {
|
|
log_error "Failed to setup Android SDK environment. Cannot proceed with Android build."
|
|
exit 1
|
|
}
|
|
|
|
# Validate Android assets and resources
|
|
validate_android_assets || {
|
|
log_error "Android asset validation failed. Please fix the issues above and try again."
|
|
exit 9
|
|
}
|
|
|
|
# Log build start
|
|
log_info "Starting Android build process at $(date)"
|
|
log_info "Build mode: $BUILD_MODE"
|
|
log_info "Build type: $BUILD_TYPE"
|
|
|
|
# Setup environment for Capacitor build
|
|
setup_build_env "capacitor" "$BUILD_MODE"
|
|
|
|
# Override API servers for Android development
|
|
if [ "$BUILD_MODE" = "development" ]; then
|
|
if [ -n "$CUSTOM_API_IP" ]; then
|
|
# Use custom IP for physical device development
|
|
export VITE_DEFAULT_ENDORSER_API_SERVER="http://${CUSTOM_API_IP}:3000"
|
|
export VITE_DEFAULT_PARTNER_API_SERVER="http://${CUSTOM_API_IP}:3000"
|
|
log_info "Android development mode: Using custom IP ${CUSTOM_API_IP} for physical device"
|
|
else
|
|
# Use Android emulator IP (10.0.2.2) for Android development
|
|
export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000"
|
|
export VITE_DEFAULT_PARTNER_API_SERVER="http://10.0.2.2:3000"
|
|
log_debug "Android development mode: Using 10.0.2.2 for emulator"
|
|
fi
|
|
fi
|
|
|
|
# Setup application directories
|
|
setup_app_directories
|
|
|
|
# Load environment-specific .env file if it exists
|
|
env_file=".env.$BUILD_MODE"
|
|
if [ -f "$env_file" ]; then
|
|
load_env_file "$env_file"
|
|
else
|
|
log_debug "No $env_file file found, using default environment"
|
|
fi
|
|
|
|
# Load .env file if it exists (fallback)
|
|
if [ -f ".env" ]; then
|
|
load_env_file ".env"
|
|
fi
|
|
|
|
# Handle clean-only mode
|
|
if [ "$CLEAN_ONLY" = true ]; then
|
|
log_info "Clean-only mode: cleaning build artifacts"
|
|
safe_execute "Cleaning Android app" "npm run clean:android" || exit 1
|
|
safe_execute "Cleaning dist directory" "clean_build_artifacts dist" || exit 1
|
|
safe_execute "Cleaning Gradle build" "cd android && ./gradlew clean && cd .." || exit 4
|
|
log_success "Clean completed successfully!"
|
|
exit 0
|
|
fi
|
|
|
|
# Handle sync-only mode
|
|
if [ "$SYNC_ONLY" = true ]; then
|
|
log_info "Sync-only mode: syncing with Capacitor"
|
|
safe_execute "Syncing with Capacitor" "npx cap sync android" || exit 6
|
|
safe_execute "Restoring local plugins" "node scripts/restore-local-plugins.js" || exit 7
|
|
log_success "Sync completed successfully!"
|
|
exit 0
|
|
fi
|
|
|
|
# Handle assets-only mode
|
|
if [ "$ASSETS_ONLY" = true ]; then
|
|
log_info "Assets-only mode: generating assets"
|
|
safe_execute "Generating assets" "npx capacitor-assets generate --android" || exit 7
|
|
log_success "Assets generation completed successfully!"
|
|
exit 0
|
|
fi
|
|
|
|
# Handle deploy-app mode
|
|
if [ "$DEPLOY_APP" = true ]; then
|
|
log_info "Deploy-app mode: building APK and deploying to device"
|
|
|
|
# Check for connected device
|
|
if ! adb devices | grep -q $'\tdevice'; then
|
|
log_error "No Android device connected. Please connect a device and try again."
|
|
exit 1
|
|
fi
|
|
|
|
# Build APK
|
|
safe_execute "Building APK" "cd android && ./gradlew assembleDebug && cd .." || exit 5
|
|
|
|
# Install APK on device
|
|
safe_execute "Installing APK on device" "adb install -r android/app/build/outputs/apk/debug/app-debug.apk" || exit 6
|
|
|
|
log_success "APK deployed successfully to device!"
|
|
log_info "You can now run the app with: npx cap run android"
|
|
exit 0
|
|
fi
|
|
|
|
# Step 1: Validate asset configuration
|
|
safe_execute "Validating asset configuration" "npm run assets:validate" || {
|
|
log_warn "Asset validation found issues, but continuing with build..."
|
|
log_info "If you encounter build failures, please run 'npm install' first to ensure all dependencies are available."
|
|
}
|
|
|
|
# Step 2: Uninstall Android app
|
|
if [ "$UNINSTALL" = true ]; then
|
|
log_info "Uninstall: uninstalling app from device"
|
|
safe_execute "Uninstalling Android app" "./scripts/uninstall-android.sh" || exit 1
|
|
log_success "Uninstall completed successfully!"
|
|
exit 0
|
|
fi
|
|
|
|
# Step 3: Clean dist directory
|
|
log_info "Cleaning dist directory..."
|
|
clean_build_artifacts "dist"
|
|
|
|
# Step 4: Run TypeScript type checking for test and production builds
|
|
if [ "$BUILD_MODE" = "production" ] || [ "$BUILD_MODE" = "test" ]; then
|
|
log_info "Running TypeScript type checking for $BUILD_MODE mode..."
|
|
|
|
if ! measure_time npm run type-check; then
|
|
log_error "TypeScript type checking failed for $BUILD_MODE mode!"
|
|
exit 2
|
|
fi
|
|
|
|
log_success "TypeScript type checking completed for $BUILD_MODE mode"
|
|
else
|
|
log_debug "Skipping TypeScript type checking for development mode"
|
|
fi
|
|
|
|
# Step 5: Build Capacitor version with mode
|
|
if [ "$BUILD_MODE" = "development" ]; then
|
|
safe_execute "Building Capacitor version (development)" "npm run build:capacitor" || exit 3
|
|
elif [ "$BUILD_MODE" = "test" ]; then
|
|
safe_execute "Building Capacitor version (test)" "npm run build:capacitor -- --mode test" || exit 3
|
|
elif [ "$BUILD_MODE" = "production" ]; then
|
|
safe_execute "Building Capacitor version (production)" "npm run build:capacitor -- --mode production" || exit 3
|
|
fi
|
|
|
|
# Step 6: Clean Gradle build
|
|
safe_execute "Cleaning Gradle build" "cd android && ./gradlew clean && cd .." || exit 4
|
|
|
|
# Step 7: Build based on type
|
|
if [ "$BUILD_TYPE" = "debug" ]; then
|
|
safe_execute "Assembling debug build" "cd android && ./gradlew assembleDebug && cd .." || exit 5
|
|
elif [ "$BUILD_TYPE" = "release" ]; then
|
|
safe_execute "Assembling release build" "cd android && ./gradlew assembleRelease && cd .." || exit 5
|
|
fi
|
|
|
|
# Step 8: Sync with Capacitor
|
|
safe_execute "Syncing with Capacitor" "npx cap sync android" || exit 6
|
|
|
|
# Step 8.5: Restore local plugins (capacitor.plugins.json gets overwritten by cap sync)
|
|
safe_execute "Restoring local plugins" "node scripts/restore-local-plugins.js" || exit 7
|
|
|
|
# Step 9: Generate assets
|
|
safe_execute "Generating assets" "npx capacitor-assets generate --android" || exit 7
|
|
|
|
# Step 10: Build APK/AAB if requested
|
|
if [ "$BUILD_APK" = true ]; then
|
|
if [ "$BUILD_TYPE" = "debug" ]; then
|
|
safe_execute "Building debug APK" "cd android && ./gradlew assembleDebug && cd .." || exit 5
|
|
else
|
|
safe_execute "Building release APK" "cd android && ./gradlew assembleRelease && cd .." || exit 5
|
|
fi
|
|
fi
|
|
|
|
if [ "$BUILD_AAB" = true ]; then
|
|
safe_execute "Building AAB" "cd android && ./gradlew bundleRelease && cd .." || exit 5
|
|
fi
|
|
|
|
# Step 11: Auto-run app if requested
|
|
# cap run runs sync by default, which would overwrite capacitor.plugins.json again;
|
|
# we already synced and ran restore-local-plugins.js above, so skip sync here.
|
|
if [ "$AUTO_RUN" = true ]; then
|
|
log_step "Auto-running Android app..."
|
|
safe_execute "Launching app" "npx cap run android --no-sync" || {
|
|
log_error "Failed to launch Android app"
|
|
log_info "You can manually run with: npx cap run android --no-sync"
|
|
exit 9
|
|
}
|
|
log_success "Android app launched successfully!"
|
|
fi
|
|
|
|
# Step 12: Open Android Studio if requested
|
|
if [ "$OPEN_STUDIO" = true ]; then
|
|
safe_execute "Opening Android Studio" "npx cap open android" || exit 8
|
|
fi
|
|
|
|
# Print build summary
|
|
log_success "Android build completed successfully!"
|
|
log_info "Build mode: $BUILD_MODE"
|
|
log_info "Build type: $BUILD_TYPE"
|
|
if [ "$BUILD_APK" = true ]; then
|
|
log_info "APK build: completed"
|
|
fi
|
|
if [ "$BUILD_AAB" = true ]; then
|
|
log_info "AAB build: completed"
|
|
fi
|
|
if [ "$AUTO_RUN" = true ]; then
|
|
log_info "Auto-run: completed"
|
|
fi
|
|
if [ "$OPEN_STUDIO" = true ]; then
|
|
log_info "Android Studio: opened"
|
|
fi
|
|
|
|
# Reminder about dependency management
|
|
log_info "💡 Tip: If you encounter dependency issues, run 'npm install' to ensure all packages are up to date."
|
|
|
|
print_footer "Android Build"
|
|
|
|
# Exit with success
|
|
exit 0 |