diff --git a/src/sdk/android.rs b/src/sdk/android.rs index 6273a00..596ed74 100644 --- a/src/sdk/android.rs +++ b/src/sdk/android.rs @@ -1,4 +1,4 @@ -use std::path::{Path, PathBuf}; +use std::path::Path; use anyhow::{Result, Context}; use indicatif::{ProgressBar, ProgressStyle}; use reqwest::blocking::Client; @@ -72,35 +72,35 @@ pub fn install(sdk_path: &Path) -> Result<()> { let mut archive = zip::ZipArchive::new(file)?; std::fs::create_dir_all(sdk_path)?; - archive.extract(sdk_path)?; + archive.extract(sdk_path) + .context("Failed to extract Android SDK")?; // Cleanup std::fs::remove_file(&temp_zip)?; // The zip extracts to cmdline-tools/ but we need it in cmdline-tools/latest/ - // This is required by the Android SDK structure let extracted_tools = sdk_path.join("cmdline-tools"); let target_location = sdk_path.join("cmdline-tools").join("latest"); if extracted_tools.exists() && !target_location.exists() { println!("Reorganizing cmdline-tools directory structure..."); - // Create a temporary directory to hold the contents let temp_dir = sdk_path.join("cmdline-tools-temp"); - std::fs::rename(&extracted_tools, &temp_dir)?; + std::fs::rename(&extracted_tools, &temp_dir) + .context("Failed to rename cmdline-tools to temp directory")?; - // Create the proper structure - std::fs::create_dir_all(&target_location)?; + std::fs::create_dir_all(&target_location) + .context("Failed to create cmdline-tools/latest directory")?; - // Move everything from temp into latest/ for entry in std::fs::read_dir(&temp_dir)? { let entry = entry?; let dest = target_location.join(entry.file_name()); - std::fs::rename(entry.path(), dest)?; + std::fs::rename(entry.path(), dest) + .with_context(|| format!("Failed to move {} to latest/", entry.file_name().to_string_lossy()))?; } - // Remove temp directory - std::fs::remove_dir_all(&temp_dir)?; + std::fs::remove_dir_all(&temp_dir) + .context("Failed to remove temporary directory")?; } // Install required packages @@ -114,7 +114,6 @@ pub fn install(sdk_path: &Path) -> Result<()> { fn install_packages(sdk_path: &Path) -> Result<()> { println!("Installing Android SDK packages..."); - // Find sdkmanager in the expected location let sdkmanager_path = sdk_path.join("cmdline-tools").join("latest").join("bin"); let sdkmanager = if cfg!(target_os = "windows") { @@ -142,36 +141,59 @@ fn run_sdkmanager(sdkmanager: &Path, sdk_root: &Path) -> Result<()> { println!("Accepting licenses..."); - // Accept licenses - let mut license_cmd = Command::new(sdkmanager) - .arg(format!("--sdk_root={}", sdk_root.display())) + // Build command based on OS + let mut cmd = if cfg!(target_os = "windows") { + let mut c = Command::new("cmd"); + c.arg("/c"); + c.arg(sdkmanager); + c + } else { + Command::new(sdkmanager) + }; + + cmd.arg(format!("--sdk_root={}", sdk_root.display())) .arg("--licenses") .stdin(Stdio::piped()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .spawn() + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); + + let mut child = cmd.spawn() .context("Failed to spawn sdkmanager for licenses")?; // Write 'y' responses to accept all licenses - if let Some(mut stdin) = license_cmd.stdin.take() { - // Write enough 'y\n' to accept all licenses (usually 5-6 licenses) - for _ in 0..10 { - let _ = stdin.write_all(b"y\n"); - } - drop(stdin); // Close stdin so sdkmanager knows we're done + if let Some(mut stdin) = child.stdin.take() { + // Create a string with many 'y' responses + let responses = "y\n".repeat(20); + stdin.write_all(responses.as_bytes()) + .context("Failed to write license responses")?; + // Explicitly drop stdin to close the pipe + drop(stdin); } - let status = license_cmd.wait() + let output = child.wait_with_output() .context("Failed to wait for license acceptance")?; - if !status.success() { + if !output.status.success() { + eprintln!("License stderr: {}", String::from_utf8_lossy(&output.stderr)); + eprintln!("License stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("{} License acceptance may have failed, continuing anyway...", "⚠".yellow()); + } else { + println!("{} Licenses accepted", "✓".green()); } println!("Installing SDK packages (this may take a few minutes)..."); - // Install packages - let status = Command::new(sdkmanager) + // Build command for package installation + let mut cmd = if cfg!(target_os = "windows") { + let mut c = Command::new("cmd"); + c.arg("/c"); + c.arg(sdkmanager); + c + } else { + Command::new(sdkmanager) + }; + + let status = cmd .arg(format!("--sdk_root={}", sdk_root.display())) .arg("platform-tools") .arg("platforms;android-34")