Skip to content

Instantly share code, notes, and snippets.

@1d10t
Created April 11, 2026 13:36
Show Gist options
  • Select an option

  • Save 1d10t/2ce712e7b506c529beafb65ca56e84aa to your computer and use it in GitHub Desktop.

Select an option

Save 1d10t/2ce712e7b506c529beafb65ca56e84aa to your computer and use it in GitHub Desktop.
termux-api Bluetooth SCO: build & test scripts
#!/usr/bin/env bash
# Download and install official Termux debug APK (signed with testkey_untrusted.jks).
#
# Required on a CLEAN device before installing our termux-api build.
# com.termux.api uses sharedUserId=com.termux — both apps must be signed
# with the same key. GitHub debug builds use the same key as our APK.
# F-Droid builds use a different key and will conflict.
#
# Run this script only if:
# - the device has no Termux installed, OR
# - Termux was installed from F-Droid (different key — must be replaced)
# WARNING: replacing F-Droid Termux will erase all Termux data on the device.
set -euo pipefail
TERMUX_VERSION="v0.118.3"
ARCH="${1:-arm64-v8a}" # pass armeabi-v7a / x86_64 / x86 / universal as argument
APK_NAME="termux-app_${TERMUX_VERSION}+github-debug_${ARCH}.apk"
APK_URL="https://github.com/termux/termux-app/releases/download/${TERMUX_VERSION}/${APK_NAME}"
APK_PATH="/tmp/${APK_NAME}"
echo "==> Downloading Termux ${TERMUX_VERSION} debug (${ARCH})"
wget -q --show-progress -O "$APK_PATH" "$APK_URL"
echo "==> Uninstalling existing Termux (if any)"
adb uninstall com.termux 2>/dev/null || true
echo "==> Installing $APK_NAME"
adb install "$APK_PATH"
echo ""
echo "Done. Now run 1-build-apk.sh and 2-install-apk.sh to install termux-api."
#!/usr/bin/env bash
# Build termux-api APK (debug)
set -euo pipefail
REPO="$HOME/life/projects/termux-api"
ANDROID_SDK="$HOME/Android/Sdk"
ANDROID_NDK="$HOME/Android/Sdk/ndk/26.3.11579264"
echo "==> Writing local.properties"
cat > "$REPO/local.properties" << EOF
sdk.dir=$ANDROID_SDK
ndk.dir=$ANDROID_NDK
EOF
echo "==> Building debug APK"
cd "$REPO"
chmod +x gradlew
./gradlew assembleDebug
echo ""
echo "Done: $REPO/app/build/outputs/apk/debug/"
ls "$REPO/app/build/outputs/apk/debug/"*.apk
#!/usr/bin/env bash
# Install termux-api APK via ADB
set -euo pipefail
REPO="$HOME/life/projects/termux-api"
APK=$(ls "$REPO/app/build/outputs/apk/debug/"*.apk 2>/dev/null | head -1)
if [ -z "$APK" ]; then
echo "ERROR: APK not found. Run 1-build-apk.sh first."
exit 1
fi
echo "==> APK: $APK"
echo "==> Force-stopping com.termux.api"
adb shell am force-stop com.termux.api 2>/dev/null || true
# com.termux.api uses sharedUserId=com.termux — all packages in this group
# must be signed with the same key. Our debug key differs from the official
# Termux key, so the old com.termux.api must be fully uninstalled first.
# The main Termux app does NOT need to be reinstalled.
echo "==> Uninstalling old com.termux.api (required: sharedUserId key mismatch)"
if ! adb uninstall com.termux.api; then
echo "NOTE: uninstall failed — package may not be installed, continuing."
fi
echo "==> Installing APK"
adb install "$APK"
echo "==> Granting runtime permissions"
adb shell pm grant com.termux.api android.permission.BLUETOOTH_CONNECT
adb shell pm grant com.termux.api android.permission.RECORD_AUDIO
echo "==> Checking permissions"
adb shell dumpsys package com.termux.api | grep -E "BLUETOOTH|MODIFY_AUDIO|RECORD_AUDIO" || true
echo ""
echo "Done."
#!/usr/bin/env bash
# Push updated shell scripts to device via ADB
# Substitutes @TERMUX_PREFIX@ and copies to /sdcard/, then prompts to run cp inside Termux
set -euo pipefail
SCRIPTS_REPO="$HOME/life/projects/termux-termux-api-package"
TMP_DIR="$(mktemp -d)"
TERMUX_PREFIX="/data/data/com.termux/files/usr"
SCRIPTS=(
termux-microphone-record
termux-audio-sco
)
echo "==> Processing templates (replacing @TERMUX_PREFIX@)"
for name in "${SCRIPTS[@]}"; do
src="$SCRIPTS_REPO/scripts/${name}.in"
dst="$TMP_DIR/$name"
if [ ! -f "$src" ]; then
echo "ERROR: $src not found"
exit 1
fi
sed "s|@TERMUX_PREFIX@|${TERMUX_PREFIX}|g" "$src" > "$dst"
chmod 755 "$dst"
echo " $src -> $dst"
done
echo ""
echo "==> Pushing to /sdcard/ (adb uses device path)"
for name in "${SCRIPTS[@]}"; do
adb push "$TMP_DIR/$name" "/sdcard/$name"
done
rm -rf "$TMP_DIR"
echo ""
echo "==> Done. /sdcard/ is used as a staging area because adb cannot write"
echo " directly to /data/data/com.termux/ without root."
echo " Copy the files to their final location inside Termux on device:"
echo ""
for name in "${SCRIPTS[@]}"; do
echo " cp ~/storage/shared/$name \$PREFIX/bin/$name && chmod 755 \$PREFIX/bin/$name"
done
echo ""
echo "Or paste all at once:"
echo ""
echo -n " "
for name in "${SCRIPTS[@]}"; do
printf "cp ~/storage/shared/%s \$PREFIX/bin/%s && chmod 755 \$PREFIX/bin/%s && " "$name" "$name" "$name"
done
echo "echo OK"
#!/data/data/com.termux/files/usr/bin/bash
# Test Bluetooth SCO microphone recording via termux-microphone-record -s 7
# Records 5 seconds, then plays back via termux-media-player
set -euo pipefail
OUTFILE="/data/data/com.termux/files/usr/tmp/bt-mic-test-$(date +%s).m4a"
echo "==> Enabling Bluetooth SCO..."
termux-audio-sco enable
echo "==> Waiting 3s for SCO channel to establish..."
sleep 3
echo "==> Recording 5 seconds from Bluetooth microphone (source=7)..."
termux-microphone-record -s 7 -f "$OUTFILE" -l 5
echo "==> Waiting for recording to finish..."
sleep 6
termux-microphone-record -q 2>/dev/null || true
echo "==> Disabling Bluetooth SCO..."
termux-audio-sco disable
echo "==> Playing back: $OUTFILE"
termux-media-player play "$OUTFILE"
sleep 8
termux-media-player stop
echo ""
echo "Done. File: $OUTFILE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment