添加 WorkTool 项目的详细交接文档,涵盖项目概述、技术栈、工程结构、运行流程、配置项、构建流程、调试方法及后续维护建议。该文档旨在帮助后续开发人员快速理解项目整体架构、关键代码位置和运行机制,便于后续维护与二次开发。
21 KiB
21 KiB
WorkTool 项目交接文档
本文档面向后续接手的开发人员,帮助快速理解 WorkTool 的整体架构、运行机制以及关键代码位置,便于后续维护与二次开发。
1. 项目概述
- 项目名称:WorkTool
- 主要功能:依附于企业微信 / 微信运行的无人值守群管理机器人,通过无障碍服务和企业微信官方 SDK 实现自动收发消息、建群、拉人、踢人等能力。
- 客户端形态:Android 原生 APP(需运行在一台专用手机上),通过 WebSocket 与后端任务调度平台长连接通信。
- 法规与安全:基于 Android 官方无障碍服务和企业微信官方 SDK,无 Hook / 无 Root / 无内存修改,注意遵守腾讯运营规范与相关法律法规。
更多面向使用方的说明及 API 文档,可参考:
- 项目 README:README.md
- 后端协议文档:BACKEND_PROTOCOL.md
2. 技术栈与运行环境
- 平台:Android
- 语言:Kotlin + Java 混合
- 构建工具:Gradle(使用仓库自带
gradlew) - 最低支持版本:
minSdkVersion 24 - 目标版本:
targetSdkVersion 30 - 编译版本:
compileSdkVersion 30 - Java 版本:
sourceCompatibility 1.8/targetCompatibility 1.8 - IDE 建议:Android Studio(Arctic Fox 及以上版本均可正常打开)
涉及的关键第三方依赖(不完整列举):
- 工具库:
com.blankj:utilcodex(通过com.blankj.utilcode.util.*等类使用) - 日志:
LogUtils(见 LogUtilsInit.kt) - Toast:
com.hjq:toast(ToastUtils) - UI 组件:
Material Components(MaterialAlertDialogBuilder)、QMUI对话框 - 网络通信:
OkHttpWebSocket(见 WebSocketManager.java) - 埋点统计:友盟 (
UMConfigure),TalkingData (TalkingDataSDK) - 企业微信 SDK:
lib_wwapi-*.aar(位于app/libs/)
3. 工程结构总览
根目录主要文件与模块:
app/:主 APP 工程(业务逻辑、UI、无障碍自动化、与后端通信等全部在此)baselibrary/:基础 UI / Adapter 等通用组件floatwindow/:悬浮窗相关实现BACKEND_PROTOCOL.md:客户端与后台 WebSocket 协议说明README.md:面向使用方的简要说明与版本更新记录
多模块声明见:
3.1 app 模块结构
路径:app/src/main/java/org/yameida/worktool/
主要包与职责:
activity/ListenActivity:主控制面板,配置链接号(robotId)、后端 host、开关无障碍与悬浮窗,是日常运维主要入口。LoginActivity:登录相关界面。SettingsActivity/SettingsAdvanceActivity:基础及高级设置。AccessibilityGuideActivity/FloatViewGuideActivity:权限引导页面。BrowserActivity、GetScreenShotActivity:辅助操作页面。
service/WeworkService:无障碍服务实现,负责监控和操作企业微信界面,是自动化的核心。WeworkController:统一调度控制,无障碍操作入口,管理循环任务状态。WeworkLoopImpl/WeworkOperationImpl/WeworkInteractionImpl/WeworkGetImpl:对企业微信不同操作的具体实现(循环拉取任务、执行发送消息、拉群、获取信息等)。PlayNotifyService/PlayNotifyManager:前台服务与通知控制,保障机器人在前台或长时间运行。GlobalMethod.kt/MyLooper.kt:封装通用操作和循环执行器。
utils/- 网络相关:
HttpUtil.kt(REST 接口访问)、OkHttpUtil.kt、WebSocketManager.java。 - 无障碍与权限:
AccessibilityUtil.kt、AccessibilityExtraUtil.kt、PermissionHelper.kt、FlowPermissionHelper.kt、PermissionPageManagement.java。 - 悬浮窗:
FloatWindowHelper.kt,配合floatwindow模块实现全局悬浮按钮。 - 屏幕与截图:
capture/包下的ScreenCaptureUtil、ScreenCaptureUtilByMediaPro、MediaProjectionHolder.kt等。 - 配置与缓存:
CacheUtil.kt、PropUtil.kt、HostTestHelper.kt。 - 其他工具:
RegexHelper.kt、RuntimeUtil.kt、WeworkRoomUtil.kt、WeworkTextUtil.kt等。
- 网络相关:
model/network/:与后端通信的返回体,例如CheckUpdateResult.java、GetMyConfigResult.java。operation/:执行结果封装,如SelectResult.kt。WeworkMessageBean.java/WeworkMessageListBean.kt:WebSocket 消息封装,与BACKEND_PROTOCOL.md一一对应。AppUpdate.java、MyConfigBean.kt等:应用更新 / 机器人配置相关模型。
notification/:通知栏相关封装(PlayNotifyManager.kt)。config/:全局异常处理(GlobalException.java)。observer/:文件监听等辅助(MultiFileObserver.java)。- 顶层文件:
MyApplication.kt:全局 Application,完成 SDK 初始化、前台服务启动等。Constant.kt:全局常量与配置(可持久化到SPUtils)。Demo.kt:示例或测试代码(如有使用可再确认)。
3.2 baselibrary 模块
路径:baselibrary/
- 主要保存通用 UI 组件与 Adapter,例如
RvSimpleAdapter、RvViewHolder。 - 资源文件中包含通用
styles、strings等。 - 项目中作为
app的依赖模块,无业务逻辑。
3.3 floatwindow 模块
路径:floatwindow/
- 浮窗管理:
FloatWindowManager.kt、BaseFloatWindow.java、DefaultFloatService.kt。 - 监听器:
listener/包下FloatWindowListener.kt、OnClickListener.kt等。 - 视图:
view/HiderView.java与相关布局、图片资源。 - 为
app提供悬浮窗入口、暂停 / 启动机器人等操作。
4. 运行流程与关键逻辑
4.1 App 启动流程
入口类:
AndroidManifest.xml中配置MyApplication作为application,主 Activity 为登录或 Listen 页(视具体配置而定)。- MyApplication.kt 负责:
- 初始化
Utils、日志配置(LogUtilsInit)、Gson代理。 - 初始化
ToastUtils。 - 初始化友盟埋点(
UMConfigure),通过SPUtils中uminit标记隐私协议同意状态。 - 初始化 TalkingData(
TalkingDataSDK.init(...)),Constant.robotId作为渠道维度之一。 - 初始化企业微信 SDK(
IWWAPIUtil.init(this))。 - 初始化应用更新框架(
UpdateAppUtils.init(this))。 - 启动前台通知(
PlayNotifyManager.show())。 - 设置全局异常捕获(
GlobalException),异常时自动重启。
- 初始化
4.2 ListenActivity 配置流程
核心界面:ListenActivity.kt。
主要职责:
- 展示并编辑链接号(
robotId):- 文本框
et_channel显示当前Constant.robotId。 - 点击“保存”按钮:
- 将输入写入
Constant.robotId(内部通过SPUtils持久化)。 - 发送广播通知
Constant.WEWORK_NOTIFY,类型为modify_channel。 - 调用
HttpUtil.getMyConfig(toast = false)拉取机器人配置。 - 将链接号上报给友盟
MobclickAgent.onProfileSignIn(channel)。
- 将输入写入
- 文本框
- 配置 WebSocket host:
- 文本
tv_host显示Constant.host。 - 点击:弹出历史 host 列表(来自
SPUtils的host_list),支持一键切换并调用HostTestHelper.testWs()进行连通性检测。 - 长按:弹出编辑对话框,支持新增 / 删除 host,新增时校验是否符合
ws://或wss://开头格式。
- 文本
- 权限开关:
- 无障碍开关
sw_accessibility:- 校验是否填写链接号。
- 校验是否已开启系统无障碍;如未开启,跳转到引导页
AccessibilityGuideActivity或系统设置。 - 如检测到 Hook / Root 环境,进行风险提示并控制运行。
- 关闭时调用
WeworkController.weworkService.disableSelf()(在部分 ROM 上会转跳到系统设置)。
- 悬浮窗开关
sw_overlay:- 开启时跳转
FloatViewGuideActivity引导授权。 - 已授权时显示悬浮窗(
FloatWindowHelper.showWindow())或引导前往权限设置页。
- 开启时跳转
- 无障碍开关
- 环境检测:
- 设备信息、Root 状态、Hook 状态写入
SPUtils,用于后续分析。 - 检查企业微信当前版本是否在
Constant.AVAILABLE_VERSION列表内,给出“已适配 / 可能存在兼容性问题”等提示。
- 设备信息、Root 状态、Hook 状态写入
- 初始化数据:
- 在
initData中设置默认Constant.robotId与Constant.host(可以视需要调整或移除默认值)。 - 调用
HttpUtil.getMyConfig(toast = false)拉取机器人配置。 - 调用
CacheUtil.autoDelete()清理旧缓存。
- 在
4.3 与后端的通信
WebSocket 链接:
- WebSocket 地址统一由
Constant.getWsUrl()生成,格式为:<host>/webserver/wework/<robotId>。- 默认 host 在
Constant.DEFAULT_HOST中配置:ws://8.166.130.74:18680。 - host 与 robotId 最终都持久化在
SPUtils中,方便修改。
- 默认 host 在
- 具体 WebSocket 管理由 WebSocketManager.java 实现:
- 维护 WebSocket 连接、心跳(每 5 秒一次)、自动重连。
- 发送和确认消息(
WeworkMessageListBean封装),写入日志。 - 断线时关闭新消息接收(
WeworkController.setEnableLoopRunning(false)),重连成功后再恢复。 - 当长时间连接正常且未开启截屏模式时,如果检测到长时间未重连且仍在运行,会通过 Toast 提示“机器人运行中 请勿人工操作手机~”。
协议格式:
- 完整协议说明见 BACKEND_PROTOCOL.md:
- 连接 URL 格式、心跳机制。
WeworkMessageListBean、WeworkMessageBean的字段含义。- 常用指令类型(如
203发送消息、218推送文件、505获取最近聊天列表、101接收消息列表等)。 - 执行结果回调、错误码定义。
- 代码中
type、socketType等字段与文档一一对应,建议修改协议前同时修改此文档与对应模型类。
4.4 自动化执行流程(企业微信侧)
高层流程(简化):
- 后端下发任务(通过 WebSocket)。
- 客户端解析为
WeworkMessageBean/WeworkMessageListBean。 WeworkController调度对应的Wework*Impl实现执行操作:- 打开企业微信指定页面。
- 定位目标群 / 联系人。
- 根据控件树执行点击、输入文本、长按、转发等操作。
- 执行完成后,将结果封装回 WebSocket 消息上报服务端,包含成功 / 失败列表、错误原因等。
关键依赖:
- 无障碍服务:
WeworkService+AccessibilityUtil/AccessibilityExtraUtil。 - 文本匹配与房间识别:
RegexHelper、WeworkRoomUtil、WeworkTextUtil。 - 循环任务:
MyLooper、WeworkLoopImpl。
5. 配置项与敏感信息
5.1 host 与 robotId
相关代码:
说明:
Constant.host- 默认值:
DEFAULT_HOST = "ws://8.166.130.74:18680"。 - 通过
SPUtils持久化,键为"host"。 - 可在 ListenActivity 中通过 host 列表 / 编辑弹窗进行修改。
- 业务上可视为“后端 WebSocket 网关地址”,如需要更换环境(测试 / 生产)时重点关注。
- 默认值:
Constant.robotId- 通过 ListenActivity 的输入框配置。
- 底层持久化键为
"robotId",同时兼容历史"LISTEN_CHANNEL_ID"。 - 后端一般将其视为“链接号 / 机器人唯一 ID”,用于区分不同设备 / 账号。
注意事项:
- 在更改默认 host 或引导用户填写 robotId 时,需要与后端保持一致(确保后台任务调度平台识别该 robotId)。
- 如需要支持多环境(测试 / 预发 / 生产),可以在现有 host 列表机制上扩展 UI 与配置管理。
5.2 企业微信兼容版本
相关代码:
- Constant.kt 中
AVAILABLE_VERSION与AVAILABLE_VERSION_MAP。 - ListenActivity 中通过
AppUtils.getAppInfo(Constant.PACKAGE_NAMES)?.versionName获取企业微信版本。
说明:
AVAILABLE_VERSION列出了当前已适配的企业微信版本号(例如4.1.8、4.1.9、4.1.10等)。AVAILABLE_VERSION_MAP用于将版本号映射为内部的整数版本,用于兼容性判断。- 当检测到企业微信版本不在列表内时,会提示“可能存在部分兼容性问题”,但仍允许使用。
后续维护建议:
- 当企业微信版本升级后,需要:
- 手动测试各项自动化功能。
- 若确认兼容,将新版本号加入
AVAILABLE_VERSION与AVAILABLE_VERSION_MAP。 - 如需要针对特定版本调整逻辑,可结合
Constant.version做分支处理。
5.3 统计与第三方 SDK key
相关代码:
说明:
- 友盟统计:
val key = "6284a3a3d024421570f97c3c"- 通过
UMConfigure.preInit/UMConfigure.init初始化。 - 隐私协议同意状态通过
SPUtils中"uminit"字段控制。
- TalkingData:
TalkingDataSDK.init(this, "80E9C84E39904DAFB28562910FF7C86C", getString(R.string.app_name) + "_master", Constant.robotId)- 依赖
Constant.robotId作为渠道维度。
接手后如需更换统计账号或关闭统计:
- 调整或移除相应初始化代码。
- 同时评估对现有数据分析的影响,必要时与产品 / 运维同步。
6. 构建、打包与发布流程
6.1 本地开发环境搭建
- 克隆仓库到本地:
- 建议完整克隆含子模块(当前项目无 Git 子模块,仅多 module)。
- 使用 Android Studio 打开仓库根目录。
- 确保本地已安装:
- JDK 8(或 Android Studio 自带 JDK)。
- Android SDK 30 及对应 Build Tools。
- 首次打开时,按 IDE 提示同步 Gradle,等待依赖下载完成。
6.2 常用构建命令
在项目根目录下,可以使用仓库自带 Gradle Wrapper:
-
编译 Debug 包:
./gradlew assembleDebug -
编译 Release 包:
./gradlew assembleRelease
注意:
app/build.gradle中release构建类型启用了混淆:minifyEnabled true- 混淆配置文件:
proguard-android-optimize.txt(默认)与app/proguard-rules.pro
- 签名配置可能未在仓库中直接提供(如使用本地
keystore),如需正式发布包,请向原维护人员或运维团队索取签名文件与配置。
6.3 打包注意事项
- 由于集成了企业微信 SDK(
libs/lib_wwapi-*.aar)及多个三方 SDK,混淆配置需要保持当前状态,避免将关键类混淆导致运行崩溃。 - 如新增依赖,请同步更新
proguard-rules.pro。 - Release 包上线前建议至少在以下维度自测:
- 不同 Android 版本(特别是 API 24~30)。
- 不同厂商 ROM(华为、小米、OPPO、VIVO 等)的无障碍与后台保活行为。
- 至少一种已适配的企业微信版本。
7. 日常调试与常见问题
7.1 日志查看
- 项目统一使用
LogUtils输出日志,初始化在LogUtilsInit中。 - 日志输出位置、格式可在 LogUtilsInit.kt 中调整。
- 联调时建议:
- 在关键流程(WebSocket 收发、无障碍执行)增加必要的日志。
- 结合后端日志与手机本地日志定位问题。
7.2 无障碍与权限问题
常见现象:
- 无法自动跳转 / 点击:
- 检查系统无障碍设置中是否已为 WorkTool 授权。
- 检查是否被 ROM 的“电池优化 / 后台保护”策略限制。
- 悬浮窗不显示:
- 检查“悬浮窗权限”是否开启。
- 检查
FloatWindowHelper.showWindow()是否被调用。
相关工具类:
PermissionHelper:无障碍权限判断与相关操作。FlowPermissionHelper:后台启动、悬浮窗等权限判断。PermissionPageManagement:跳转至系统设置页面。
7.3 WebSocket 连接异常
排查步骤:
- 在 ListenActivity 中确认
host与robotId配置正确。 - 使用
HostTestHelper.testWs()(ListenActivity 操作 host 时自动调用)测试连通性。 - 查看
WebSocketManager日志,确认是否存在频繁断线重连。 - 确认服务端配置与
BACKEND_PROTOCOL.md版本一致。
进一步建议(针对日志中偶发 Connection closed 场景):
- 现象判定:
- 若出现“断开后 1~2 秒内自动重连成功,且同一 clientId 可继续收发消息”,通常是短时网络抖动或网关空闲回收,不一定是严重故障。
- 若出现“周期性断开(如每几分钟一次)”或“重连失败持续告警”,优先排查配置问题。
- 归因方法(客户端 / 服务端 / 网关):
- 客户端(Android)补充日志:在
WeworkService.EchoWebSocketListener的onClosing/onClosed/onFailure打印code、reason、throwable。 - 服务端补充日志:在 WebSocket Handler 的关闭与异常回调中打印
clientId、sessionId、关闭码、异常栈。 - 网关层补充日志:Nginx / LB 记录 upstream 连接关闭原因与空闲超时触发记录。
- 通过同一时间窗口对齐三端日志,判断“谁先发起关闭、关闭码是什么、是否有网络异常”。
- 客户端(Android)补充日志:在
- 常见根因:
- 手机网络切换(Wi-Fi/移动网络)或弱网导致 TCP 断开。
- 网关 / 反向代理空闲超时过短,主动关闭 WebSocket。
- 心跳机制仅业务层保活,未启用 WebSocket ping,导致中间设备误回收长连接。
- Android 省电策略导致后台网络能力受限。
- 建议优化项(按优先级):
- 客户端统一复用
OkHttpClient,并开启pingInterval(建议 20~30 秒)。 - 网关与服务端 idle timeout 应明显高于心跳周期(建议至少 30~60 秒)。
- 重连策略增加“指数退避 + 抖动”,避免批量设备同时重连。
- 在运维侧统计“每设备每小时断线次数、重连耗时、连续失败次数”,作为健康度指标。
- 客户端统一复用
相关代码入口:
- WebSocket 管理:
app/src/main/java/org/yameida/worktool/utils/WebSocketManager.java - 监听与回调:
app/src/main/java/org/yameida/worktool/service/WeworkService.kt
8. 后续可扩展与注意事项
- 协议变更:
- 修改 WebSocket 协议或新增指令类型时,需同时更新:
WeworkMessageBean/WeworkMessageListBean数据结构。Wework*Impl中对新指令的处理逻辑。- 文档 BACKEND_PROTOCOL.md。
- 修改 WebSocket 协议或新增指令类型时,需同时更新:
- 新企业微信版本适配:
- 新版本上线后,需实机测试高频功能。
- 确认后更新
Constant.AVAILABLE_VERSION及相关逻辑。
- 安全与合规:
- 严禁在代码中硬编码任何生产环境账号密码。
- 涉及数据采集、上传时注意隐私合规(特别是好友信息、聊天内容等)。
9. 交接建议
建议接手同学优先按以下顺序熟悉项目:
- 阅读 README 与本交接文档,理解整体定位与功能。
- 在测试环境跑通完整链路:
- 编译安装 APP。
- 配置测试后端 host 与 robotId。
- 打开无障碍与悬浮窗权限。
- 使用后台调度平台下发几种典型任务(发送文本、发送图片、获取最近聊天列表等)。
- 深入阅读核心代码:
MyApplication(启动流程)。ListenActivity(配置入口)。WeworkService+WeworkController+Wework*Impl(自动化执行)。WebSocketManager+ 协议模型类(通讯层)。
- 根据实际需要再进一步梳理业务细节与扩展点。
如后续对具体模块或逻辑有疑问,可在对应类文件中逐步补充更细的内部文档或注释,并与团队同步更新本交接文档。