butubb f100301a56 feat: 扫码配置——扫平台上生成的二维码,一次配好(v1.4)
场景:设备还没接进平台、或人站在机架前不想插线时,原来得在手机上手动输平台地址和
令牌(还可能漏指纹)。现在平台「设备池」里点某台设备的「二维码」,手机上点
「扫码配置」扫一下即完成。

- ScanActivity:Camera1 + **ZXing core**(刻意不用 ML Kit —— 那要 Google Play 服务,
  国内机型普遍没有);QR 的定位图案让 ZXing 自带旋转不变性,不用手动转 YUV 帧
- 二维码内容(平台侧生成):{"v":1,"server":…,"token":…,"fingerprint":…,"name":…}
  —— 指纹只能由平台给(应用读不到 ro.serialno,见 Prefs 说明),扫码正好是最省事的传递方式
- MainActivity 加「扫码配置」按钮(原「配置」改名「手动配置」)

实机踩到的坑(已修):
- **相机必须在拿到权限后再打开**:surfaceCreated 早于权限回调触发,先开相机会报
  "Fail to connect to camera service" 并把流程直接断掉(第一次实测就是这么挂的)
  → 改成 surfaceCreated 只记下 holder,授权回调里再开
- `params.previewSize = size` 编译不过:setPreviewSize 收的是两个 int 不是 Size 对象

实测(A07 / USB 连接):扫码 → 相机启动 → 解码 → 保存 → 立刻拉清单,
平台认出「A07」,全程无需打字、无需 adb。
2026-09-13 16:42:07 +08:00

设备 Agent(DeviceAgent)

装在每台 Android 手机上的设备端补位 App,配合 auto_control 平台使用。 平台通过 adb 驱动设备;这个 App 负责三件 adb 干不好/干不了的事:

能力 为什么 adb 不行 入口
剪贴板注入 Android 10+ 只有有焦点的应用能写剪贴板,shell/后台写会被系统静默丢弃 ClipActivity(透明 Activity,adb 拉起)
应用分发(商店) adb install 会被 MIUI 的「USB 安装」拦成 USER_RESTRICTED;由设备上的 App 自己调系统安装器走的是普通安装流程,不触发那道拦截 MainActivity(商店界面,自己联网拉清单)
设备身份显示 以前要把 HTML 大字页推给设备浏览器打开,依赖浏览器 InfoActivity(全屏大字,adb 拉起)

接口契约

平台的接口协议见 ../auto_control/doc/DEVICE_AGENT.md(那是两个仓库共享的契约; 改协议必须同时改两边)。本仓库里也留了一份副本:INTERFACE.md。

快速开始

# 1. 构建(需要 JDK 17 + Android SDK;也可以用 Android Studio 直接打开)
./gradlew assembleDebug

# 2. 装到设备(平台用网络 adb 管理设备,serial 形如 IP:5555)
adb -s 192.168.20.100:5555 install -r app/build/outputs/apk/debug/app-debug.apk

# 3. 一次性配置平台地址与令牌(不用在手机上手输)
adb -s 192.168.20.100:5555 shell am start -n com.example.deviceagent/.ConfigActivity \
    --es server "http://192.168.20.220:18050" --es token "<平台面板里的设备令牌>"

# 4. 自检:确认装上了、看是哪一版
adb -s 192.168.20.100:5555 shell am start -n com.example.deviceagent/.PingActivity
adb -s 192.168.20.100:5555 shell cat /sdcard/Android/data/com.example.deviceagent/files/status.json

# 5. 手动试试剪贴板注入
adb -s 192.168.20.100:5555 shell am start -n com.example.deviceagent/.ClipActivity \
    --es text_b64 "$(printf '测试中文' | base64)"

# 6. 让设备显示自己的身份大字页
adb -s 192.168.20.100:5555 shell am start -n com.example.deviceagent/.InfoActivity \
    --es name "A08" --es ip "192.168.20.100" --es serial "192.168.20.100:5555" \
    --es server "http://192.168.20.220:18050"

然后用手机打开 App 图标 → 就是应用商店(前提是平台侧已启用设备端商店并给了令牌)。

权限说明

只申请三个,都是必需的:

  • INTERNET —— 从平台拉应用清单、下载 APK
  • REQUEST_INSTALL_PACKAGES —— 调系统安装器装应用(首次会引导去系统设置里授权)
  • ACCESS_NETWORK_STATE —— 判断有没有网

不需要 root、不需要设备管理员、不常驻后台、不申请任何读取隐私的权限。

代码结构

app/src/main/java/com/example/deviceagent/
  MainActivity.kt    应用商店主界面(清单/下载/调安装器/回报)
  ClipActivity.kt    剪贴板注入(透明,等窗口获得焦点后再写)
  InfoActivity.kt    设备身份全屏大字页
  ConfigActivity.kt  一次性配置下发(平台用 adb 推地址+令牌)
  PingActivity.kt    自检(版本/指纹/配置状态,写 logcat + status.json)
  Api.kt             平台接口客户端(HttpURLConnection,无第三方库)
  Prefs.kt           配置存储 + 设备指纹(getprop ro.serialno)

刻意只依赖 androidx.core(就为了 FileProvider):HTTP 用 HttpURLConnection、 JSON 用系统内置的 org.json,依赖越少越不容易被构建问题绊住。

S
Description
No description provided
Readme
85 KiB
Languages
Kotlin 100%