Files
device_agent/app/src/main/java/com/example/deviceagent/ConfigActivity.kt
T
butubb 2580cfaead feat: 设备端 Agent 首个版本——剪贴板注入 / 应用商店 / 身份显示 / 配置下发
配合 auto_control 平台的设备端补位 App(接口契约见 INTERFACE.md,与平台仓库
doc/DEVICE_AGENT.md 是同一份)。

四个 adb 可拉起的 Activity + 一个商店界面:
- ClipActivity    剪贴板注入(透明 Activity,**必须等窗口获得焦点再写** ——
                  Android 10+ 只有前台应用能写剪贴板,这正是 u2 set_clipboard
                  "成功但内容被丢弃"的原因);写完立即退出,不驻留
- InfoActivity    全屏大字显示设备身份(名称/IP/序列号/平台地址),
                  替代原来"推 HTML 让设备浏览器打开"那套
- ConfigActivity  一次性配置下发(平台用 adb 把 server/token/指纹推进来),
                  一批设备不用一台台手输
- PingActivity    自检(版本/指纹/配置状态),结果写 logcat + 外部私有目录的
                  status.json,平台据此判断"装没装、哪一版"
- MainActivity    应用商店:拉平台清单 → 选应用 → 安装;已装的显示「已安装」,
                  有新版显示「更新到 vX」

实机踩出来的几个坑(都已处理):
- **应用身份读不到 ro.serialno**(shell 能读、应用被 SELinux 挡)→ 指纹改由平台
  通过 ConfigActivity 下发(平台本来就知道),本机 getprop 只作兜底
- **Android 9+ 默认拦明文 HTTP** → 平台是局域网 http,需 usesCleartextTraffic
- **Android 11+ 软件包可见性** → 不加 QUERY_ALL_PACKAGES 会"明明装了却显示未安装"
- **MIUI 安装确认不止一步** → 装完检测窗口给到 3 分钟(人会依次点继续→勾选→继续更新)
- 上报带重试(实测遇到过一次网络抖动导致 timeout)

构建:JDK 17 + Android SDK(minSdk 29 / targetSdk 34),只依赖 androidx.core,
HTTP 用 HttpURLConnection、JSON 用系统内置 org.json。
2026-09-13 16:30:16 +08:00

48 lines
1.8 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.example.deviceagent
import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
/**
* 一次性配置下发(透明 Activity,由平台用 adb 拉起):
*
* adb shell am start -n com.example.deviceagent/.ConfigActivity \
* --es server http://192.168.20.220:18050 --es token <设备令牌> \
* --es fingerprint <ro.serialno>
*
* 有了它,一批设备不用一台台手输地址和令牌。
* 只写传进来的字段;三个都能单独更新。
*
* ⚠️ fingerprint 必须由平台推下来:实测应用身份读不到 ro.serialno
*(shell 能读、应用被 SELinux 挡住),而平台通过 adb 本来就知道这个值。
*/
class ConfigActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val server = intent?.getStringExtra("server")
val token = intent?.getStringExtra("token")
val fp = intent?.getStringExtra("fingerprint")
if (server.isNullOrEmpty() && token.isNullOrEmpty() && fp.isNullOrEmpty()) {
Log.w(TAG, "ConfigActivity 没收到 server/token/fingerprint")
finish()
return
}
try {
Prefs.save(this, server, token, fp)
val msg = "配置已更新:${Prefs.server(this)} / 令牌${if (Prefs.token(this).isEmpty()) "空" else "已设置"} / 指纹${if (Prefs.fingerprint(this).isEmpty()) "空" else "已设置"}"
Log.i(TAG, msg)
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
} catch (e: Exception) {
Log.e(TAG, "配置写入失败: ${e.message}")
}
finish()
}
companion object {
const val TAG = "DeviceAgent"
}
}