Kotlin 层三个文件(刻意零第三方依赖,纯 View 布局——阶段 1 只验证链路): - RustBridge.kt:android-ffi 的 JNI 声明 + 帧头拆解(25 字节定长头 + Annex-B 载荷) - H264Decoder.kt:MediaCodec 同步模式 + Surface 直出;内置两条实测教训—— 只用 getInputBuffer(i)(Exynos Quirk)、awaitingIdr 状态机(R-3 跳帧断参考链) - MainActivity.kt:连接/解码循环/触摸绝对坐标映射;断开顺序遵守 「先停解码线程 join 后 destroy」的 FFI 纪律 构建链(build-android.ps1,一条命令:cargo ndk -> .so -> gradle assembleDebug -> 安装启动): - 路径自适应( 定位仓库根),local.properties 自动生成 - gradle.properties 固定 JDK 17,不动全局 JAVA_HOME 真机验收(vivo S6 / 192.168.1.163 -> PC / 192.168.1.180:47800): - agent 日志:peer connected + auth ok, desktop 2560x1440 - 手机截图:Windows 桌面(WPS 文件列表)已渲染在 SurfaceView 上 证据:evidence/screen-connected.png(本地,不入库) 已知环境限制(记录在个人层 baseline):本机 Windows 防火墙的 agent.exe 程序级放行规则对 UDP 入站不生效(临时关防火墙即通),QQPC 驱动级防护 静默拦 TCP 入站(管理员无法停止/杀死)。阶段 2 前需落定长期方案: 端口级防火墙规则或换开发机。
86 lines
3.7 KiB
PowerShell
86 lines
3.7 KiB
PowerShell
# Phase 1 build chain: Rust .so -> jniLibs -> Gradle debug APK -> install -> launch
|
|
#
|
|
# Keep this file ASCII-only (PS 5.1 reads BOM-less .ps1 as GBK; see lessons).
|
|
#
|
|
# Usage (from apps/android-viewer/):
|
|
# powershell -ExecutionPolicy Bypass -File build-android.ps1 [-Host_ 192.168.1.5] [-Port 47800] [-Code t] [-SkipRust]
|
|
# (param is Host_ because $Host is a PowerShell automatic variable)
|
|
#
|
|
# Prereqs (Windows dev box):
|
|
# - Rust + Android targets + cargo-ndk + NDK (see personal docs/baseline.md toolchain table)
|
|
# - JDK 17 + Gradle 8.14 (paths in $vars below, adjust to your machine)
|
|
# - local.properties with sdk.dir (gitignored; template: sdk.dir=<android sdk path>)
|
|
|
|
param(
|
|
[string]$Host_ = "192.168.1.5",
|
|
[int]$Port = 47800,
|
|
[string]$Code = "t",
|
|
[switch]$SkipRust
|
|
)
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
# repo root = two levels up from this script (apps/android-viewer -> repo)
|
|
$proj = $PSScriptRoot
|
|
$repo = (Resolve-Path "$proj\..\..").Path
|
|
$env_ = "D:\working\environment"
|
|
$gradle = "D:\working\android\gradle\gradle-8.14.3\bin\gradle.bat"
|
|
$adb = "D:\working\android\sdk\platform-tools\adb.exe"
|
|
|
|
$env:RUSTUP_HOME = "$env_\rust"
|
|
$env:CARGO_HOME = "$env_\cargo"
|
|
$env:PATH = "$env_\mingw64\bin;$env_\cargo\bin;$env:PATH"
|
|
$env:ANDROID_HOME = "D:\working\android\sdk"
|
|
$env:ANDROID_NDK_HOME = "D:\working\android\sdk\ndk\30.0.16248370"
|
|
$env:GRADLE_USER_HOME = "D:\working\android\gradle-home"
|
|
$env:JAVA_HOME = "D:\working\java\jdk17"
|
|
|
|
if (-not (Test-Path "$proj\local.properties")) {
|
|
Set-Content "$proj\local.properties" 'sdk.dir=D\:\\working\\android\\sdk' -Encoding ascii
|
|
Write-Host "generated local.properties (sdk.dir)"
|
|
}
|
|
|
|
if (-not $SkipRust) {
|
|
Write-Host "=== 1/4 cargo ndk: android-ffi (arm64 release) ===" -ForegroundColor Cyan
|
|
Push-Location $repo
|
|
# cargo writes progress to stderr; PS 5.1 + ErrorActionPreference=Stop turns
|
|
# every stderr line into a terminating error. Relax for native calls and
|
|
# judge by exit code (same for gradle below).
|
|
$ErrorActionPreference = "Continue"
|
|
cargo ndk -t arm64-v8a build -p android-ffi --release 2>&1 |
|
|
Select-String "error|Finished|Building"
|
|
if ($LASTEXITCODE -ne 0) { throw "cargo ndk build failed (exit $LASTEXITCODE)" }
|
|
$ErrorActionPreference = "Stop"
|
|
Pop-Location
|
|
}
|
|
|
|
Write-Host "=== 2/4 copy .so into app/libs ===" -ForegroundColor Cyan
|
|
$so = "$repo\target\aarch64-linux-android\release\libandroidffi.so"
|
|
if (-not (Test-Path $so)) { throw "missing $so (run without -SkipRust)" }
|
|
New-Item -ItemType Directory -Force -Path "$proj\app\libs\arm64-v8a" | Out-Null
|
|
Copy-Item $so "$proj\app\libs\arm64-v8a\libandroidffi.so" -Force
|
|
Write-Host (" libandroidffi.so: {0:N0} KB" -f ((Get-Item $so).Length/1KB))
|
|
|
|
Write-Host "=== 3/4 gradle assembleDebug ===" -ForegroundColor Cyan
|
|
Push-Location $proj
|
|
$ErrorActionPreference = "Continue"
|
|
& $gradle :app:assembleDebug --console=plain 2>&1 | Select-Object -Last 25
|
|
$code = $LASTEXITCODE
|
|
$ErrorActionPreference = "Stop"
|
|
Pop-Location
|
|
if ($code -ne 0) { throw "gradle build failed (exit $code)" }
|
|
|
|
$apk = "$proj\app\build\outputs\apk\debug\app-debug.apk"
|
|
if (-not (Test-Path $apk)) { throw "apk not found: $apk" }
|
|
Write-Host (" APK: {0:N0} KB" -f ((Get-Item $apk).Length/1KB))
|
|
|
|
Write-Host "=== 4/4 install + launch ===" -ForegroundColor Cyan
|
|
$ErrorActionPreference = "Continue"
|
|
& $adb install -r $apk
|
|
if ($LASTEXITCODE -ne 0) { throw "install failed (phone must allow USB install)" }
|
|
& $adb logcat -c | Out-Null
|
|
& $adb shell am start -n com.verify.remote/.MainActivity `
|
|
--es host $Host_ --ei port $Port --es code $Code | Out-Null
|
|
$ErrorActionPreference = "Stop"
|
|
Write-Host "launched. watch: adb logcat -s MainActivity:H264Decoder RustBridge:* viewer-core:* AndroidRuntime:E"
|
|
Write-Host "after 10s capture screen: adb exec-out screencap -p > screen.png"
|