andorid app

This commit is contained in:
2026-01-01 10:47:57 +01:00
parent ff9209062e
commit b99d9ce524
80 changed files with 6154 additions and 5 deletions

206
scripts/build-android.ps1 Normal file
View File

@@ -0,0 +1,206 @@
<#
Build helper for Android (Windows PowerShell)
What it does:
- Checks for required commands (`npm`, `rustup`, `cargo`, `cargo-ndk`)
- Builds frontend (runs `npm run build` if `dist`/`build` not present)
- Copies frontend files from `dist` or `src` into `android/app/src/main/assets`
- Builds Rust native libs using `cargo-ndk` (if available) for `aarch64` and `armv7`
- Copies produced `.so` files into `android/app/src/main/jniLibs/*`
Note: This script prepares the Android project. To produce the APK, open `android/` in Android Studio and run Build -> Assemble, or run `gradlew assembleDebug` locally.
#>
Set-StrictMode -Version Latest
function Check-Command($name) {
$which = Get-Command $name -ErrorAction SilentlyContinue
return $which -ne $null
}
Write-Output "Starting Android prep script..."
if (-not (Check-Command npm)) { Write-Warning "npm not found in PATH. Install Node.js to build frontend." }
if (-not (Check-Command rustup)) { Write-Warning "rustup not found in PATH. Install Rust toolchain." }
if (-not (Check-Command cargo)) { Write-Warning "cargo not found in PATH." }
$cargoNdkAvailable = Check-Command cargo-ndk
if (-not $cargoNdkAvailable) { Write-Warning "cargo-ndk not found. Native libs will not be built. Install via 'cargo install cargo-ndk'" }
# Determine repository root (parent of the scripts folder)
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
$root = Split-Path -Parent $scriptDir
Push-Location $root
# Prefer Tauri-generated Android Studio project (tauri android init)
$androidRoot = Join-Path $root 'src-tauri\gen\android'
if (-not (Test-Path $androidRoot)) {
# Legacy fallback (non-Tauri project)
$androidRoot = Join-Path $root 'android'
}
function Escape-LocalPropertiesPath([string]$p) {
# local.properties expects ':' escaped and backslashes doubled on Windows.
# Use plain string replacements to avoid regex escaping pitfalls.
return ($p.Replace('\', '\\').Replace(':', '\:'))
}
# Ensure Android SDK/NDK locations are set for Gradle (local.properties)
$sdkRoot = $env:ANDROID_SDK_ROOT
if (-not $sdkRoot) { $sdkRoot = $env:ANDROID_HOME }
if (-not $sdkRoot) { $sdkRoot = Join-Path $env:LOCALAPPDATA 'Android\Sdk' }
$ndkRoot = $env:ANDROID_NDK_ROOT
if (-not $ndkRoot) { $ndkRoot = $env:ANDROID_NDK_HOME }
if (-not $ndkRoot -and (Test-Path (Join-Path $sdkRoot 'ndk'))) {
$ndkVersions = Get-ChildItem -Path (Join-Path $sdkRoot 'ndk') -Directory -ErrorAction SilentlyContinue | Sort-Object Name -Descending
if ($ndkVersions -and (@($ndkVersions)).Count -gt 0) { $ndkRoot = @($ndkVersions)[0].FullName }
}
if (Test-Path $androidRoot) {
$localPropsPath = Join-Path $androidRoot 'local.properties'
$lines = @()
if ($sdkRoot) { $lines += "sdk.dir=$(Escape-LocalPropertiesPath $sdkRoot)" }
if ($ndkRoot) { $lines += "ndk.dir=$(Escape-LocalPropertiesPath $ndkRoot)" }
if ($lines.Count -gt 0) {
Set-Content -Path $localPropsPath -Value ($lines -join "`n") -Encoding ASCII
Write-Output "Wrote Android SDK/NDK config to: $localPropsPath"
}
}
# Build frontend (optional)
Write-Output "Preparing frontend files..."
$distDirs = @('dist','build')
$foundDist = $null
foreach ($d in $distDirs) {
if (Test-Path (Join-Path $root $d)) { $foundDist = $d; break }
}
if (-not $foundDist) {
# IMPORTANT: `npm run build` in this repo runs `tauri build`, which is a desktop bundling step.
# For Android prep we only need web assets, so we fall back to copying `src/` as assets.
Write-Warning "No dist/build output found — copying `src/` as assets (skipping `npm run build` to avoid desktop bundling)."
}
$assetsDst = Join-Path $androidRoot 'app\src\main\assets'
if (-not (Test-Path $assetsDst)) { New-Item -ItemType Directory -Path $assetsDst -Force | Out-Null }
if ($foundDist) {
Write-Output "Copying frontend from '$foundDist' to Android assets..."
robocopy (Join-Path $root $foundDist) $assetsDst /MIR | Out-Null
} else {
Write-Output "Copying raw 'src' to Android assets..."
robocopy (Join-Path $root 'src') $assetsDst /MIR | Out-Null
}
# Build native libs if cargo-ndk available
if ($cargoNdkAvailable) {
Write-Output "Building Rust native libs via cargo-ndk from project root: $root"
try {
# Build from the Rust crate directory `src-tauri`
$crateDir = Join-Path $root 'src-tauri'
if (-not (Test-Path (Join-Path $crateDir 'Cargo.toml'))) {
Write-Warning "Cargo.toml not found in src-tauri; skipping native build."
} else {
# Prefer Ninja generator for CMake if available (avoids Visual Studio generator issues)
# Restore env vars at the end so we don't pollute the current PowerShell session.
$oldCmakeGenerator = $env:CMAKE_GENERATOR
$oldCmakeMakeProgram = $env:CMAKE_MAKE_PROGRAM
$ninjaCmd = Get-Command ninja -ErrorAction SilentlyContinue
if ($ninjaCmd) {
Write-Output "Ninja detected at $($ninjaCmd.Source); setting CMake generator to Ninja."
$env:CMAKE_GENERATOR = 'Ninja'
$env:CMAKE_MAKE_PROGRAM = $ninjaCmd.Source
} else {
Write-Warning "Ninja not found in PATH. Installing Ninja or adding it to PATH is strongly recommended to avoid Visual Studio CMake generator on Windows."
}
# Attempt to locate Android NDK if environment variables are not set
if (-not $env:ANDROID_NDK_ROOT -and -not $env:ANDROID_NDK_HOME) {
$candidates = @()
if ($env:ANDROID_SDK_ROOT) { $candidates += Join-Path $env:ANDROID_SDK_ROOT 'ndk' }
if ($env:ANDROID_HOME) { $candidates += Join-Path $env:ANDROID_HOME 'ndk' }
$candidates += Join-Path $env:LOCALAPPDATA 'Android\sdk\ndk'
$candidates += Join-Path $env:USERPROFILE 'AppData\Local\Android\sdk\ndk'
$candidates += 'C:\Program Files (x86)\Android\AndroidNDK'
foreach ($cand in $candidates) {
if (Test-Path $cand) {
$versions = Get-ChildItem -Path $cand -Directory -ErrorAction SilentlyContinue | Sort-Object Name -Descending
if ($versions -and (@($versions)).Count -gt 0) {
$ndkPath = @($versions)[0].FullName
Write-Output "Detected Android NDK at: $ndkPath"
$env:ANDROID_NDK_ROOT = $ndkPath
$env:ANDROID_NDK = $ndkPath
break
}
}
}
if (-not $env:ANDROID_NDK_ROOT) { Write-Warning "ANDROID_NDK_ROOT/ANDROID_NDK not set and no NDK found in common locations. Set ANDROID_NDK_ROOT to your NDK path." }
} else {
Write-Output "Using existing ANDROID_NDK_ROOT: $($env:ANDROID_NDK_ROOT)"
if (-not $env:ANDROID_NDK) { $env:ANDROID_NDK = $env:ANDROID_NDK_ROOT }
}
# Ensure expected external binary placeholders exist so Tauri bundling doesn't fail
$binariesDir = Join-Path $crateDir 'binaries'
if (-not (Test-Path $binariesDir)) { New-Item -ItemType Directory -Path $binariesDir -Force | Out-Null }
$placeholder1 = Join-Path $binariesDir 'RadioPlayer-aarch64-linux-android'
$placeholder2 = Join-Path $binariesDir 'RadioPlayer-armv7-linux-androideabi'
if (-not (Test-Path $placeholder1)) { New-Item -ItemType File -Path $placeholder1 -Force | Out-Null; Write-Output "Created placeholder: $placeholder1" }
if (-not (Test-Path $placeholder2)) { New-Item -ItemType File -Path $placeholder2 -Force | Out-Null; Write-Output "Created placeholder: $placeholder2" }
# If a previous build used a different CMake generator (e.g., Visual Studio), aws-lc-sys can fail with
# "Does not match the generator used previously". Clean only the aws-lc-sys CMake build dirs.
$awsLcBuildDirs = Get-ChildItem -Path (Join-Path $crateDir 'target') -Recurse -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like 'aws-lc-sys-*' }
foreach ($d in @($awsLcBuildDirs)) {
$cmakeBuildDir = Join-Path $d.FullName 'out\build'
$cmakeCache = Join-Path $cmakeBuildDir 'CMakeCache.txt'
if (Test-Path $cmakeCache) {
Write-Output "Cleaning stale CMake cache for aws-lc-sys: $cmakeBuildDir"
Remove-Item -Path $cmakeBuildDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
Push-Location $crateDir
try {
# Use API 24 to ensure libc symbols like getifaddrs/freeifaddrs are available.
# Build only the library to avoid linking the desktop binary for Android.
Write-Output "Running: cargo ndk -t arm64-v8a -t armeabi-v7a -P 24 build --release --lib (in $crateDir)"
cargo ndk -t arm64-v8a -t armeabi-v7a -P 24 build --release --lib
} finally {
Pop-Location
if ($null -eq $oldCmakeGenerator) { Remove-Item Env:\CMAKE_GENERATOR -ErrorAction SilentlyContinue } else { $env:CMAKE_GENERATOR = $oldCmakeGenerator }
if ($null -eq $oldCmakeMakeProgram) { Remove-Item Env:\CMAKE_MAKE_PROGRAM -ErrorAction SilentlyContinue } else { $env:CMAKE_MAKE_PROGRAM = $oldCmakeMakeProgram }
}
# Search for produced .so files under src-tauri/target
$soFiles = Get-ChildItem -Path (Join-Path $crateDir 'target') -Recurse -Filter "*.so" -ErrorAction SilentlyContinue
if (-not $soFiles) {
Write-Warning "No .so files found after build. Check cargo-ndk output above for errors."
} else {
foreach ($f in @($soFiles)) {
$full = $f.FullName
if ($full -match 'aarch64|aarch64-linux-android|arm64-v8a') { $abi = 'arm64-v8a' }
elseif ($full -match 'armv7|armv7-linux-androideabi|armeabi-v7a') { $abi = 'armeabi-v7a' }
else { continue }
$dst = Join-Path $androidRoot "app\src\main\jniLibs\$abi"
if (-not (Test-Path $dst)) { New-Item -ItemType Directory -Path $dst -Force | Out-Null }
Copy-Item $full -Destination $dst -Force
Write-Output "Copied $($f.Name) -> $dst"
}
}
}
} catch {
Write-Warning "cargo-ndk build failed. Exception: $($_.Exception.Message)"
if ($_.ScriptStackTrace) { Write-Output $_.ScriptStackTrace }
}
} else {
Write-Warning "Skipping native lib build (cargo-ndk missing)."
}
Write-Output "Android prep complete. Open '$androidRoot' in Android Studio and build the APK (or run './gradlew assembleDebug' in that folder)."
Pop-Location

45
scripts/build-android.sh Normal file
View File

@@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -euo pipefail
# Cross-platform helper for Unix-like shells
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
echo "Preparing Android assets and native libs..."
if command -v npm >/dev/null 2>&1; then
echo "Running npm install & build"
npm install
npm run build || true
fi
DIST_DIR="dist"
if [ ! -d "$DIST_DIR" ]; then DIST_DIR="build"; fi
if [ -d "$DIST_DIR" ]; then
echo "Copying $DIST_DIR -> android/app/src/main/assets"
mkdir -p android/app/src/main/assets
rsync -a --delete "$DIST_DIR/" android/app/src/main/assets/
else
echo "No dist/build found, copying src/ -> android assets"
mkdir -p android/app/src/main/assets
rsync -a --delete src/ android/app/src/main/assets/
fi
if command -v cargo-ndk >/dev/null 2>&1; then
echo "Building native libs with cargo-ndk"
cargo-ndk -t aarch64 -t armv7 build --release || true
# copy so files
find target -type f -name "*.so" | while read -r f; do
if [[ "$f" =~ aarch64|aarch64-linux-android ]]; then abi=arm64-v8a; fi
if [[ "$f" =~ armv7|armv7-linux-androideabi ]]; then abi=armeabi-v7a; fi
if [ -n "${abi-}" ]; then
mkdir -p android/app/src/main/jniLibs/$abi
cp "$f" android/app/src/main/jniLibs/$abi/
echo "Copied $f -> android/app/src/main/jniLibs/$abi/"
fi
done
else
echo "cargo-ndk not found; skipping native lib build"
fi
echo "Prepared Android project. Open android/ in Android Studio to build the APK (or run ./gradlew assembleDebug)."