#!/usr/bin/env bash # capacitor_build_apk # ------------------- # Pipeline que convierte una web app buildeada en un APK de Android usando Capacitor. # Asume que el Android SDK está instalado (via install_android_sdk o manualmente). # # USO: # ./capacitor_build_apk.sh [--app-id com.example.app] [--app-name "My App"] # # ARGUMENTOS: # web_app_dir Directorio de la web app (debe contener package.json) # --app-id ID de la app Android (default: com.fnregistry.app) # --app-name Nombre visible de la app (default: name de package.json) # # REQUISITOS: # - Node.js + pnpm instalados en PATH # - Java 17+ instalado en PATH # - Android SDK: ANDROID_HOME seteado o $HOME/android-sdk/env.sh disponible set -euo pipefail # --------------------------------------------------------------------------- # Parseo de argumentos # --------------------------------------------------------------------------- WEB_APP_DIR="" APP_ID="com.fnregistry.app" APP_NAME="" while [[ $# -gt 0 ]]; do case "$1" in --app-id) APP_ID="$2" shift 2 ;; --app-name) APP_NAME="$2" shift 2 ;; -*) echo "[capacitor_build_apk] ERROR: argumento desconocido: $1" >&2 echo "USO: $0 [--app-id com.example.app] [--app-name \"My App\"]" >&2 exit 1 ;; *) WEB_APP_DIR="$1" shift ;; esac done if [[ -z "$WEB_APP_DIR" ]]; then echo "[capacitor_build_apk] ERROR: web_app_dir es obligatorio." >&2 echo "USO: $0 [--app-id com.example.app] [--app-name \"My App\"]" >&2 exit 1 fi # --------------------------------------------------------------------------- # 1. Validación # --------------------------------------------------------------------------- echo "[capacitor_build_apk] Validando entorno..." # Verificar que web_app_dir existe y tiene package.json if [[ ! -d "$WEB_APP_DIR" ]]; then echo "[capacitor_build_apk] ERROR: directorio no existe: $WEB_APP_DIR" >&2 exit 1 fi if [[ ! -f "$WEB_APP_DIR/package.json" ]]; then echo "[capacitor_build_apk] ERROR: no se encontró package.json en $WEB_APP_DIR" >&2 exit 1 fi # Resolver app name desde package.json si no se pasó if [[ -z "$APP_NAME" ]]; then APP_NAME=$(node -e "const p = require('$WEB_APP_DIR/package.json'); process.stdout.write(p.name || 'app');" 2>/dev/null || echo "app") echo "[capacitor_build_apk] App name detectado desde package.json: $APP_NAME" fi # Verificar ANDROID_HOME o sourcea env.sh if [[ -z "${ANDROID_HOME:-}" ]]; then ANDROID_ENV="$HOME/android-sdk/env.sh" if [[ -f "$ANDROID_ENV" ]]; then echo "[capacitor_build_apk] ANDROID_HOME no seteado, sourceando $ANDROID_ENV ..." # shellcheck source=/dev/null source "$ANDROID_ENV" else echo "[capacitor_build_apk] ERROR: ANDROID_HOME no está seteado y no se encontró $ANDROID_ENV" >&2 echo " Instala el SDK con install_android_sdk o setea ANDROID_HOME manualmente." >&2 exit 1 fi fi echo "[capacitor_build_apk] ANDROID_HOME: $ANDROID_HOME" # Verificar Java 17+ if ! command -v java &>/dev/null; then echo "[capacitor_build_apk] ERROR: java no está en PATH." >&2 exit 1 fi JAVA_VERSION=$(java -version 2>&1 | head -1 | grep -oP '(?<=version ")([0-9]+)' | head -1 || echo "0") if [[ "$JAVA_VERSION" -lt 17 ]]; then echo "[capacitor_build_apk] ERROR: se requiere Java 17+. Versión detectada: $JAVA_VERSION" >&2 exit 1 fi echo "[capacitor_build_apk] Java $JAVA_VERSION detectado." # --------------------------------------------------------------------------- # 2. Build web (si no existe dist/) # --------------------------------------------------------------------------- if [[ ! -d "$WEB_APP_DIR/dist" ]]; then echo "[capacitor_build_apk] No se encontró dist/, ejecutando pnpm build..." (cd "$WEB_APP_DIR" && pnpm build) echo "[capacitor_build_apk] Build web completado." else echo "[capacitor_build_apk] dist/ ya existe, omitiendo build web." fi # --------------------------------------------------------------------------- # 3. Init Capacitor (si no existe capacitor.config.ts) # --------------------------------------------------------------------------- if [[ ! -f "$WEB_APP_DIR/capacitor.config.ts" ]]; then echo "[capacitor_build_apk] Instalando dependencias de Capacitor..." (cd "$WEB_APP_DIR" && npm install @capacitor/core @capacitor/cli @capacitor/android) echo "[capacitor_build_apk] Generando capacitor.config.ts..." cat > "$WEB_APP_DIR/capacitor.config.ts" <&2 exit 1 fi APK_SOURCE="$WEB_APP_DIR/android/app/build/outputs/apk/debug/app-debug.apk" if [[ ! -f "$APK_SOURCE" ]]; then echo "[capacitor_build_apk] ERROR: Gradle terminó sin error pero no se encontró el APK en $APK_SOURCE" >&2 exit 1 fi # --------------------------------------------------------------------------- # 7. Copia APK al directorio raíz # --------------------------------------------------------------------------- APK_DEST="$WEB_APP_DIR/${APP_NAME}.apk" cp "$APK_SOURCE" "$APK_DEST" # --------------------------------------------------------------------------- # 8. Resultado # --------------------------------------------------------------------------- APK_SIZE_BYTES=$(stat -c%s "$APK_DEST" 2>/dev/null || stat -f%z "$APK_DEST" 2>/dev/null || echo "0") APK_SIZE_MB=$(awk "BEGIN {printf \"%.1f\", $APK_SIZE_BYTES/1048576}") echo "" echo "---------------------------------------------------------------------" echo "APK generado: $APK_DEST" echo "Tamaño: ${APK_SIZE_MB} MB" echo "" echo "Para instalar en un dispositivo conectado por USB:" echo " adb install '$APK_DEST'" echo "---------------------------------------------------------------------"