# Builds Pithos for Android with the bare Android SDK: no Gradle, no AGP. # Toolchain: JDK 8 + build-tools 30.0.3 + platform android-30. # The page is Pithos/web, copied into the APK's assets at build time. # Usage: powershell -File build.ps1 -> build\pithos-debug.apk (debug key) # powershell -File build.ps1 -Release -> build\pithos-v.apk (release key) param([switch]$Release) $ErrorActionPreference = "Stop" $VERSION = "0.1.0" $VERSION_CODE = 1 $SDK = "$env:LOCALAPPDATA\Android\Sdk" $BT = "$SDK\build-tools\30.0.3" $PLATFORM = "$SDK\platforms\android-30\android.jar" $JDK = "C:\Program Files\Java\jdk1.8.0_202" $ROOT = $PSScriptRoot $WEB = Resolve-Path "$ROOT\..\..\web" $OUT = "$ROOT\build" $env:JAVA_HOME = $JDK $env:Path = "$JDK\bin;$env:Path" if (Test-Path $OUT) { Remove-Item -Recurse -Force $OUT } New-Item -ItemType Directory -Force "$OUT\classes", "$OUT\dex", "$OUT\gen", "$OUT\assets\web" | Out-Null Write-Host "[0/6] page + version" Copy-Item -Recurse "$WEB\*" "$OUT\assets\web\" @" package st.silentmode.pithos; final class BuildInfo { static final String VERSION = "$VERSION"; private BuildInfo() {} } "@ | Set-Content -Encoding ASCII "$OUT\gen\BuildInfo.java" $manifest = (Get-Content -Raw "$ROOT\AndroidManifest.xml") ` -replace 'android:versionCode="\d+"', "android:versionCode=`"$VERSION_CODE`"" ` -replace 'android:versionName="[^"]*"', "android:versionName=`"$VERSION`"" Set-Content -Encoding UTF8 "$OUT\AndroidManifest.xml" $manifest Write-Host "[1/6] aapt2 compile+link" & "$BT\aapt2.exe" compile --dir "$ROOT\res" -o "$OUT\res.zip" if ($LASTEXITCODE -ne 0) { throw "aapt2 compile failed" } & "$BT\aapt2.exe" link -o "$OUT\app-unsigned.apk" -I $PLATFORM --manifest "$OUT\AndroidManifest.xml" ` --java "$OUT\gen" --min-sdk-version 24 --target-sdk-version 30 -A "$OUT\assets" "$OUT\res.zip" if ($LASTEXITCODE -ne 0) { throw "aapt2 link failed" } Write-Host "[2/6] javac" $sources = Get-ChildItem "$ROOT\src","$OUT\gen" -Recurse -Filter *.java | ForEach-Object { $_.FullName } & "$JDK\bin\javac.exe" -source 1.8 -target 1.8 -encoding UTF-8 -Xlint:-options ` -bootclasspath $PLATFORM -classpath $PLATFORM -d "$OUT\classes" @sources if ($LASTEXITCODE -ne 0) { throw "javac failed" } Write-Host "[3/6] d8" $classesDir = "$OUT\classes" Push-Location $classesDir $classes = Get-ChildItem -Recurse -Filter *.class | ForEach-Object { $_.FullName.Substring($classesDir.Length + 1) } & "$BT\d8.bat" --release --min-api 24 --lib $PLATFORM --output "$OUT\dex" @classes Pop-Location if ($LASTEXITCODE -ne 0) { throw "d8 failed" } Write-Host "[4/6] add classes.dex" Push-Location "$OUT\dex" & "$JDK\bin\jar.exe" uf "$OUT\app-unsigned.apk" classes.dex Pop-Location if ($LASTEXITCODE -ne 0) { throw "jar failed" } Write-Host "[5/6] zipalign" & "$BT\zipalign.exe" -f -p 4 "$OUT\app-unsigned.apk" "$OUT\app-aligned.apk" if ($LASTEXITCODE -ne 0) { throw "zipalign failed" } Write-Host "[6/6] sign" if ($Release) { # Generated once, then REUSED FOREVER: Android installs updates only when # they are signed by the same key. Keep both files out of git, backed up. $ks = "$ROOT\release.keystore" $passFile = "$ROOT\release-keystore-password.txt" if (-not (Test-Path $passFile)) { throw "missing $passFile (put the keystore password in it first)" } $pass = (Get-Content $passFile -Raw).Trim() if (-not (Test-Path $ks)) { & "$JDK\bin\keytool.exe" -genkeypair -keystore $ks -storepass $pass -keypass $pass ` -alias pithos -keyalg RSA -keysize 4096 -validity 14000 -dname "CN=Pithos,O=Silent Mode" if ($LASTEXITCODE -ne 0) { throw "keytool failed" } Write-Host "NOTE: new release key created. BACK UP $ks and $passFile." } $apk = "$OUT\pithos-v$VERSION.apk" & "$BT\apksigner.bat" sign --ks $ks --ks-key-alias pithos --ks-pass "pass:$pass" --key-pass "pass:$pass" --out $apk "$OUT\app-aligned.apk" } else { $ks = "$ROOT\debug.keystore" if (-not (Test-Path $ks)) { & "$JDK\bin\keytool.exe" -genkeypair -keystore $ks -storepass android -keypass android ` -alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Android Debug,O=Android,C=US" if ($LASTEXITCODE -ne 0) { throw "keytool failed" } } $apk = "$OUT\pithos-debug.apk" & "$BT\apksigner.bat" sign --ks $ks --ks-pass pass:android --key-pass pass:android --out $apk "$OUT\app-aligned.apk" } if ($LASTEXITCODE -ne 0) { throw "apksigner failed" } Write-Host "OK -> $apk"