222 lines
9.3 KiB
PowerShell
222 lines
9.3 KiB
PowerShell
<#
|
|
Maakt een APK van de Android-app.
|
|
|
|
Draaien vanaf je eigen pc:
|
|
D:\MijnBesluit VS\MijnBesluit\tools\Apk-maken.ps1 # release-APK, ondertekend
|
|
D:\MijnBesluit VS\MijnBesluit\tools\Apk-maken.ps1 -Snel # snel, met de debug-sleutel
|
|
D:\MijnBesluit VS\MijnBesluit\tools\Apk-maken.ps1 -Aab # bundel voor de Play Store
|
|
|
|
De eerste keer maakt het script een sleutelbestand aan (een "keystore"). Bewaar dat goed:
|
|
zonder dat bestand kun je later geen nieuwe versie van de app meer uitbrengen die Android
|
|
als dezelfde app herkent. Dat is niet te herstellen — net zo min als het sleutelbestand
|
|
van de kluis.
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
# Bouwt een debug-versie met de standaard debug-sleutel: meteen te installeren op je eigen
|
|
# toestel. Heet bewust niet -Debug: die naam is van PowerShell zelf.
|
|
[switch] $Snel,
|
|
|
|
# Bouwt een AAB in plaats van een APK. Dat is wat de Play Store wil: een bundel waaruit
|
|
# Google per toestel een APK maakt, zodat niemand de onderdelen voor andere toestellen
|
|
# meedownloadt. Een AAB kun je niet zelf op een telefoon zetten - daarvoor blijf je de APK
|
|
# gebruiken. Zelfde sleutelbestand, zelfde wachtwoord.
|
|
[switch] $Aab,
|
|
|
|
# Waar de APK terechtkomt.
|
|
[string] $Uit = 'D:\MijnBesluit VS\MijnBesluitpublish\mijnbesluit-app',
|
|
|
|
# Het sleutelbestand waarmee de app wordt ondertekend.
|
|
[string] $Sleutelbestand = 'D:\MijnBesluit VS\MijnBesluitSleutels\mijnbesluit-app.keystore',
|
|
[string] $Alias = 'mijnbesluit',
|
|
|
|
# Alleen invullen als het script keytool.exe niet zelf kan vinden.
|
|
[string] $Keytool
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$project = Join-Path $PSScriptRoot '..\src\MijnBesluit.App\MijnBesluit.App.csproj' | Resolve-Path
|
|
$doel = 'net10.0-android'
|
|
|
|
New-Item -ItemType Directory -Path $Uit -Force | Out-Null
|
|
|
|
if ($Snel) {
|
|
Write-Host "APK bouwen (debug)..." -ForegroundColor Cyan
|
|
|
|
# EmbedAssembliesIntoApk: bij Debug laat MAUI de .NET-assemblies normaal buiten het pakket,
|
|
# omdat Visual Studio ze bij het debuggen los naar het toestel duwt. Een APK die je met de
|
|
# hand installeert mist ze dan, en de app klapt bij het starten meteen dicht.
|
|
dotnet build $project -f $doel -c Debug -p:EmbedAssembliesIntoApk=true
|
|
if ($LASTEXITCODE -ne 0) { throw "Bouwen mislukt." }
|
|
|
|
$apk = Get-ChildItem (Join-Path (Split-Path $project) "bin\Debug\$doel") -Filter '*-Signed.apk' |
|
|
Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
|
if (-not $apk) { throw "Geen APK gevonden. Staat de MAUI-werkbelasting geinstalleerd?" }
|
|
|
|
Copy-Item $apk.FullName (Join-Path $Uit 'mijnbesluit-debug.apk') -Force
|
|
Write-Host "Klaar: $Uit\mijnbesluit-debug.apk" -ForegroundColor Green
|
|
return
|
|
}
|
|
|
|
# ------------------------------------------------------------------ keytool zoeken
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Zoekt keytool.exe, dat bij de Java hoort die met de Android-werkbelasting meekomt.
|
|
|
|
.DESCRIPTION
|
|
Waar die Java staat hangt af van hoe Visual Studio is geinstalleerd - er zijn er een stuk
|
|
of vijf in omloop. Daarom kijken we op alle bekende plekken in plaats van op een.
|
|
#>
|
|
function Vind-Keytool
|
|
{
|
|
if ($Keytool) {
|
|
if (-not (Test-Path $Keytool)) { throw "Opgegeven keytool bestaat niet: $Keytool" }
|
|
return $Keytool
|
|
}
|
|
|
|
$inPad = Get-Command keytool -ErrorAction SilentlyContinue
|
|
if ($inPad) { return $inPad.Source }
|
|
|
|
$plekken = @()
|
|
|
|
if ($env:JAVA_HOME) { $plekken += (Join-Path $env:JAVA_HOME 'bin\keytool.exe') }
|
|
|
|
$mappen = @(
|
|
'C:\Program Files\Microsoft\jdk-*',
|
|
'C:\Program Files\Android\openjdk\*',
|
|
'C:\Program Files\Android\jdk\*',
|
|
'C:\Program Files (x86)\Android\openjdk\*',
|
|
'C:\Program Files (x86)\Android\jdk\*',
|
|
'C:\Program Files\Eclipse Adoptium\jdk-*',
|
|
'C:\Program Files\Java\jdk-*',
|
|
"$env:LOCALAPPDATA\Android\jdk\*"
|
|
)
|
|
|
|
foreach ($map in $mappen) {
|
|
Get-ChildItem $map -Directory -ErrorAction SilentlyContinue |
|
|
Sort-Object Name -Descending |
|
|
ForEach-Object { $plekken += (Join-Path $_.FullName 'bin\keytool.exe') }
|
|
}
|
|
|
|
# Android Studio brengt zijn eigen Java mee.
|
|
$plekken += 'C:\Program Files\Android\Android Studio\jbr\bin\keytool.exe'
|
|
|
|
foreach ($pad in $plekken) {
|
|
if (Test-Path $pad) { return $pad }
|
|
}
|
|
|
|
throw @"
|
|
keytool.exe is nergens gevonden. Dat hoort bij de Java die met de Android-werkbelasting meekomt.
|
|
|
|
Gezocht in:
|
|
$($plekken -join "`n")
|
|
|
|
Zoek hem zelf met:
|
|
Get-ChildItem 'C:\Program Files','C:\Program Files (x86)' -Recurse -Filter keytool.exe -ErrorAction SilentlyContinue |
|
|
Select-Object -First 5 FullName
|
|
|
|
Zet de map met keytool.exe daarna in JAVA_HOME, of geef het pad mee met -Keytool.
|
|
|
|
Wil je alleen op je eigen toestel testen, gebruik dan -Snel: een debug-APK heeft dit niet nodig.
|
|
"@
|
|
}
|
|
|
|
# ------------------------------------------------------------------ release
|
|
|
|
if (-not (Test-Path $Sleutelbestand)) {
|
|
Write-Host "Er is nog geen sleutelbestand. Ik maak er een aan." -ForegroundColor Yellow
|
|
Write-Host "Kies een wachtwoord dat je NIET kwijtraakt." -ForegroundColor Yellow
|
|
|
|
$keytool = Vind-Keytool
|
|
|
|
New-Item -ItemType Directory -Path (Split-Path $Sleutelbestand) -Force | Out-Null
|
|
|
|
& $keytool -genkeypair -v `
|
|
-keystore $Sleutelbestand -alias $Alias `
|
|
-keyalg RSA -keysize 2048 -validity 10000
|
|
if ($LASTEXITCODE -ne 0) { throw "Sleutelbestand aanmaken mislukt." }
|
|
|
|
Write-Host ""
|
|
Write-Host "MAAK HIER NU EEN BACK-UP VAN: $Sleutelbestand" -ForegroundColor Red
|
|
Write-Host "Zonder dit bestand is er later geen nieuwe versie van de app meer uit te brengen." -ForegroundColor Red
|
|
Write-Host ""
|
|
}
|
|
|
|
# Het wachtwoord van het sleutelbestand. Drie wegen, in deze volgorde:
|
|
#
|
|
# 1. De omgevingsvariabele MIJNBESLUIT_KEYSTORE_WACHTWOORD. Zet je die als gebruikersvariabele
|
|
# in Windows, dan kan het uitrolvenster ook een ondertekende APK bouwen. Hij staat dan wel
|
|
# op je machine; dat is een afweging die jij maakt en niet dit script.
|
|
# 2. Zelf intypen, als je dit script in een PowerShell-venster draait.
|
|
# 3. Draait dit vanuit het uitrolvenster zonder die variabele, dan houdt het hier op MET een
|
|
# melding. Dat is met opzet: zo'n venster heeft geen invoer, dus Read-Host zou daar blijven
|
|
# wachten op iets wat nooit komt - en dan staat er een build "nog bezig" die nooit afloopt.
|
|
if ($env:MIJNBESLUIT_KEYSTORE_WACHTWOORD) {
|
|
$plat = $env:MIJNBESLUIT_KEYSTORE_WACHTWOORD
|
|
}
|
|
elseif ($env:MIJNBESLUIT_UITROLVENSTER) {
|
|
throw @"
|
|
Het sleutelbestand vraagt om een wachtwoord, en dit venster kan daar niet om vragen.
|
|
|
|
Twee manieren om verder te komen:
|
|
* Draai dit script zelf in PowerShell: D:\MijnBesluit VS\MijnBesluit\tools\Apk-maken.ps1
|
|
* Of zet het wachtwoord eenmalig in een gebruikersvariabele, dan kan het venster het ook:
|
|
[Environment]::SetEnvironmentVariable('MIJNBESLUIT_KEYSTORE_WACHTWOORD', '<wachtwoord>', 'User')
|
|
Daarna het uitrolvenster opnieuw starten, anders kent het die variabele nog niet.
|
|
"@
|
|
}
|
|
else {
|
|
$wachtwoord = Read-Host "Wachtwoord van het sleutelbestand" -AsSecureString
|
|
$plat = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
|
|
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($wachtwoord))
|
|
}
|
|
|
|
# Leeg is geen wachtwoord. Dit is de val die een kwartier kost: in een proces zonder invoer geeft
|
|
# Read-Host geen fout maar een lege tekst, en dan bouwt hij eerst honderd assemblies om pas bij
|
|
# het ondertekenen om te vallen met "java.exe exited with code 2" - een melding waar niets in
|
|
# staat over een wachtwoord. Beter hier stoppen, voordat er iets gebouwd is.
|
|
if ([string]::IsNullOrWhiteSpace($plat)) {
|
|
throw @"
|
|
Er is geen wachtwoord voor het sleutelbestand opgegeven.
|
|
|
|
Krijg je dit terwijl je het net hebt ingetypt, dan draait dit script in een venster zonder invoer.
|
|
Draai hem dan zelf in PowerShell, of zet het wachtwoord eenmalig in een gebruikersvariabele:
|
|
[Environment]::SetEnvironmentVariable('MIJNBESLUIT_KEYSTORE_WACHTWOORD', '<wachtwoord>', 'User')
|
|
"@
|
|
}
|
|
|
|
$formaat = if ($Aab) { 'aab' } else { 'apk' }
|
|
|
|
Write-Host "$($formaat.ToUpper()) bouwen (release)..." -ForegroundColor Cyan
|
|
dotnet publish $project -f $doel -c Release `
|
|
-p:AndroidPackageFormat=$formaat `
|
|
-p:AndroidKeyStore=true `
|
|
-p:AndroidSigningKeyStore=$Sleutelbestand `
|
|
-p:AndroidSigningKeyAlias=$Alias `
|
|
-p:AndroidSigningStorePass=$plat `
|
|
-p:AndroidSigningKeyPass=$plat `
|
|
-o $Uit
|
|
|
|
if ($LASTEXITCODE -ne 0) { throw "Bouwen mislukt." }
|
|
|
|
# De ondertekende bundel heet meestal <pakketnaam>-Signed.aab, maar niet elke versie van de
|
|
# werkbelasting hangt er "-Signed" achter. Eerst de nette naam, en anders wat er ligt.
|
|
$pakket = Get-ChildItem $Uit -Filter "*-Signed.$formaat" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
|
if (-not $pakket) {
|
|
$pakket = Get-ChildItem $Uit -Filter "*.$formaat" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
|
}
|
|
if (-not $pakket) { throw "Geen ondertekende $($formaat.ToUpper()) gevonden in $Uit." }
|
|
|
|
Write-Host ""
|
|
Write-Host "Klaar: $($pakket.FullName)" -ForegroundColor Green
|
|
|
|
if ($Aab) {
|
|
Write-Host ""
|
|
Write-Host "Dit bestand gaat naar de Play Console. Op een telefoon zetten kan er niet mee;" -ForegroundColor Yellow
|
|
Write-Host "bouw daarvoor zonder -Aab een gewone APK." -ForegroundColor Yellow
|
|
} else {
|
|
Write-Host "Voor de Play Store heb je geen APK nodig maar een AAB: draai dit script met -Aab."
|
|
}
|