$ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' # Official Windows command-line tools 22.0; checksum from developer.android.com/studio. # Explicit .zip avoids tool-cache's extensionless archive bug on Windows PowerShell. $sdkRoot = Join-Path $env:RUNNER_TEMP 'android-sdk' $archive = Join-Path $env:RUNNER_TEMP 'commandlinetools-win-15859902.zip' $unpack = Join-Path $env:RUNNER_TEMP 'android-tools-extracted' $expected = '90ae805d20434428bffcb699c290860f19bb5f66a67e6b330067e3de801fb04a' Invoke-WebRequest 'https://dl.google.com/android/repository/commandlinetools-win-15859902_latest.zip' -OutFile $archive -UseBasicParsing if ((Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash.ToLowerInvariant() -ne $expected) { throw 'Android command-line tools checksum mismatch' } Expand-Archive -LiteralPath $archive -DestinationPath $unpack $toolsRoot = Join-Path $sdkRoot 'cmdline-tools' New-Item -ItemType Directory -Path $toolsRoot -Force | Out-Null # Both absolute paths are bounded to the runner's fresh temporary directory. $source = [IO.Path]::GetFullPath((Join-Path $unpack 'cmdline-tools')) $destination = [IO.Path]::GetFullPath((Join-Path $toolsRoot 'latest')) $boundary = [IO.Path]::GetFullPath($env:RUNNER_TEMP).TrimEnd('\') + '\' foreach ($candidate in @($source, $destination)) { if (-not $candidate.StartsWith($boundary, [StringComparison]::OrdinalIgnoreCase)) { throw 'SDK extraction path escaped runner temporary directory' } } Move-Item -LiteralPath $source -Destination $destination $env:ANDROID_HOME = $sdkRoot $env:ANDROID_SDK_ROOT = $sdkRoot $manager = Join-Path $destination 'bin\sdkmanager.bat' # Transfer the already accepted workstation license, as documented by Google: # https://developer.android.com/studio/intro/update#download-with-gradle # The self-hosted runner does not reliably forward stdin to sdkmanager prompts. $licenses = Join-Path $sdkRoot 'licenses' New-Item -ItemType Directory -Path $licenses -Force | Out-Null Copy-Item -LiteralPath (Join-Path $PSScriptRoot 'android-licenses\android-sdk-license') -Destination $licenses & $manager "--sdk_root=$sdkRoot" 'platform-tools' 'platforms;android-37.0' 'build-tools;37.0.0' if ($LASTEXITCODE -ne 0) { throw 'Android SDK installation failed' } foreach ($required in @('platforms\android-37.0\android.jar', 'build-tools\37.0.0\aapt2.exe', 'licenses\android-sdk-license')) { if (-not (Test-Path -LiteralPath (Join-Path $sdkRoot $required))) { throw "Android SDK setup incomplete: $required" } } "ANDROID_HOME=$sdkRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append "ANDROID_SDK_ROOT=$sdkRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append