phase 0: add Android build/test scripts and fix lint menu attrs -

This commit is contained in:
2026-03-03 08:00:17 -06:00
parent 28750c1332
commit 9f1c2168a8
8 changed files with 304 additions and 4 deletions
+37
View File
@@ -124,6 +124,43 @@ Release bundle (for Play):
------------------------------------------------------------------------
## 🔧 Local Build/Test Scripts
Validate host environment:
./scripts/check-android-env.sh all
Install SDK components (requires sdkmanager):
./scripts/bootstrap-android.sh
Build + lint + unit tests:
./scripts/build-debug.sh
Connected/device tests:
./scripts/test-connected.sh
------------------------------------------------------------------------
# 📦 Play Store Ready
Release build includes:
- Resource shrinking
- Code minification
- Material 3 theming
- Clean package namespace
Before Play upload:
- Configure signing keystore
- Increment versionCode
- Generate .aab
------------------------------------------------------------------------
# 🏠 Home Assistant Integration
RelayTV integrates directly with Home Assistant via:
+5 -4
View File
@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_servers"
android:title="@string/servers"
android:icon="@android:drawable/ic_menu_manage"
android:showAsAction="ifRoom" />
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_reload"
android:title="Reload"
android:title="@string/reload"
android:icon="@android:drawable/ic_popup_sync"
android:showAsAction="ifRoom" />
app:showAsAction="ifRoom" />
</menu>
+1
View File
@@ -8,4 +8,5 @@
<string name="select_server">Select RelayTV server</string>
<string name="server_name">Name</string>
<string name="server_url">Base URL</string>
<string name="reload">Reload</string>
</resources>
Vendored Regular → Executable
View File
+81
View File
@@ -0,0 +1,81 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
INSTALL_EMULATOR="${INSTALL_EMULATOR:-0}"
ANDROID_PLATFORM="${ANDROID_PLATFORM:-android-34}"
ANDROID_BUILD_TOOLS="${ANDROID_BUILD_TOOLS:-34.0.0}"
ANDROID_SYSTEM_IMAGE="${ANDROID_SYSTEM_IMAGE:-system-images;android-34;google_apis;x86_64}"
say() { printf '%s\n' "$*"; }
find_sdkmanager() {
if command -v sdkmanager >/dev/null 2>&1; then
command -v sdkmanager
return 0
fi
local sdk="${ANDROID_SDK_ROOT:-${ANDROID_HOME:-}}"
if [[ -n "${sdk}" ]]; then
local candidate="${sdk}/cmdline-tools/latest/bin/sdkmanager"
if [[ -x "${candidate}" ]]; then
printf '%s\n' "${candidate}"
return 0
fi
fi
return 1
}
ensure_sdk_root() {
if [[ -n "${ANDROID_SDK_ROOT:-}" ]]; then
mkdir -p "${ANDROID_SDK_ROOT}"
return
fi
if [[ -n "${ANDROID_HOME:-}" ]]; then
export ANDROID_SDK_ROOT="${ANDROID_HOME}"
mkdir -p "${ANDROID_SDK_ROOT}"
return
fi
export ANDROID_SDK_ROOT="${HOME}/Android/Sdk"
mkdir -p "${ANDROID_SDK_ROOT}"
}
ensure_gradlew_executable() {
if [[ ! -x "${REPO_ROOT}/gradlew" ]]; then
chmod +x "${REPO_ROOT}/gradlew"
fi
}
ensure_sdk_root
ensure_gradlew_executable
SDKMANAGER_BIN="$(find_sdkmanager || true)"
if [[ -z "${SDKMANAGER_BIN}" ]]; then
say "sdkmanager not found."
say "Install Android cmdline-tools and add sdkmanager to PATH, then rerun."
exit 1
fi
PACKAGES=(
"platform-tools"
"platforms;${ANDROID_PLATFORM}"
"build-tools;${ANDROID_BUILD_TOOLS}"
"cmdline-tools;latest"
)
if [[ "${INSTALL_EMULATOR}" == "1" ]]; then
PACKAGES+=("emulator" "${ANDROID_SYSTEM_IMAGE}")
fi
say "Using Android SDK root: ${ANDROID_SDK_ROOT}"
say "Installing packages:"
printf ' - %s\n' "${PACKAGES[@]}"
"${SDKMANAGER_BIN}" --sdk_root="${ANDROID_SDK_ROOT}" "${PACKAGES[@]}"
"${SDKMANAGER_BIN}" --sdk_root="${ANDROID_SDK_ROOT}" --licenses < <(yes)
say
say "Bootstrap complete."
say "Tip: run ./scripts/check-android-env.sh all"
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
cd "${REPO_ROOT}"
if [[ ! -x "./scripts/check-android-env.sh" ]]; then
chmod +x "./scripts/check-android-env.sh"
fi
./scripts/check-android-env.sh build
if [[ ! -x "./gradlew" ]]; then
chmod +x ./gradlew
fi
if [[ "$#" -gt 0 ]]; then
TASKS=("$@")
else
TASKS=("clean" "assembleDebug" "lint" "testDebugUnitTest")
fi
echo "Running Gradle tasks: ${TASKS[*]}"
./gradlew --no-daemon "${TASKS[@]}"
+119
View File
@@ -0,0 +1,119 @@
#!/usr/bin/env bash
set -euo pipefail
MODE="${1:-all}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
failures=0
warnings=0
say() { printf '%s\n' "$*"; }
ok() { say "[ok] $*"; }
warn() { say "[warn] $*"; warnings=$((warnings + 1)); }
fail() { say "[fail] $*"; failures=$((failures + 1)); }
need_cmd() {
local name="$1"
if command -v "${name}" >/dev/null 2>&1; then
ok "Found command: ${name}"
else
fail "Missing command: ${name}"
fi
}
sdk_dir_from_local_properties() {
local lp="${REPO_ROOT}/local.properties"
[[ -f "${lp}" ]] || return 1
local raw
raw="$(grep -E '^sdk\.dir=' "${lp}" | tail -n1 | cut -d'=' -f2- || true)"
[[ -n "${raw}" ]] || return 1
# Gradle escaping uses backslashes. This normalizes common Linux/macOS forms.
local unescaped="${raw//\\:/:}"
unescaped="${unescaped//\\\\/\\}"
printf '%s\n' "${unescaped}"
return 0
}
detect_sdk_root() {
if [[ -n "${ANDROID_SDK_ROOT:-}" ]]; then
printf '%s\n' "${ANDROID_SDK_ROOT}"
return 0
fi
if [[ -n "${ANDROID_HOME:-}" ]]; then
printf '%s\n' "${ANDROID_HOME}"
return 0
fi
if sdk_dir_from_local_properties >/dev/null 2>&1; then
sdk_dir_from_local_properties
return 0
fi
return 1
}
validate_mode() {
case "${MODE}" in
build|connected|all) ;;
*)
say "Usage: $0 [build|connected|all]"
exit 2
;;
esac
}
check_base_tools() {
need_cmd java
need_cmd javac
}
check_connected_tools() {
need_cmd adb
}
check_sdk() {
local sdk_root=""
if sdk_root="$(detect_sdk_root)"; then
if [[ -d "${sdk_root}" ]]; then
ok "Android SDK root: ${sdk_root}"
else
fail "Android SDK path does not exist: ${sdk_root}"
fi
else
fail "Android SDK root not found. Set ANDROID_SDK_ROOT (or ANDROID_HOME)."
fi
if command -v sdkmanager >/dev/null 2>&1; then
ok "Found command: sdkmanager"
else
warn "sdkmanager not in PATH. bootstrap script can still work if cmdline-tools path is set manually."
fi
}
check_gradle_wrapper() {
if [[ -f "${REPO_ROOT}/gradlew" ]]; then
ok "Found gradle wrapper"
else
fail "Missing gradlew in repo root"
fi
}
validate_mode
say "Checking Android environment (${MODE}) for ${REPO_ROOT}"
check_base_tools
check_gradle_wrapper
check_sdk
if [[ "${MODE}" == "connected" || "${MODE}" == "all" ]]; then
check_connected_tools
fi
if [[ "${failures}" -gt 0 ]]; then
say
fail "Environment check failed with ${failures} issue(s) and ${warnings} warning(s)."
exit 1
fi
say
ok "Environment check passed with ${warnings} warning(s)."
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
cd "${REPO_ROOT}"
if [[ ! -x "./scripts/check-android-env.sh" ]]; then
chmod +x "./scripts/check-android-env.sh"
fi
./scripts/check-android-env.sh connected
if [[ ! -x "./gradlew" ]]; then
chmod +x ./gradlew
fi
adb start-server >/dev/null
DEVICES="$(adb devices | awk 'NR>1 && $2=="device" {print $1}')"
if [[ -z "${DEVICES}" ]]; then
echo "No connected Android device/emulator detected."
echo "Connect a device (adb devices) or start an emulator, then rerun."
exit 1
fi
echo "Connected devices:"
printf ' - %s\n' ${DEVICES}
if [[ "$#" -gt 0 ]]; then
TASKS=("$@")
else
TASKS=("connectedDebugAndroidTest")
fi
echo "Running Gradle tasks: ${TASKS[*]}"
./gradlew --no-daemon "${TASKS[@]}"