Android 无 Root 固定 ADB 5555:Termux Widget 与 Tailscale 实践记录
实验目标与技术路线
目标是在无 Root 的 Android 手机上,将系统无线调试产生的随机 ADB 端口切换为固定的 TCP 5555,并借助 Tailscale 的稳定设备名,使 Ubuntu 或 macOS 最终只需执行:
adb connect oppo-reno6-pro-5g:5555
实验环境为 Android 13 / ColorOS、Termux、Termux:Widget、Termux:API、Android Platform Tools 和 Tailscale。整体链路如下:
Android 无线调试随机端口
↓
Termux 连接本机 adbd
↓
adb tcpip 5555
↓
adbd 固定监听 TCP 5555
↓
Tailscale 提供稳定主机名
↓
Ubuntu/macOS 直接连接
这里需要明确两个职责:Termux 脚本负责启动 5555,Tailscale 只负责网络可达性和稳定名称。Tailscale 不会主动开启 ADB 服务。
原理验证
Android 无线调试存在两个不同端口。“使用配对码配对设备”页面显示的是一次性配对端口,只用于:
adb pair 192.168.51.138:36435 057615
无线调试主页显示的 IP address & Port 才是实际连接端口,例如:
adb connect 192.168.51.138:36555
完成连接后,可将 adbd 切换到固定端口:
adb -s 192.168.51.138:36555 tcpip 5555
验证结果如下:
adb connect 192.168.51.138:5555
adb devices -l
当设备状态为 device 时,说明当前 ColorOS 允许从无线调试 TLS 模式切换到传统 TCP ADB 模式。
随后开启手机和电脑上的 Tailscale,测试稳定设备名:
adb connect oppo-reno6-pro-5g:5555
连接成功说明完整链路成立,后续不再依赖手机不断变化的 Wi-Fi 地址。
手机端 Termux 也应验证本机回环连接:
adb connect 127.0.0.1:5555
adb -s 127.0.0.1:5555 get-state
预期输出:
device
脚本应始终使用明确的 ADB serial,例如:
adb -s 127.0.0.1:5555 get-state
而不是直接运行不带 -s 的 adb shell 或 adb tcpip。这是因为 Termux 中可能同时出现 127.0.0.1:5555 和 emulator-5554,未指定设备时可能触发 more than one device/emulator。
手机端实现
Termux 中安装依赖:
pkg update
pkg install android-tools termux-api
可选安装 jq,用于可靠解析 Termux:API 返回的 JSON:
pkg install jq
Android 端还需要安装 Termux、Termux:Widget 和 Termux:API。三个应用建议来自同一软件源,避免插件签名不一致。
主逻辑脚本位于:
$HOME/bin/adb5555
它至少需要支持以下接口:
adb5555 --status
adb5555 --port 43099
adb5555 --endpoint 127.0.0.1:43099
主脚本的职责是检查 127.0.0.1:5555、连接当前无线调试端口、执行 adb tcpip 5555,并在切换后再次验证固定端口。
本机实际测试表明,ColorOS 上:
getprop service.adb.tls.port
返回为空,而:
adb mdns services
也无法发现 _adb-tls-connect._tcp。因此无法可靠地自动获取重启后产生的新端口,但显式传入端口可以成功:
adb5555 --port 43099
实验输出为:
[adb5555] 正在验证无线调试端点:127.0.0.1:43099。
[adb5555] 已连接端点:127.0.0.1:43099,正在执行 adb -s 127.0.0.1:43099 tcpip 5555。
[adb5555] ADB 5555 已经可用。
因此问题仅存在于“端口自动发现”,不影响配对授权、ADB 自连接以及 tcpip 5555。
Termux:Widget 启动脚本
桌面启动脚本保存为:
$HOME/.shortcuts/ADB-5555
当前实现如下:
#!/data/data/com.termux/files/usr/bin/bash
set -Eeuo pipefail
readonly MAIN="$HOME/bin/adb5555"
readonly LOG_FILE="$HOME/.cache/adb5555-widget.log"
has_termux_api_app() {
/system/bin/pm path com.termux.api >/dev/null 2>&1
}
notify() {
local message="$1"
if has_termux_api_app && command -v termux-toast >/dev/null 2>&1; then
termux-toast "$message" >/dev/null 2>&1 || true
fi
printf '%s\n' "$message"
}
write_log() {
mkdir -p "${LOG_FILE%/*}"
printf '%s\n' "$1" > "$LOG_FILE"
}
if "$MAIN" --status >/dev/null 2>&1; then
notify 'ADB 5555 已经可用。'
exit 0
fi
if ! has_termux_api_app || ! command -v termux-dialog >/dev/null 2>&1; then
notify '缺少 Termux:API 应用。请安装该 Android 应用,并在 Termux 执行:pkg install termux-api'
exit 1
fi
result="$(
termux-dialog text \
-t 'ADB 无线调试端口' \
-i '请输入“无线调试”主页显示的 IP:端口,例如 172.19.0.1:37405' \
2>/dev/null || true
)"
if command -v jq >/dev/null 2>&1; then
port="$(
printf '%s' "$result" |
jq -r \
'if .code == 0 and (.text | type == "string")
then .text
else empty
end' \
2>/dev/null || true
)"
else
port="$(
printf '%s' "$result" |
tr -d '\r\n' |
sed -n \
's/.*"text"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p'
)"
fi
if [[ "$port" == *:* ]]; then
command=(--endpoint "$port")
elif [[ "$port" =~ ^[0-9]+$ ]] &&
(( port >= 1024 && port <= 65535 )); then
command=(--port "$port")
else
write_log "对话框返回内容:$result"
notify 'ADB 端点无效或已取消。请输入 IP:端口,或仅输入端口。'
exit 1
fi
if output="$("$MAIN" "${command[@]}" 2>&1)"; then
write_log "$output"
notify 'ADB 5555 已启动。'
exit 0
fi
write_log "$output"
notify 'ADB 启动失败;请在 Termux 查看 ~/.cache/adb5555-widget.log'
exit 1
该脚本采用严格 Bash 模式,并将核心逻辑委托给 $HOME/bin/adb5555。启动时首先调用 --status 检查固定端口,若 5555 已可用则直接退出,保证重复点击不会反复重启 adbd。
当固定端口不可用时,脚本检查 Termux:API 应用与 termux-dialog 命令,并弹出无线调试端口输入框。
termux-dialog 返回 JSON。脚本优先使用 jq 解析,在未安装 jq 时退回 sed;输入既可以是完整的 IP:端口,也可以只输入端口号。纯端口必须处于 1024~65535 范围内。
最终,Widget 根据输入调用:
adb5555 --port 43099
或者:
adb5555 --endpoint 192.168.51.138:43099
执行结果会保存到:
$HOME/.cache/adb5555-widget.log
成功时显示 Toast,失败时保留完整日志供排查。
完成后设置权限并检查语法:
chmod 700 "$HOME/bin/adb5555"
chmod 700 "$HOME/.shortcuts/ADB-5555"
bash -n "$HOME/bin/adb5555"
bash -n "$HOME/.shortcuts/ADB-5555"
随后在 Android 桌面添加 Termux:Widget,并选择 ADB-5555。
最终操作流程与结论
手机每次重启后,固定 5555 通常会失效。实际操作流程为:
开启开发者选项中的“无线调试”
↓
查看主页中的 IP address & Port
↓
点击桌面的 ADB-5555 Widget
↓
输入冒号后的端口,例如 43099
↓
脚本连接 127.0.0.1:43099
↓
脚本执行 adb tcpip 5555
↓
开启 Tailscale
电脑端最终只需运行:
adb connect oppo-reno6-pro-5g:5555
建议进一步使用明确的 serial:
adb -s oppo-reno6-pro-5g:5555 shell
adb -s oppo-reno6-pro-5g:5555 install app.apk
adb -s oppo-reno6-pro-5g:5555 push file.txt /sdcard/Download/
本实验说明,无 Root 环境下仍可以利用 Android 原生无线调试完成授权,再由 Termux 将 adbd 切换至固定 5555。对于无法通过 getprop 或 mDNS 自动发现随机端口的厂商系统,使用 Termux:API 弹窗接收端口,是一种比全端口扫描更稳定、透明且易维护的折中方案。
该方案不得将 5555 映射到公网。推荐仅在可信局域网或个人 Tailscale Tailnet 内使用。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 kipleyarch@gmail.com