车机(Android 系统)上的 ADB / 无线调试管理工具,附带开机自启等系统级能力。
| 左栏 | 中栏 | 右栏 |
|---|---|---|
| USB 调试开关 + 底层状态 | 配对设备 / 配对码 / 配对端口 / 二维码 | (底部)检测更新 / 退出、作者信息 |
| 无线 ADB 开关 | 已配对设备 | |
| 无线 ADB 状态(状态、IP:端口、无线客户端) |
中栏与右栏各自独立上下滑动;三栏从上到下依次为:标题区 → 内容区(左:USB 调试 / 无线 ADB 开关;状态信息固定在左栏底部)→ 操作区。
- USB ADB 开关:切换系统 ADB 及
adbd服务。默认只切sys.usb.config(加/去adbfunction,摘完为空才落到none)与adbd,不再把调试口切成 host;开关状态由系统持久化保存(与原生开发者选项一致,不再开机强制关闭);左栏实时显示底层config/adbd/ 调试口角色,设置项与底层不一致时该行变橙 - 无线 ADB 开关:开启/关闭系统无线调试(端口由 adbd 动态分配并 mDNS 广播,不再固定 5555),走热切换:只改
adb_wifi_enabled让 adbd 自己起/停 TLS 监听,不杀进程,因此不牵连有线 USB 调试,也无需二次确认(少数 ROM 热切换不生效时才重启 adbd 兜底);异步执行不阻塞 UI,实时显示已连接客户端。切换时会顺带把明文端口service.adb.tcp.port置-1——原生只管adb_wifi_enabled、不碰明文端口,这里是刻意的安全强化(关掉无需配对的明文入口),会断掉别人用adb tcpip 5555建立的连接 - 开关交互(全部开关统一):USB 调试 / 无线 ADB 都改为「真实状态确认后才落定」——拨动后开关先停在拨动前的状态并置灰、文案显示「开启中/关闭中」,后台轮询等底层真正生效,成功才切到目标状态,失败则原地不动并提示;期间轮询不会把开关掰回去,不留「看着开了其实没开」的假状态。动过 adbd 会作废配对码/配对端口,界面上的旧值会一并清除
- 无线 ADB 后台保活:开关的状态会被记住(仅记住「用户上次是否希望开启」)。用户手动开启后,若被系统重置(熄屏省电、
adbd被杀、ROM 清理属性),AdbService会在 10 秒级检测到并自动重开;用户手动关闭则不会被拉起 - 撤销 USB 调试授权:等同开发者选项里的同名按钮,通过
IAdbManager.clearDebuggingKeys()清空系统 adb keystore;点按钮会先二次确认。执行后不重启 adbd(避免掐断正在调试的连接),被撤销的电脑下次连接时需重新确认授权 - 无线调试配对码:生成 6 位配对码(Android 11+),支持配对码与二维码两种方式;二维码里的服务名取 mDNS 上 adbd 真实注册的那个(拿不到才退回
adb-<serial>),避免扫码时adb找不到配对服务 - 已配对设备 / 忘记设备:列表 = 本地档案 + 系统侧配对凭证(本地档案丢失也能列出来);点「忘记」会调
IAdbManager.unpairDevice()删除系统里的配对凭证,与原生一致——只删本地记录的话电脑照样能连,属于假解绑 - 服务器更新检测(占位):从更新服务器拉取
version.json检测新版本并自动下载安装(服务器地址暂为占位,见MainActivity.UPDATE_BASE_URL) - 开机自启常驻:开机通过前台服务拉起并监听 ADB 状态变化;USB 调试状态不再被改写,由系统按持久化的
ADB_ENABLED自行恢复(与原生一致)
车机上通常有多个 USB 控制器,开关 USB 调试只碰调试口那一个:
| 控制器 | 角色 | 对应 | 本应用是否操作 |
|---|---|---|---|
调试口(如 a600000.ssusb) |
peripheral / device | 主驾USB1、USB 调试 | 是 |
其他口(如 a800000.ssusb) |
host | U 盘、4G 模组等外设 | 否 |
- 控制器不写死:启动时从
/sys/class/udc探测,再按候选路径解析出mode节点,适配不同内核布局;写入后回读校验,失败会在界面上报。 sys.usb.config虽然是全局属性,但 gadget 只挂在调试口那个 UDC 上,所以重新枚举只发生在调试口;host 那一路的 U 盘 / 4G 模组不经过 gadget,不受影响。- 关闭 USB 调试是「从 composition 里摘掉
adb」而不是清空整口:与原生开发者选项一致,MTP 等其它 function 会保留;摘完为空才落到none(这台车 persist 就是纯adb,实际结果与写none相同)。刻意不写mtp:这类车机没有 MTP function,写mtp要么切换失败、要么反而把 MTP 暴露给电脑。
| 档位 | 动作 | 影响面 |
|---|---|---|
LEVEL_SILENT |
只 ctl.stop/start adbd |
不重枚举,电脑侧仅 offline |
LEVEL_CONFIG(默认) |
+ sys.usb.config 加/去 adb(摘完为空才 none) |
调试口重新枚举一次,其他口不受影响 |
LEVEL_ROLE |
+ 控制器角色 peripheral ↔ host |
该口失去 device 能力,同口 CarLife/AOA 失效(预留档位,当前无 UI 入口) |
另外,开启 USB 调试时若调试口正停在 host(这车冷上电就是 host),applyUsbAdb 会自动拉回 peripheral,因此不需要、也不提供手动切角色的入口。
部分 ROM(含这类车机)会监听 Settings.Global.ADB_ENABLED 并自行重算 sys.usb.config。
实测在这台车机上:只要写入 adb_enabled=0,系统就立刻把 composition 切到 none 并停掉 adbd。
所以本应用先切底层、最后再写设置项。顺序反过来时,系统异步重算的结果会覆盖刚写入的 composition,导致开关结果与预期不符。
Settings.Global.ADB_ENABLED 由系统持久化保存,开机后系统自己按保存的值恢复(composition 与 adbd 一并恢复),本应用不再在开机时改写它。
BootReceiver 只负责拉起 AdbService,不再调 AdbCtl.setUsbAdb(false)。
历史行为:早期版本把「默认关闭」挂在
MainActivity.onCreate上(每次开界面都掐断一遍), 后来改为开机广播执行一次;现版本已去掉——与原生开发者选项保持一致,用户开了就一直是开的。 若确实需要「每次上电都回到关闭」,在BootReceiver.onReceive()里补一次AdbCtl.setUsbAdb(app, false)即可。
注意:系统恢复 USB 调试后,插上电脑时仍需系统弹出「允许 USB 调试吗?」授权(车机 ROM 自带该弹窗)。
AdbService 以前台服务常驻(常态通知 + PARTIAL_WAKE_LOCK + Wi-Fi 锁),职责:
- 轮询
Settings.Global.ADB_ENABLED与service.adb.tcp.port,变化时提示; - 自动重开:
AdbCtl.repairIfNeeded()每 10 秒检查一次(内部再做 15 秒节流), 仅当「用户期望开启 且 没有客户端在线 且(属性被重置 /adbd不在 / 端口没监听)」时才重启 adbd; - 网络从休眠恢复(Wi-Fi 重连)时立刻做一次修复检查。
有客户端在线时绝不重启 adbd,避免把正在使用的连接掐断。
前往 Releases 获取最新版本 APK(打 tag 后由 CI 自动构建发布)。
本应用为 platform 签名的系统应用,通过 ROM 预置或
adb install安装,无法上架应用商店。
bash ./build.sh产物:bin/apk/ADBManager_v<version>_<date>.apk(如 ADBManager_v1.7.0_20260921.apk)
依赖:Android SDK(ANDROID_HOME,build-tools 36 + platform 36)、JDK 11+、可联网环境。无需 Gradle / Android Studio。
默认用 AOSP 公开的 platform 测试密钥(公签),证书指纹固定为:
SHA-256: C8A2E9BCCF597C2FB6DC66BEE293FC13F2FC47EC77BC6B2B0D52C11F51192AB8
- 首次构建自动下载到
sign/(已.gitignore,不入库),后续复用; - 想明确「只用公签」、不想被
sign/里别的文件影响:USE_AOSP_TESTKEY=1 bash ./build.sh(公签会单独缓存在sign/aosp/,且下载后按上面的指纹校验,下载错文件会直接报错); - 想换源:
AOSP_KEY_BASE(备用源AOSP_KEY_BASE_MIRROR); - 构建时会打印所用证书的 SHA-256,并对产物做回验(v1+v2 均有效、指纹一致),不一致直接构建失败——避免「以为换了 key,产物其实还是旧的」。
本应用是 platform 签名的系统应用(sharedUserId=android.uid.system),
APK 签名必须与车机 ROM 的 platform 密钥完全一致,否则报 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE。
按顺序自测(连上 adb 后执行):
# 1) 这台 ROM 到底是不是公签(test-keys)
adb shell getprop ro.build.tags # test-keys → 可以装;release-keys → 装不了
# 2) 取 ROM 自己的 platform 证书,和上面的公签指纹对比
adb pull /system/framework/framework-res.apk /tmp/fr.apk
java -jar tools/apksigner.jar verify --print-certs /tmp/fr.apk
# 3) 车机上是不是已经装了同包名但不同签名的旧版(同名不同签名无法覆盖安装)
adb shell dumpsys package com.qianxian.adbmanager | grep -i versionName结论与处理:
| 现象 | 原因 | 处理 |
|---|---|---|
ro.build.tags=release-keys |
ROM 用厂商私有 platform key | 必须拿到该车型的 platform.pk8 / platform.x509.pem 重签(放 sign/ 或用 PLATFORM_PK8/PLATFORM_PEM 指定);拿不到就装不了,这是 Android 的硬限制 |
| 指纹不一致但 ROM 是 test-keys | 装了别的渠道/别的密钥打的包 | 先 adb uninstall com.qianxian.adbmanager(老包名还要 adb uninstall com.vendor.adbmanager),再装 |
INSTALL_FAILED_UPDATE_INCOMPATIBLE |
同包名不同签名 | 同上,先卸载 |
adb install -r "$(ls -t bin/apk/ADBManager_v*.apk | head -1)"若车机上装有其它签名版本的 ADBManager(含 v1.6.x 及更早的旧包名
com.vendor.adbmanager), 覆盖安装会被签名校验挡掉,需先卸载再装。
- v2.5.0(2026-11-05):界面按 1920x1080(横屏三栏)重排,解决低高度车机上「太挤、内容被裁」的问题——① 外层与栏内留白、栏间距整体收紧;② 标题/正文/按钮字号与按钮高度分级下调,一屏内三栏内容不再溢出,中栏按钮与右栏标题不再被切掉;③ 顶栏右侧的版本号与 UID 改为上下两行竖排,避免与状态文字挤在一行;④ 右栏「系统 / 检测更新 / 退出」改为与另外两栏同基线顶部对齐,作者署名固定栏底
- v2.4.2(2026-11-05)(构建):重新构建发布,功能同 v2.4.1,仍为「自签正式版 + AOSP 公签版」双 APK 输出,可直接覆盖升级
- v2.4.1(2026-11-04)(构建):
build.sh改为双版本签名输出——同一次构建产出「自签正式版」与「AOSP 公签版」两个 APK,均带 v1+v2 签名,公签版独立缓存密钥并校验指纹,产物名以_aosp-testkey后缀区分;Release 同时附上两个 APK,按车机 ROM 签名需求自选 - v2.4.0(2026-10-20):对齐原生开发者选项——① 配对广播状态码修正:
WIRELESS_STATUS_CONNECTED由 4 改为 5(4 是WIRELESS_STATUS_ADB_PORT,只在配对结果广播里带端口),原值导致onPaired不触发、已配对设备不会自动记录;② 二维码服务名改用 mDNS 上 adbd 真实注册的名字(拿不到才退回adb-<serial>),避免扫码配对找不到服务;③ 「忘记设备」改为调IAdbManager.unpairDevice()删除系统侧配对凭证(原来只删本地显示,属于假解绑),列表合并展示系统侧凭证;④ 关闭 USB 调试由写死none改为「从 composition 摘掉adb」,其它 function 保留;⑤ composition 判定改为按逗号精确匹配adb;⑥ 配对超时后收尾disablePairing()(拿到码时留 3 分钟给电脑执行adb pair再取消);⑦ 自动修复显式跳过「有客户端在线」的时刻;⑧ 无线客户端解析在netstat不可用时回退/proc/net/tcp;⑨ 开机不再强制关闭 USB 调试,状态交由系统持久化恢复;⑩minSdkVersion提到 30(无线调试为 Android 11+ 能力) - v2.3.0(2026-10-19):移除「USB 供电控制」——右栏不再有主驾USB1 / 主驾USB2 供电开关,同时移除
MainActivity里的toggleUsbPower/updateUsbPowerStatus/updateUsbPowerSwitch/ensureUsb2PowerDefaultOn/writeUsbPower/readUsbPowerValue及usbPowerBusy、USB_POWER_SETTLE_ROUNDS;不再读写/sys/devices/platform/usbpower/*节点,启动时也不再默认开启主驾USB1 供电 - v2.2.0+(构建):
build.sh增加密钥自检与产物回验——构建前校验 pk8/x509 是否为同一对密钥、打印所用证书 SHA-256,签名后回验 APK 指纹与 v1/v2 有效性,不一致即构建失败;新增USE_AOSP_TESTKEY=1(强制只用 AOSP 公签,独立缓存并校验指纹)、PLATFORM_PK8/PLATFORM_PEM/PLATFORM_KS系列环境变量;使用 AOSP 公签时给出适用 ROM 提示 - v2.2.0(2026-09-27):无线 ADB 改为热切换(
AdbCtl.applyWirelessHot():只改adb_wifi_enabled,等 adbd 自己起/停 TLS 监听,不动进程),不再无条件重启 adbd,因此切无线不再牵连有线 USB 调试;据此移除切换无线前的「会断开有线调试」二次确认(下发未生效时回退开关到拨动前状态);USB 调试、USB 供电开关统一改为「真实状态确认后才落定」(先停在旧状态 + 置灰 + 「开启中/关闭中」,轮询等底层生效,失败原地回退),新增adbSwitchBusy/usbPowerBusy避免轮询把进行中的开关掰回去;新增AdbCtl.wirelessNeedsAdbd();动过 adbd 后清除界面上的旧配对码与配对端口 - v2.1.0(2026-09-23):移除右栏「主驾USB1 角色」开关及其
AdbCtl.setDebugPortRole()——开启 USB 调试时applyUsbAdb会自动把停在 host 的调试口拉回 peripheral,手动切回已无意义,而主动切 host 是破坏性操作且无日常场景;角色状态看左栏底层状态行的「调试口」即可。作为补偿,2 秒轮询改为刷新updateStatus(),左栏那行保持实时 - v2.0.0(2026-09-23):USB 调试按硬件接口分档,默认不再把调试口切成 host(避免同口 CarLife/AOA 失效);新增
UsbHw动态探测控制器(不再硬编码a600000)并回读校验;关闭时sys.usb.config由mtp改为none;默认关闭改走与手动开关同一出口(AdbCtl.setUsbAdb),并改为只在开机广播执行一次(原先挂在 Activity 启动上,每次开界面都掐断 USB 调试);设置项改为最后写入(避免 ROM 监听adb_enabled自行重算 composition 覆盖我们的写入);左栏新增底层状态行;右栏新增「主驾USB1 角色」独立开关;切换无线 ADB 前若有线调试在用的会二次确认 - v1.9.0(2026-09-23):新增「撤销 USB 调试授权」(左栏 USB 调试区下方,走系统
IAdbManager.clearDebuggingKeys(),带二次确认) - v1.8.0(2026-09-23):UI 重排(左栏:USB 调试 / 无线 ADB 开关 + 底部状态;右栏:USB 供电 + 底部检测更新/退出);中栏精简为单纯配对功能并支持上下滑动;移除 USB 供电的状态描述文案;关闭全部 Toast 提示(
TOAST_ENABLED开关控制,可恢复) - v1.7.0(2026-09-21):包名改为
com.qianxian.adbmanager(旧包名需先卸载);构建改用 AOSP 公开 platform 测试密钥并自动下载;清理冗余资源与死代码;修复 CI 产物路径失效 - v1.6.3(2026-09-21):合并「无线 ADB」与「无线调试」两个开关(同为
adb_wifi_enabled),中栏只保留只读状态行 - v1.6.2(2026-09-21):移除移动数据开关;右栏改为可滚动;构建产物名带版本号与日期
- v1.6.1(2026-09-15):顶栏显示版本号(右侧小字
v<versionName>) - v1.6.0(2026-09-15):三栏布局重构;按钮全部改为滑块并修复拉伸变形;修复 USB 连接状态误报;主驾USB1 供电启动默认开启;移除 USB3.2 控制;无线 ADB 开关异步化即时响应
- v1.5.1:AdbService 后台监听、状态栏遮挡修复、APP 内置静默安装
- v1.4.0:ADB 默认关闭策略、横屏三栏 UI 初版