feat: multi-platform bug fixes, Android audio path, and build tooling
Flutter UI fixes: - Fix stale channel badge/speaker when moved by others (derive current channel from ownClientId instead of optimistic local state) - Fix Linux PTT via focused fallback key handler - Distinguish ServerQuery clients with terminal icon in client list - Reduce duplicate current-channel badge display - Prevent PTT key-bind save from permanently closing voice settings - Fix Linux GTK reopen-after-close (quit app on window destroy) - Fix focused PTT: consume key events, release held keys on disconnect/leave-channel/mode/backend changes, suppress stale errors Flutter Rust bridge: - Thread is_server_query flag through protocol→bridge→Dart - Add own_client_id to BridgeSnapshot DTO - Add log_file_path_str() for platform log path queries Rust protocol: - Add ServerQuery test coverage (query_client_type_maps_to_server_query_flag) - Split reqwest TLS: native-tls for desktop/iOS, rustls for Android Rust audio: - Upgrade cpal 0.16→0.17.3 with API adjustments (SampleRate, description()) - Suppress Android-only dead-code warnings (open_log_file, keyring_account) Android build tooling: - tools/build-opus-android.sh: NDK auto-discovery, correct CMake Android variables (ANDROID_ABI, ANDROID_PLATFORM), portable baseline - tools/build-android-rust.sh: build+copy Rust cdylib for arm64-v8a, armeabi-v7a, x86_64 into android/app/src/main/jniLibs/ - Add jniLibs/ to .gitignore Rust bridge: - Guard open_log_file() on non-Android (Android uses logcat)
This commit is contained in:
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
REPO_ROOT="$(pwd)"
|
||||
|
||||
NDK_ROOT="${ANDROID_NDK_HOME:-}"
|
||||
if [[ -z "$NDK_ROOT" && -n "${ANDROID_HOME:-}" ]]; then
|
||||
NDK_ROOT="$(find "$ANDROID_HOME/ndk" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort | tail -1 || true)"
|
||||
fi
|
||||
if [[ -z "$NDK_ROOT" && -n "${ANDROID_SDK_ROOT:-}" ]]; then
|
||||
NDK_ROOT="$(find "$ANDROID_SDK_ROOT/ndk" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort | tail -1 || true)"
|
||||
fi
|
||||
|
||||
ANDROID_PLATFORM=28
|
||||
JNI_LIBS_DIR="$REPO_ROOT/apps/chanora_flutter/android/app/src/main/jniLibs"
|
||||
|
||||
declare -a BUILDS=(
|
||||
"arm64-v8a;aarch64-linux-android;/tmp/opus-android-arm64-v8a"
|
||||
"armeabi-v7a;armv7-linux-androideabi;/tmp/opus-android-armeabi-v7a"
|
||||
"x86_64;x86_64-linux-android;/tmp/opus-android-x86_64"
|
||||
)
|
||||
|
||||
bar() { printf '%s\n' '========================================================================'; }
|
||||
|
||||
require_cmd() {
|
||||
local cmd=$1
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
echo "ERROR: '$cmd' is required but not on PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
bar
|
||||
echo "Chanora Android Rust build"
|
||||
echo "Repo root : $REPO_ROOT"
|
||||
echo "NDK : $NDK_ROOT"
|
||||
echo "Android platform: $ANDROID_PLATFORM"
|
||||
bar
|
||||
|
||||
require_cmd cargo
|
||||
require_cmd cargo-ndk
|
||||
|
||||
if [[ ! -d "$NDK_ROOT" ]]; then
|
||||
echo "ERROR: Android NDK not found. Set ANDROID_NDK_HOME or ANDROID_HOME." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export ANDROID_NDK_HOME="$NDK_ROOT"
|
||||
export LIBOPUS_STATIC=1
|
||||
export LIBOPUS_NO_PKG=1
|
||||
|
||||
for build in "${BUILDS[@]}"; do
|
||||
IFS=';' read -r abi triple opus_dir <<< "$build"
|
||||
if [[ ! -f "$opus_dir/lib/libopus.a" ]]; then
|
||||
echo "ERROR: missing $opus_dir/lib/libopus.a" >&2
|
||||
echo "Run tools/build-opus-android.sh first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Building Rust bridge for $abi ($triple)"
|
||||
export LIBOPUS_LIB_DIR="$opus_dir"
|
||||
cargo ndk --platform "$ANDROID_PLATFORM" -t "$abi" build --release -p chanora_bridge
|
||||
|
||||
mkdir -p "$JNI_LIBS_DIR/$abi"
|
||||
cp "$REPO_ROOT/target/$triple/release/libchanora_bridge.so" "$JNI_LIBS_DIR/$abi/"
|
||||
done
|
||||
|
||||
bar
|
||||
echo "Android Rust libraries copied to $JNI_LIBS_DIR"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Executable
+108
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
NDK_ROOT="${ANDROID_NDK_HOME:-}"
|
||||
if [[ -z "$NDK_ROOT" && -n "${ANDROID_HOME:-}" ]]; then
|
||||
NDK_ROOT="$(find "$ANDROID_HOME/ndk" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort | tail -1 || true)"
|
||||
fi
|
||||
if [[ -z "$NDK_ROOT" && -n "${ANDROID_SDK_ROOT:-}" ]]; then
|
||||
NDK_ROOT="$(find "$ANDROID_SDK_ROOT/ndk" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort | tail -1 || true)"
|
||||
fi
|
||||
OPUS_VERSION="v1.3.1"
|
||||
OPUS_SRC_DIR="/tmp/opus-1.3.1"
|
||||
API_LEVEL=21
|
||||
|
||||
declare -a ABIS=(
|
||||
"arm64-v8a"
|
||||
"armeabi-v7a"
|
||||
"x86_64"
|
||||
)
|
||||
|
||||
bar() { printf '%s\n' '========================================================================'; }
|
||||
|
||||
require_cmd() {
|
||||
local cmd=$1
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
echo "ERROR: '$cmd' is required but not on PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
clone_or_update_opus() {
|
||||
if [[ ! -d "$OPUS_SRC_DIR/.git" ]]; then
|
||||
echo "Cloning opus ${OPUS_VERSION} into $OPUS_SRC_DIR"
|
||||
rm -rf "$OPUS_SRC_DIR"
|
||||
git clone --branch "$OPUS_VERSION" --depth 1 https://github.com/xiph/opus.git "$OPUS_SRC_DIR"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Reusing existing opus checkout at $OPUS_SRC_DIR"
|
||||
git -C "$OPUS_SRC_DIR" fetch --tags origin
|
||||
git -C "$OPUS_SRC_DIR" checkout "$OPUS_VERSION"
|
||||
}
|
||||
|
||||
build_one() {
|
||||
local abi=$1
|
||||
local build_dir="/tmp/opus-android-${abi}-build"
|
||||
local install_dir="/tmp/opus-android-${abi}"
|
||||
|
||||
echo "Building opus for ${abi} (API ${API_LEVEL})"
|
||||
rm -rf "$build_dir" "$install_dir"
|
||||
mkdir -p "$build_dir"
|
||||
|
||||
# Opus 1.3.1's ARM NEON CMake path fails with recent NDK clang
|
||||
# (`celt_inner_prod_neon` implicit declaration). Keep this portable
|
||||
# baseline until we either patch Opus or upgrade the vendored version.
|
||||
cmake -S "$OPUS_SRC_DIR" -B "$build_dir" \
|
||||
-DCMAKE_TOOLCHAIN_FILE="$NDK_ROOT/build/cmake/android.toolchain.cmake" \
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||||
-DANDROID_ABI="$abi" \
|
||||
-DANDROID_PLATFORM="android-${API_LEVEL}" \
|
||||
-DCMAKE_INSTALL_PREFIX="$install_dir" \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-DOPUS_BUILD_PROGRAMS=OFF \
|
||||
-DOPUS_BUILD_TESTING=OFF \
|
||||
-DOPUS_DISABLE_INTRINSICS=ON \
|
||||
-DOPUS_USE_NEON=OFF \
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||
|
||||
cmake --build "$build_dir" --parallel
|
||||
cmake --install "$build_dir"
|
||||
|
||||
if [[ ! -f "$install_dir/lib/libopus.a" ]]; then
|
||||
echo "ERROR: expected $install_dir/lib/libopus.a" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
bar
|
||||
echo "Chanora Android opus build"
|
||||
echo "NDK : $NDK_ROOT"
|
||||
echo "Opus tag : $OPUS_VERSION"
|
||||
echo "API level : $API_LEVEL"
|
||||
bar
|
||||
|
||||
require_cmd git
|
||||
require_cmd cmake
|
||||
|
||||
if [[ ! -d "$NDK_ROOT" ]]; then
|
||||
echo "ERROR: Android NDK not found at $NDK_ROOT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
clone_or_update_opus
|
||||
|
||||
for abi_entry in "${ABIS[@]}"; do
|
||||
build_one "$abi_entry"
|
||||
done
|
||||
|
||||
bar
|
||||
echo "Android opus builds complete."
|
||||
for abi_entry in "${ABIS[@]}"; do
|
||||
echo " /tmp/opus-android-${abi_entry}/lib/libopus.a"
|
||||
done
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user