Initial React Native Android project setup with multiplatform desktop support.
Added React Native project structure with Android configuration, Tauri desktop app support, and build artifacts. Includes development tools, test configuration, and platform-specific resources. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
694
setup_android.py
Normal file
694
setup_android.py
Normal file
@@ -0,0 +1,694 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Android Development Environment Setup Script for Windows
|
||||
MyMemoApp - Full Android Development Environment Setup
|
||||
Date: 2025-09-14
|
||||
Run with Administrator privileges
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import shutil
|
||||
import zipfile
|
||||
import urllib.request
|
||||
import winreg
|
||||
import ctypes
|
||||
from pathlib import Path
|
||||
import json
|
||||
import time
|
||||
|
||||
# Configuration
|
||||
JAVA_VERSION = "17"
|
||||
GRADLE_VERSION = "9.0.0"
|
||||
ANDROID_SDK_VERSION = "13114758"
|
||||
ANDROID_API_LEVEL = "34"
|
||||
BUILD_TOOLS_VERSION = "34.0.0"
|
||||
NDK_VERSIONS = ["25.1.8937393", "27.1.12297006"]
|
||||
CMAKE_VERSIONS = ["3.22.1", "3.18.1"]
|
||||
|
||||
# Paths
|
||||
JAVA_INSTALL_PATH = r"C:\Program Files\Java"
|
||||
GRADLE_INSTALL_PATH = r"C:\Gradle"
|
||||
ANDROID_SDK_PATH = r"C:\Android\sdk"
|
||||
TEMP_DIR = Path(os.environ['TEMP']) / "android-setup"
|
||||
|
||||
# URLs
|
||||
JAVA_17_URL = "https://aka.ms/download-jdk/microsoft-jdk-17.0.12-windows-x64.msi"
|
||||
JAVA_21_URL = "https://aka.ms/download-jdk/microsoft-jdk-21.0.4-windows-x64.msi"
|
||||
GRADLE_URL = f"https://services.gradle.org/distributions/gradle-{GRADLE_VERSION}-bin.zip"
|
||||
ANDROID_SDK_URL = f"https://dl.google.com/android/repository/commandlinetools-win-{ANDROID_SDK_VERSION}_latest.zip"
|
||||
|
||||
class AndroidSetup:
|
||||
def __init__(self):
|
||||
self.errors = []
|
||||
self.warnings = []
|
||||
|
||||
def print_header(self, text):
|
||||
"""Print section header"""
|
||||
print("\n" + "="*60)
|
||||
print(f" {text}")
|
||||
print("="*60)
|
||||
|
||||
def print_step(self, step_num, text):
|
||||
"""Print step information"""
|
||||
print(f"\n[Step {step_num}] {text}")
|
||||
print("-" * 50)
|
||||
|
||||
def is_admin(self):
|
||||
"""Check if running with administrator privileges"""
|
||||
try:
|
||||
return ctypes.windll.shell32.IsUserAnAdmin()
|
||||
except:
|
||||
return False
|
||||
|
||||
def run_command(self, cmd, shell=True, capture_output=True):
|
||||
"""Run a command and return result"""
|
||||
try:
|
||||
# On Windows, use shell=True for better command resolution
|
||||
if isinstance(cmd, list):
|
||||
cmd = ' '.join(cmd)
|
||||
result = subprocess.run(cmd, shell=shell, capture_output=capture_output, text=True)
|
||||
return result.returncode == 0, result.stdout, result.stderr
|
||||
except Exception as e:
|
||||
return False, "", str(e)
|
||||
|
||||
def download_file(self, url, destination, description=""):
|
||||
"""Download file with progress indicator"""
|
||||
print(f"Downloading {description}...")
|
||||
print(f"URL: {url}")
|
||||
|
||||
try:
|
||||
def download_progress(block_num, block_size, total_size):
|
||||
downloaded = block_num * block_size
|
||||
percent = min(downloaded * 100 / total_size, 100)
|
||||
progress_bar = '#' * int(percent // 2)
|
||||
sys.stdout.write(f'\r[{progress_bar:<50}] {percent:.1f}%')
|
||||
sys.stdout.flush()
|
||||
|
||||
urllib.request.urlretrieve(url, destination, reporthook=download_progress)
|
||||
print() # New line after progress bar
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"\nDownload failed: {e}")
|
||||
return False
|
||||
|
||||
def extract_zip(self, zip_path, extract_to):
|
||||
"""Extract zip file"""
|
||||
print(f"Extracting {zip_path.name}...")
|
||||
try:
|
||||
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
||||
zip_ref.extractall(extract_to)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Extraction failed: {e}")
|
||||
return False
|
||||
|
||||
def set_environment_variable(self, name, value, user=False):
|
||||
"""Set Windows environment variable permanently"""
|
||||
try:
|
||||
# First, update current session
|
||||
os.environ[name] = value
|
||||
print(f" Updated {name} in current session")
|
||||
|
||||
success = False
|
||||
|
||||
# Method 1: Direct registry modification
|
||||
try:
|
||||
if user:
|
||||
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
|
||||
r"Environment",
|
||||
0, winreg.KEY_ALL_ACCESS)
|
||||
else:
|
||||
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
|
||||
r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment",
|
||||
0, winreg.KEY_ALL_ACCESS)
|
||||
|
||||
winreg.SetValueEx(key, name, 0, winreg.REG_EXPAND_SZ, value)
|
||||
winreg.CloseKey(key)
|
||||
print(f" ✓ Persisted {name} to system registry")
|
||||
success = True
|
||||
|
||||
# Notify system of environment change (optional)
|
||||
try:
|
||||
import win32gui, win32con
|
||||
win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')
|
||||
except ImportError:
|
||||
# pywin32 not installed, skip notification
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f" Warning: Registry method failed: {e}")
|
||||
|
||||
# Method 2: Use setx as backup
|
||||
if not success:
|
||||
try:
|
||||
# Use setx to set system environment variable
|
||||
cmd = f'setx {name} "{value}" /M'
|
||||
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
if result.returncode == 0:
|
||||
print(f" ✓ Set {name} using setx")
|
||||
success = True
|
||||
else:
|
||||
print(f" Warning: setx failed: {result.stderr}")
|
||||
except Exception as e:
|
||||
print(f" Warning: setx method failed: {e}")
|
||||
|
||||
if not success:
|
||||
print(f" ⚠ {name} will only work for current session")
|
||||
print(f" Please set manually: {name}={value}")
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f" Error: Failed to set {name}: {e}")
|
||||
return False
|
||||
|
||||
def add_to_path(self, new_path, user=False):
|
||||
"""Add directory to PATH environment variable permanently"""
|
||||
try:
|
||||
# First, update current session
|
||||
if new_path not in os.environ['PATH']:
|
||||
os.environ['PATH'] = f"{os.environ['PATH']};{new_path}"
|
||||
print(f" Added to current session PATH: {new_path}")
|
||||
else:
|
||||
print(f" Already in current session PATH: {new_path}")
|
||||
|
||||
# Persist to system PATH using both registry and setx
|
||||
success = False
|
||||
|
||||
# Method 1: Direct registry modification
|
||||
try:
|
||||
if user:
|
||||
key_path = r"Environment"
|
||||
root_key = winreg.HKEY_CURRENT_USER
|
||||
else:
|
||||
key_path = r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
|
||||
root_key = winreg.HKEY_LOCAL_MACHINE
|
||||
|
||||
key = winreg.OpenKey(root_key, key_path, 0, winreg.KEY_ALL_ACCESS)
|
||||
|
||||
try:
|
||||
current_path, reg_type = winreg.QueryValueEx(key, "Path")
|
||||
except:
|
||||
current_path = ""
|
||||
reg_type = winreg.REG_EXPAND_SZ
|
||||
|
||||
if new_path not in current_path:
|
||||
# Clean up the path (remove duplicates and empty entries)
|
||||
path_parts = [p.strip() for p in current_path.split(';') if p.strip()]
|
||||
if new_path not in path_parts:
|
||||
path_parts.append(new_path)
|
||||
new_path_value = ';'.join(path_parts)
|
||||
|
||||
winreg.SetValueEx(key, "Path", 0, reg_type, new_path_value)
|
||||
print(f" ✓ Persisted to system registry PATH")
|
||||
success = True
|
||||
else:
|
||||
print(f" Already in system registry PATH")
|
||||
success = True
|
||||
|
||||
winreg.CloseKey(key)
|
||||
except Exception as e:
|
||||
print(f" Warning: Registry method failed: {e}")
|
||||
|
||||
# Method 2: Use setx as backup (this has 1024 char limit but works well)
|
||||
if not success:
|
||||
try:
|
||||
# Use setx to set system PATH
|
||||
cmd = f'setx PATH "%PATH%;{new_path}" /M'
|
||||
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
if result.returncode == 0:
|
||||
print(f" ✓ Updated system PATH using setx")
|
||||
success = True
|
||||
else:
|
||||
print(f" Warning: setx failed: {result.stderr}")
|
||||
except Exception as e:
|
||||
print(f" Warning: setx method failed: {e}")
|
||||
|
||||
if not success:
|
||||
print(f" ⚠ PATH update will only work for current session")
|
||||
print(f" Please add manually to system PATH: {new_path}")
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f" Error: Failed to update PATH: {e}")
|
||||
return False
|
||||
|
||||
def check_nodejs(self):
|
||||
"""Check Node.js installation"""
|
||||
self.print_step(1, "Checking Node.js and npm")
|
||||
|
||||
# Check Node.js
|
||||
success, stdout, _ = self.run_command("node --version")
|
||||
if success:
|
||||
print(f"✓ Node.js installed: {stdout.strip()}")
|
||||
else:
|
||||
print("✗ Node.js not installed")
|
||||
print("Please download and install from: https://nodejs.org/")
|
||||
return False
|
||||
|
||||
# Check npm - try different approaches
|
||||
npm_found = False
|
||||
npm_version = ""
|
||||
|
||||
# Try 1: Direct npm command
|
||||
success, stdout, _ = self.run_command("npm --version")
|
||||
if success:
|
||||
npm_found = True
|
||||
npm_version = stdout.strip()
|
||||
else:
|
||||
# Try 2: Use cmd /c for Windows
|
||||
success, stdout, _ = self.run_command("cmd /c npm --version")
|
||||
if success:
|
||||
npm_found = True
|
||||
npm_version = stdout.strip()
|
||||
else:
|
||||
# Try 3: Use full path if Node.js is in Program Files
|
||||
node_path = shutil.which('node')
|
||||
if node_path:
|
||||
npm_path = Path(node_path).parent / "npm.cmd"
|
||||
if npm_path.exists():
|
||||
success, stdout, _ = self.run_command(f'"{npm_path}" --version')
|
||||
if success:
|
||||
npm_found = True
|
||||
npm_version = stdout.strip()
|
||||
|
||||
if npm_found:
|
||||
print(f"✓ npm installed: {npm_version}")
|
||||
return True
|
||||
else:
|
||||
print("✗ npm not found")
|
||||
print("Note: npm should be installed with Node.js")
|
||||
print("Try running 'npm --version' manually to verify")
|
||||
response = input("\nContinue anyway? (y/n): ")
|
||||
return response.lower() == 'y'
|
||||
|
||||
def check_java(self):
|
||||
"""Check and install Java if needed"""
|
||||
self.print_step(2, "Checking Java")
|
||||
|
||||
success, stdout, _ = self.run_command("java --version")
|
||||
if success:
|
||||
print(f"✓ Java installed:\n{stdout}")
|
||||
|
||||
# Set JAVA_HOME if not set
|
||||
if not os.environ.get('JAVA_HOME'):
|
||||
# Try to find Java installation
|
||||
java_path = shutil.which('java')
|
||||
if java_path:
|
||||
java_home = Path(java_path).parent.parent
|
||||
self.set_environment_variable('JAVA_HOME', str(java_home))
|
||||
print(f"✓ JAVA_HOME set to: {java_home}")
|
||||
else:
|
||||
print(f"✓ JAVA_HOME: {os.environ['JAVA_HOME']}")
|
||||
return True
|
||||
|
||||
print("Java not found. Installing...")
|
||||
|
||||
# Create temp directory
|
||||
TEMP_DIR.mkdir(exist_ok=True)
|
||||
os.chdir(TEMP_DIR)
|
||||
|
||||
# Download Java
|
||||
java_msi = TEMP_DIR / "openjdk-17.msi"
|
||||
if not java_msi.exists():
|
||||
if not self.download_file(JAVA_17_URL, java_msi, "OpenJDK 17"):
|
||||
# Try Java 21 as fallback
|
||||
java_msi = TEMP_DIR / "openjdk-21.msi"
|
||||
if not self.download_file(JAVA_21_URL, java_msi, "OpenJDK 21"):
|
||||
self.errors.append("Failed to download Java")
|
||||
return False
|
||||
|
||||
# Install Java
|
||||
print("Installing Java... (Please complete the installation wizard)")
|
||||
subprocess.run(f'msiexec /i "{java_msi}"', shell=True)
|
||||
|
||||
print("\n⚠ Please complete Java installation manually, then press Enter to continue...")
|
||||
input()
|
||||
|
||||
# Verify installation
|
||||
success, stdout, _ = self.run_command("java --version")
|
||||
if success:
|
||||
print(f"✓ Java installed successfully")
|
||||
return True
|
||||
else:
|
||||
self.warnings.append("Java installation may require system restart")
|
||||
return False
|
||||
|
||||
def install_gradle(self):
|
||||
"""Install Gradle"""
|
||||
self.print_step(3, "Installing Gradle")
|
||||
|
||||
# Check if already installed
|
||||
gradle_exe = Path(GRADLE_INSTALL_PATH) / f"gradle-{GRADLE_VERSION}" / "bin" / "gradle.bat"
|
||||
if gradle_exe.exists():
|
||||
print(f"✓ Gradle already installed at: {gradle_exe.parent.parent}")
|
||||
self.add_to_path(str(gradle_exe.parent))
|
||||
return True
|
||||
|
||||
success, stdout, _ = self.run_command("gradle --version")
|
||||
if success:
|
||||
print(f"✓ Gradle found in PATH")
|
||||
return True
|
||||
|
||||
print("Installing Gradle...")
|
||||
|
||||
# Create temp directory
|
||||
TEMP_DIR.mkdir(exist_ok=True)
|
||||
os.chdir(TEMP_DIR)
|
||||
|
||||
# Download Gradle
|
||||
gradle_zip = TEMP_DIR / f"gradle-{GRADLE_VERSION}-bin.zip"
|
||||
if not gradle_zip.exists():
|
||||
if not self.download_file(GRADLE_URL, gradle_zip, f"Gradle {GRADLE_VERSION}"):
|
||||
self.errors.append("Failed to download Gradle")
|
||||
return False
|
||||
|
||||
# Extract Gradle
|
||||
if not self.extract_zip(gradle_zip, TEMP_DIR):
|
||||
self.errors.append("Failed to extract Gradle")
|
||||
return False
|
||||
|
||||
# Move to installation directory
|
||||
gradle_src = TEMP_DIR / f"gradle-{GRADLE_VERSION}"
|
||||
gradle_dst = Path(GRADLE_INSTALL_PATH) / f"gradle-{GRADLE_VERSION}"
|
||||
|
||||
print(f"Installing Gradle to {gradle_dst}...")
|
||||
gradle_dst.parent.mkdir(exist_ok=True)
|
||||
|
||||
if gradle_dst.exists():
|
||||
shutil.rmtree(gradle_dst)
|
||||
shutil.move(str(gradle_src), str(gradle_dst))
|
||||
|
||||
# Add to PATH
|
||||
gradle_bin = gradle_dst / "bin"
|
||||
self.add_to_path(str(gradle_bin))
|
||||
|
||||
print(f"✓ Gradle {GRADLE_VERSION} installed successfully")
|
||||
return True
|
||||
|
||||
def install_android_sdk(self):
|
||||
"""Install Android SDK"""
|
||||
self.print_step(4, "Installing Android SDK")
|
||||
|
||||
# Check if already installed
|
||||
sdkmanager = Path(ANDROID_SDK_PATH) / "cmdline-tools" / "latest" / "bin" / "sdkmanager.bat"
|
||||
if sdkmanager.exists():
|
||||
print(f"✓ Android SDK already installed at: {ANDROID_SDK_PATH}")
|
||||
else:
|
||||
print("Installing Android SDK Command Line Tools...")
|
||||
|
||||
# Create temp directory
|
||||
TEMP_DIR.mkdir(exist_ok=True)
|
||||
os.chdir(TEMP_DIR)
|
||||
|
||||
# Download Android SDK
|
||||
sdk_zip = TEMP_DIR / f"commandlinetools-win-{ANDROID_SDK_VERSION}_latest.zip"
|
||||
if not sdk_zip.exists():
|
||||
if not self.download_file(ANDROID_SDK_URL, sdk_zip, "Android SDK Command Line Tools"):
|
||||
self.errors.append("Failed to download Android SDK")
|
||||
return False
|
||||
else:
|
||||
print(f"Using existing SDK zip: {sdk_zip}")
|
||||
|
||||
# Extract SDK
|
||||
if not self.extract_zip(sdk_zip, TEMP_DIR):
|
||||
self.errors.append("Failed to extract Android SDK")
|
||||
return False
|
||||
|
||||
# Setup SDK directory structure
|
||||
print("Setting up SDK directory structure...")
|
||||
sdk_path = Path(ANDROID_SDK_PATH)
|
||||
sdk_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
cmdline_tools = sdk_path / "cmdline-tools" / "latest"
|
||||
cmdline_tools.parent.mkdir(exist_ok=True)
|
||||
|
||||
# Move cmdline-tools
|
||||
print("Moving cmdline-tools to SDK directory...")
|
||||
src_tools = TEMP_DIR / "cmdline-tools"
|
||||
if cmdline_tools.exists():
|
||||
print(f"Removing existing cmdline-tools at {cmdline_tools}")
|
||||
shutil.rmtree(cmdline_tools)
|
||||
shutil.move(str(src_tools), str(cmdline_tools))
|
||||
|
||||
print(f"✓ Android SDK installed to: {ANDROID_SDK_PATH}")
|
||||
|
||||
# Set environment variables
|
||||
print("Setting environment variables...")
|
||||
|
||||
print(" Setting ANDROID_HOME...")
|
||||
if not self.set_environment_variable('ANDROID_HOME', ANDROID_SDK_PATH):
|
||||
self.warnings.append("Failed to set ANDROID_HOME")
|
||||
|
||||
print(" Adding cmdline-tools to PATH...")
|
||||
if not self.add_to_path(str(Path(ANDROID_SDK_PATH) / "cmdline-tools" / "latest" / "bin")):
|
||||
self.warnings.append("Failed to add cmdline-tools to PATH")
|
||||
|
||||
print(" Adding platform-tools to PATH...")
|
||||
if not self.add_to_path(str(Path(ANDROID_SDK_PATH) / "platform-tools")):
|
||||
self.warnings.append("Failed to add platform-tools to PATH")
|
||||
|
||||
print("✓ Environment variables configured")
|
||||
return True
|
||||
|
||||
def install_sdk_components(self):
|
||||
"""Install Android SDK components"""
|
||||
self.print_step(5, "Installing Android SDK Components")
|
||||
|
||||
sdkmanager = Path(ANDROID_SDK_PATH) / "cmdline-tools" / "latest" / "bin" / "sdkmanager.bat"
|
||||
|
||||
if not sdkmanager.exists():
|
||||
print("✗ sdkmanager not found")
|
||||
return False
|
||||
|
||||
# Accept licenses
|
||||
print("Accepting Android SDK licenses...")
|
||||
license_cmd = f'echo y | "{sdkmanager}" --licenses'
|
||||
subprocess.run(license_cmd, shell=True, capture_output=True)
|
||||
|
||||
# Install platform-tools first (contains adb)
|
||||
print("Installing platform-tools (contains adb)...")
|
||||
cmd = f'"{sdkmanager}" "platform-tools"'
|
||||
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
if result.returncode == 0:
|
||||
print("✓ platform-tools installed")
|
||||
|
||||
# Add adb to PATH immediately after platform-tools installation
|
||||
platform_tools_path = Path(ANDROID_SDK_PATH) / "platform-tools"
|
||||
if platform_tools_path.exists():
|
||||
print("Adding adb (platform-tools) to PATH...")
|
||||
self.add_to_path(str(platform_tools_path))
|
||||
|
||||
# Verify adb is accessible
|
||||
adb_path = platform_tools_path / "adb.exe"
|
||||
if adb_path.exists():
|
||||
print(f"✓ adb found at: {adb_path}")
|
||||
else:
|
||||
print("⚠ adb.exe not found in platform-tools")
|
||||
else:
|
||||
print(f"⚠ Failed to install platform-tools: {result.stderr}")
|
||||
|
||||
# Install other components
|
||||
components = [
|
||||
f"platforms;android-{ANDROID_API_LEVEL}",
|
||||
f"platforms;android-35",
|
||||
f"platforms;android-33",
|
||||
f"build-tools;{BUILD_TOOLS_VERSION}",
|
||||
f"build-tools;35.0.0"
|
||||
]
|
||||
|
||||
for component in components:
|
||||
print(f"Installing {component}...")
|
||||
cmd = f'"{sdkmanager}" "{component}"'
|
||||
subprocess.run(cmd, shell=True, capture_output=True)
|
||||
|
||||
# Install NDK
|
||||
for ndk_version in NDK_VERSIONS:
|
||||
print(f"Installing NDK {ndk_version}...")
|
||||
cmd = f'"{sdkmanager}" "ndk;{ndk_version}"'
|
||||
subprocess.run(cmd, shell=True, capture_output=True)
|
||||
|
||||
# Install CMake
|
||||
for cmake_version in CMAKE_VERSIONS:
|
||||
print(f"Installing CMake {cmake_version}...")
|
||||
cmd = f'"{sdkmanager}" "cmake;{cmake_version}"'
|
||||
subprocess.run(cmd, shell=True, capture_output=True)
|
||||
|
||||
print("✓ Android SDK components installed")
|
||||
return True
|
||||
|
||||
def create_local_properties(self):
|
||||
"""Create local.properties files"""
|
||||
self.print_step(6, "Creating local.properties files")
|
||||
|
||||
ndk_path = Path(ANDROID_SDK_PATH) / "ndk" / NDK_VERSIONS[-1]
|
||||
|
||||
# Create for platforms/android
|
||||
android_dir = Path.cwd() / "platforms" / "android"
|
||||
if android_dir.exists():
|
||||
local_props = android_dir / "local.properties"
|
||||
content = f"""# Android SDK path
|
||||
sdk.dir={ANDROID_SDK_PATH.replace(chr(92), '/')}
|
||||
|
||||
# NDK path
|
||||
ndk.dir={str(ndk_path).replace(chr(92), '/')}
|
||||
"""
|
||||
local_props.write_text(content)
|
||||
print(f"✓ Created: {local_props}")
|
||||
|
||||
# Create for TestApp/android if exists
|
||||
testapp_dir = Path.cwd() / "TestApp" / "android"
|
||||
if testapp_dir.exists():
|
||||
local_props = testapp_dir / "local.properties"
|
||||
local_props.write_text(content)
|
||||
print(f"✓ Created: {local_props}")
|
||||
|
||||
return True
|
||||
|
||||
def create_gradle_properties(self):
|
||||
"""Create gradle.properties file"""
|
||||
self.print_step(7, "Creating gradle.properties")
|
||||
|
||||
android_dir = Path.cwd() / "platforms" / "android"
|
||||
if android_dir.exists():
|
||||
gradle_props = android_dir / "gradle.properties"
|
||||
content = """# Gradle settings
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
org.gradle.parallel=true
|
||||
org.gradle.daemon=true
|
||||
org.gradle.configureondemand=true
|
||||
|
||||
# Android settings
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
# React Native settings
|
||||
reactNativeArchitectures=armeabi-v7a,arm64-v8a
|
||||
|
||||
# Build optimization
|
||||
org.gradle.caching=true
|
||||
"""
|
||||
gradle_props.write_text(content)
|
||||
print(f"✓ Created: {gradle_props}")
|
||||
|
||||
return True
|
||||
|
||||
def verify_installation(self):
|
||||
"""Verify all installations"""
|
||||
self.print_step(8, "Verifying Installation")
|
||||
|
||||
checks = [
|
||||
("Java", "java --version"),
|
||||
("Gradle", "gradle --version"),
|
||||
("ADB", "adb --version"),
|
||||
]
|
||||
|
||||
all_good = True
|
||||
for name, cmd in checks:
|
||||
success, stdout, _ = self.run_command(cmd)
|
||||
if success:
|
||||
print(f"✓ {name}: OK")
|
||||
if name == "ADB":
|
||||
# Show adb version
|
||||
print(f" {stdout.strip().split()[0]}")
|
||||
else:
|
||||
if name == "ADB":
|
||||
# Try with full path
|
||||
adb_path = Path(ANDROID_SDK_PATH) / "platform-tools" / "adb.exe"
|
||||
if adb_path.exists():
|
||||
print(f"✓ {name}: Found at {adb_path}")
|
||||
print(f" (Add {adb_path.parent} to PATH manually or restart)")
|
||||
self.warnings.append("adb found but not in PATH - restart required")
|
||||
else:
|
||||
print(f"✗ {name}: Not found")
|
||||
self.warnings.append(f"{name} not installed")
|
||||
all_good = False
|
||||
else:
|
||||
print(f"✗ {name}: Not found (may need restart)")
|
||||
self.warnings.append(f"{name} verification failed - may need system restart")
|
||||
all_good = False
|
||||
|
||||
# Also check ANDROID_HOME
|
||||
android_home = os.environ.get('ANDROID_HOME')
|
||||
if android_home:
|
||||
print(f"✓ ANDROID_HOME: {android_home}")
|
||||
else:
|
||||
print("✗ ANDROID_HOME: Not set")
|
||||
self.warnings.append("ANDROID_HOME not set - restart required")
|
||||
|
||||
return all_good
|
||||
|
||||
def run(self):
|
||||
"""Main setup process"""
|
||||
self.print_header("Android Development Environment Setup")
|
||||
|
||||
# Check admin privileges
|
||||
if not self.is_admin():
|
||||
print("\n⚠ WARNING: Not running as administrator!")
|
||||
print("Some operations may fail. Run as administrator for best results.")
|
||||
response = input("\nContinue anyway? (y/n): ")
|
||||
if response.lower() != 'y':
|
||||
return
|
||||
|
||||
# Check Node.js
|
||||
if not self.check_nodejs():
|
||||
self.errors.append("Node.js is required. Please install it first.")
|
||||
return
|
||||
|
||||
# Check/Install Java
|
||||
if not self.check_java():
|
||||
self.warnings.append("Java installation incomplete")
|
||||
|
||||
# Install Gradle
|
||||
if not self.install_gradle():
|
||||
self.warnings.append("Gradle installation incomplete")
|
||||
|
||||
# Install Android SDK
|
||||
if not self.install_android_sdk():
|
||||
self.errors.append("Android SDK installation failed")
|
||||
return
|
||||
|
||||
# Install SDK components
|
||||
if not self.install_sdk_components():
|
||||
self.warnings.append("Some SDK components may not be installed")
|
||||
|
||||
# Create configuration files
|
||||
os.chdir(Path(__file__).parent) # Return to script directory
|
||||
self.create_local_properties()
|
||||
self.create_gradle_properties()
|
||||
|
||||
# Verify installation
|
||||
self.verify_installation()
|
||||
|
||||
# Print summary
|
||||
self.print_header("Setup Complete!")
|
||||
|
||||
if self.errors:
|
||||
print("\n❌ Errors:")
|
||||
for error in self.errors:
|
||||
print(f" - {error}")
|
||||
|
||||
if self.warnings:
|
||||
print("\n⚠ Warnings:")
|
||||
for warning in self.warnings:
|
||||
print(f" - {warning}")
|
||||
|
||||
print("\n✅ Next Steps:")
|
||||
print("1. Restart your command prompt or system")
|
||||
print("2. Run: npm install")
|
||||
print("3. Run: npm run android")
|
||||
print("\nFor troubleshooting, run: npx react-native doctor")
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
setup = AndroidSetup()
|
||||
setup.run()
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nSetup cancelled by user")
|
||||
except Exception as e:
|
||||
print(f"\n❌ Setup failed: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
input("\nPress Enter to exit...")
|
||||
Reference in New Issue
Block a user