#!/usr/bin/env bash # # Ubuntu (22.04+) setup for this React Native 0.81 / Android build (headless or desktop). # Run: bash scripts/setup-ubuntu.sh # or: bash scripts/setup-ubuntu.sh --skip-android # if ANDROID_HOME is already set up # Fix "SDK location not found" on an existing box: bash scripts/write-android-local-properties.sh # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" # Match android/build.gradle (update here if the project changes) COMPILE_SDK_VERSION=36 BUILD_TOOLS_VERSION="36.0.0" NDK_VERSION="27.1.12297006" CMAKE_VERSION="3.22.1" # Android command-line tools (update periodically): https://developer.android.com/studio#command-line-tools-only CMDLINE_TOOLS_ZIP_URL="${CMDLINE_TOOLS_ZIP_URL:-https://dl.google.com/android/repository/commandlinetools-linux-12266719_latest.zip}" # Node: use 20 LTS (compatible with RN 0.81). Override: NODE_VERSION=22 bash ... NODE_VERSION="${NODE_VERSION:-20}" ANDROID_HOME_DEFAULT="${HOME}/Android/Sdk" ANDROID_HOME="${ANDROID_HOME:-$ANDROID_HOME_DEFAULT}" SKIP_ANDROID=false INSTALL_NVM=true for arg in "$@"; do case "$arg" in --skip-android) SKIP_ANDROID=true ;; --no-nvm) INSTALL_NVM=false ;; -h|--help) echo "Usage: $0 [--skip-android] [--no-nvm]" echo " Env: ANDROID_HOME (default: $ANDROID_HOME_DEFAULT), NODE_VERSION (default: $NODE_VERSION), CMDLINE_TOOLS_ZIP_URL" exit 0 ;; esac done echo "==> Installing apt packages (needs sudo)..." sudo apt-get update sudo apt-get install -y \ openjdk-17-jdk \ build-essential \ git \ curl \ unzip \ libssl-dev \ pkg-config \ ca-certificates # Watchman (Metro file watching). Optional; skip if the package is missing on your release. if apt-cache show watchman &>/dev/null; then sudo apt-get install -y watchman || true else echo " (Optional) Install watchman from source or use Metro polling if needed." fi if [[ "$INSTALL_NVM" == "true" ]]; then echo "==> Installing nvm + Node $NODE_VERSION..." export NVM_DIR="${NVM_DIR:-$HOME/.nvm}" if [[ ! -s "$NVM_DIR/nvm.sh" ]]; then curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash fi # shellcheck source=/dev/null source "$NVM_DIR/nvm.sh" nvm install "$NODE_VERSION" nvm use "$NODE_VERSION" nvm alias default "$NODE_VERSION" node -v corepack enable 2>/dev/null || true else echo "==> Skipping nvm (--no-nvm). Ensure Node 18+ is on PATH." fi if [[ "$SKIP_ANDROID" == "true" ]]; then echo "==> Skipping Android SDK (--skip-android). Set ANDROID_HOME and ensure SDK/NDK match the project." echo " Required: platforms;android-$COMPILE_SDK_VERSION, build-tools;$BUILD_TOOLS_VERSION, ndk;$NDK_VERSION, cmake;$CMAKE_VERSION" if [[ -n "${ANDROID_HOME:-}" && -d "${ANDROID_HOME}" ]]; then bash "$SCRIPT_DIR/write-android-local-properties.sh" else echo " After setting ANDROID_HOME, run: bash $SCRIPT_DIR/write-android-local-properties.sh" fi exit 0 fi echo "==> Installing Android SDK to $ANDROID_HOME..." if [[ -z "${JAVA_HOME:-}" ]]; then if [[ -d /usr/lib/jvm/java-17-openjdk-amd64 ]]; then export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 else JAVA_17=$(dirname "$(dirname "$(readlink -f "$(command -v java)")")") export JAVA_HOME="$JAVA_17" fi fi echo " JAVA_HOME=$JAVA_HOME" WORKDIR="$(mktemp -d)" TMP_ZIP="${WORKDIR}/android-cmdline-tools.zip" curl -L -f -o "$TMP_ZIP" "$CMDLINE_TOOLS_ZIP_URL" unzip -q -o "$TMP_ZIP" -d "$WORKDIR" # Google zip contains a top-level `cmdline-tools` dir; it must end up as .../cmdline-tools/latest/... if [[ -d "$WORKDIR/cmdline-tools" ]]; then rm -rf "$ANDROID_HOME/cmdline-tools/latest" mkdir -p "$ANDROID_HOME/cmdline-tools" mv "$WORKDIR/cmdline-tools" "$ANDROID_HOME/cmdline-tools/latest" else echo "Error: expected folder cmdline-tools/ inside the downloaded zip. Update CMDLINE_TOOLS_ZIP_URL." rm -rf "$WORKDIR" exit 1 fi rm -rf "$WORKDIR" export PATH="$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools" SDKMGR=("$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager") echo " Accepting licenses..." yes | "${SDKMGR[@]}" --licenses --sdk_root="$ANDROID_HOME" >/dev/null 2>&1 || yes | "${SDKMGR[@]}" --licenses echo " Installing packages (this may take a while)..." "${SDKMGR[@]}" --sdk_root="$ANDROID_HOME" \ "platforms;android-${COMPILE_SDK_VERSION}" \ "build-tools;${BUILD_TOOLS_VERSION}" \ "platform-tools" \ "ndk;${NDK_VERSION}" \ "cmake;${CMAKE_VERSION}" # Gradle requires sdk.dir in android/local.properties (or ANDROID_HOME in every session). if [[ -f "$SCRIPT_DIR/write-android-local-properties.sh" ]]; then export ANDROID_HOME bash "$SCRIPT_DIR/write-android-local-properties.sh" || { echo " (Could not auto-write local.properties; run: bash $SCRIPT_DIR/write-android-local-properties.sh )" } else printf '## This file is machine-specific (not committed).\nsdk.dir=%s\n' "$ANDROID_HOME" > "${REPO_ROOT}/android/local.properties" echo "==> Wrote ${REPO_ROOT}/android/local.properties" fi echo "" echo "==> Shell exports (add to ~/.bashrc or ~/.zshrc):" { echo "" echo "# React Native / Android" echo "export JAVA_HOME=\"${JAVA_HOME}\"" echo "export ANDROID_HOME=\"${ANDROID_HOME}\"" echo "export PATH=\"\$PATH:\$ANDROID_HOME/platform-tools:\$ANDROID_HOME/emulator\"" echo "export PATH=\"\$PATH:\$ANDROID_HOME/cmdline-tools/latest/bin\"" if [[ "$INSTALL_NVM" == "true" ]]; then echo "export NVM_DIR=\"\$HOME/.nvm\"" echo "[ -s \"\$NVM_DIR/nvm.sh\" ] && . \"\$NVM_DIR/nvm.sh\"" fi } echo "" echo "==> Next: open a new shell (or source your rc file), then from the repo:" echo " npm ci # or npm install / yarn / pnpm" echo " cd android && ./gradlew :app:assembleRelease" echo " (If you still see missing codegen/jni, use: ./gradlew :app:assembleRelease --no-configure-on-demand --no-parallel)" echo "" echo "Done. This project needs New Architecture: keep org.gradle.configureondemand=false in android/gradle.properties."