搜 索

Auto.js源代码阅读心得

  • 393阅读
  • 2023年03月11日
  • 0评论
首页 / 编程 / 正文
本文是我对 AutoX (AutoJs 的开源分支) 项目的深度技术分析,从架构师的角度全面剖析这个 Android 自动化框架的设计与实现。

一、项目基础信息

1.1 基本信息

项目属性
项目名称AutoX (AutoJs 社区分支)
包名org.autojs.autoxjs
版本号6.6.8 (versionCode: 668)
开发语言Java + Kotlin 混合
许可证Mozilla Public License

1.2 SDK 配置

SDK 配置项版本
minSdk21 (Android 5.0)
targetSdk28 (Android 9.0)
compileSdk34 (Android 14)
buildToolsVersion34.0.0

1.3 构建工具版本

工具版本
Gradle8.0
Android Gradle Plugin (AGP)8.0.2
Kotlin1.6.21
Jetpack Compose1.2.0-rc01
JDK17
IDE 推荐Android Studio 2023.3.1 Patch 2

1.4 构建变体配置

项目采用 channel 维度的产品风味(Product Flavors):

flavorDimensions.add("channel")
productFlavors {
    create("common") {
        applicationId = "org.autojs.autoxjs"
        versionCode = 668
        versionName = "6.6.8"
    }
    create("v6") {
        applicationIdSuffix = ".v6"  // org.autojs.autoxjs.v6
        versionCode = 668
        versionName = "6.6.8"
    }
}

同时启用了 ABI 分包:

  • arm64-v8a (ARMv8 64位)
  • armeabi-v7a (ARM 32位)

二、架构分析

2.1 整体架构模式

经过对源码的深入分析,我发现 AutoX 采用的是混合架构模式,主要以 MVVM 为主,同时保留了大量 MVC 风格的遗留代码:

flowchart TB subgraph Presentation["表现层 Presentation"] direction TB Activity["Activities
(MainActivity, BuildActivity)"] Fragment["Fragments
(ScriptListFragment, TaskManagerFragment)"] Compose["Compose UI
(BuildPage, SearchBox)"] ViewModel["ViewModels
(BuildViewModel, DrawerViewModel)"] end subgraph Domain["领域层 Domain"] direction TB Service["Services
(UserService, VersionService)"] Tool["Tools
(AccessibilityServiceTool)"] AutoJs["AutoJs Core
(ScriptRuntime, ScriptEngine)"] end subgraph Data["数据层 Data"] direction TB API["Network APIs
(Retrofit Interfaces)"] Storage["Local Storage
(SharedPreferences, Database)"] Model["Models
(User, VersionInfo, Script)"] end Activity --> ViewModel Fragment --> ViewModel Compose --> ViewModel ViewModel --> Service ViewModel --> AutoJs Service --> API Service --> Storage AutoJs --> Model API --> Model Storage --> Model

2.2 模块化结构

项目采用多模块 Gradle 结构,模块划分清晰:

graph TD subgraph MainModules["主要模块"] app["📱 app
主应用模块"] autojs["⚙️ autojs
核心引擎库"] automator["🤖 automator
自动化库"] common["📦 common
公共工具库"] inrt["🚀 inrt
运行时模块"] apkbuilder["🔨 apkbuilder
APK构建库"] paddleocr["👁️ paddleocr
OCR识别库"] end subgraph LocalRepo["本地仓库模块"] libtermexec["libtermexec"] emulatorview["emulatorview"] term["term"] p7zip["p7zip"] opencv["OpenCV 4.5.5"] end app --> autojs app --> apkbuilder autojs --> common autojs --> automator autojs --> libtermexec autojs --> emulatorview autojs --> term autojs --> p7zip autojs --> opencv autojs --> paddleocr automator --> common inrt --> autojs inrt --> automator inrt --> common

2.3 依赖注入方案

项目没有使用任何 DI 框架(无 Dagger/Hilt/Koin),而是采用手动依赖注入配合服务定位器模式

flowchart LR subgraph Singletons["单例服务"] AutoJs["AutoJs.getInstance()"] GlobalAppContext["GlobalAppContext.get()"] VersionService2["VersionService2
(Kotlin object)"] end subgraph Factories["工厂类"] Factory["BuildViewModelFactory"] end Factory -->|创建| ViewModel["BuildViewModel"] AutoJs -->|依赖| GlobalAppContext ViewModel -->|使用| AutoJs

服务定位模式示例:

// 单例服务 - Kotlin object
object VersionService2 {
    private val retrofit = Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .build()
    val gitUpdateCheckApi = retrofit.create<GithubUpdateCheckApi>()
}

// 单例获取 - Java static
public static AutoJs getInstance() {
    return instance;
}

2.4 核心引擎架构

AutoJs 的核心是基于 Mozilla Rhino 的 JavaScript 执行引擎:

flowchart LR subgraph ScriptExecution["脚本执行流程"] direction TB Script["JavaScript 脚本"] Engine["ScriptEngine
(Rhino 1.7.14)"] Runtime["ScriptRuntime"] API["运行时 API"] end subgraph RuntimeAPIs["运行时 API 模块"] direction TB UI["ui - UI构建"] Auto["auto - 自动化"] Image["images - 图像处理"] OCR["ocr - 文字识别"] Files["files - 文件操作"] Http["http - 网络请求"] Threads["threads - 多线程"] Events["events - 事件系统"] end subgraph NativeSupport["原生支持"] direction TB Accessibility["AccessibilityService
无障碍服务"] OpenCV_Native["OpenCV
图像处理"] Tesseract["Tesseract
OCR引擎"] MLKit["Google MLKit
多语言OCR"] PaddleOCR_Native["PaddleOCR
飞桨OCR"] end Script --> Engine Engine --> Runtime Runtime --> API API --> UI & Auto & Image & OCR & Files & Http & Threads & Events Image --> OpenCV_Native OCR --> Tesseract OCR --> MLKit OCR --> PaddleOCR_Native Auto --> Accessibility

2.5 UI 架构演进

项目正处于从传统 View 体系向 Jetpack Compose 迁移的过渡期:

graph LR subgraph Legacy["传统架构 (遗留)"] Activity_Old["Activity"] Fragment_Old["Fragment"] XML["XML Layout"] ButterKnife["ButterKnife
View绑定"] end subgraph Modern["现代架构 (新增)"] Activity_New["Activity"] Compose["Jetpack Compose"] ViewModel_New["ViewModel"] State["Compose State"] end Activity_Old --> XML XML --> ButterKnife Activity_New --> Compose Compose --> ViewModel_New ViewModel_New --> State Legacy -.->|迁移中| Modern

三、代码质量评估

3.1 代码规范遵循情况

维度评估说明
命名规范⭐⭐⭐⭐遵循 Android 惯例,成员变量使用 m 前缀
包结构⭐⭐⭐⭐按功能模块清晰划分
注释质量⭐⭐⭐类级注释较完整,但存在过时 TODO
代码格式⭐⭐⭐Java/Kotlin 混合,风格不够统一

3.2 设计模式使用情况

pie title 设计模式分布 "单例模式" : 66 "工厂模式" : 20 "建造者模式" : 15 "观察者模式" : 30 "策略模式" : 5

具体使用:

模式实现数量典型示例
Singleton66+AutoJs.getInstance(), DebuggerSingleton
Factory20+ScriptEngineFactory, ViewAttributesFactory
Builder15+JsDialogBuilder, ScriptRuntime.Builder
Observer30+EventDispatcher, ScriptExecutionObserver
Delegate5+ViewAttributeDelegate

3.3 代码异味(Code Smell)分析

我在源码中发现了以下主要问题:

3.3.1 大型类(God Class)

类名行数问题描述
TokenStream.java2,319Rhino 词法分析器,职责过重
HVScrollView.java1,647自定义滚动视图,触摸处理复杂
Dim.java1,558调试器实现,状态管理混乱
BuildPage.kt954Compose UI,嵌套层级过深
JsDialog.java810对话框包装,方法委托过多
User.java755数据实体,185个属性!

3.3.2 问题代码示例

// HVScrollView.java 中发现的不专业注释
// TODO: FUCK  <- 这类注释应该被清理

// 2017-2018年的过时TODO仍未处理
// TODO: 2018/10/24
// TODO: 2018/2/24 优化效率。不绘制透明字体。

3.4 单元测试覆盖情况

pie title 测试覆盖率分析 "有测试覆盖" : 0.65 "无测试覆盖" : 99.35
指标数值
总代码行数~100,770
测试代码行数~656
实际有效测试~130 行
测试覆盖率0.65% (极低)

已有测试:

  • XmlConverterTest.java - XML布局转换测试 (5个用例)
  • MultiLinePreprocessorTest.java - JS预处理测试 (10个用例)
  • 其余多为 Example 模板文件

四、依赖管理

4.1 核心依赖库清单

mindmap root((依赖库)) UI框架 Jetpack Compose 1.2.0-rc01 Material Design 1.9.0 Accompanist 0.24.13-rc ButterKnife 10.2.1 网络通信 Retrofit 2.9.0 OkHttp 4.10.0 Ktor 2.0.3 异步处理 RxJava2 2.2.21 Kotlin Coroutines 1.6.2 图像处理 OpenCV 4.5.5 Glide 4.8.0 Coil 2.0.0-rc03 OCR识别 Tesseract 4.1.1 Google MLKit 16.0.0-beta5 PaddleOCR 脚本引擎 Rhino 1.7.14 其他 EventBus 3.3.1 LeakCanary 2.13 Bugly 4.0.0

4.2 依赖版本评估

当前版本最新版本状态
Kotlin1.6.212.0.0+⚠️ 落后2个大版本
Compose1.2.0-rc011.6.0+⚠️ 落后较多
AGP8.0.28.3.0+⚠️ 可升级
OkHttp4.10.04.12.0✅ 较新
Material1.9.01.11.0⚠️ 可升级
Spongy Castle1.56.0.0-❌ 已废弃

4.3 废弃/风险库

问题建议
spongycastleAndroid 5.0 后已废弃迁移至 BouncyCastle
ButterKnife已停止维护迁移至 ViewBinding
AndroidAnnotations维护不活跃移除,使用 Kotlin
tiny-sign签名有问题(README提到)迁移至 apksigner

4.4 依赖冲突风险

// build.gradle.kts 中的强制版本控制
configurations.all {
    exclude(group = "org.jetbrains", module = "annotations-java5")
    exclude(group = "com.github.atlassian.commonmark-java", module = "commonmark")
    resolutionStrategy {
        force("com.google.code.findbugs:jsr305:3.0.1")
    }
}

五、性能与安全

5.1 内存泄漏风险

flowchart TD subgraph MemoryLeaks["内存泄漏风险点"] L1["🔴 未注销的监听器
Events.java"] L2["🔴 Handler泄漏
无Looper指定"] L3["🟡 Bitmap未回收
Drawables.java"] L4["🟡 静态Context引用
ScriptRuntime.java"] L5["🟡 OrientationEventListener
未disable"] end L1 --> |"addListener()无对应remove"| Leak1["Activity泄漏"] L2 --> |"消息未清理"| Leak2["Handler泄漏"] L3 --> |"大图片堆积"| Leak3["OOM"]

具体问题代码:

// Events.java - 监听器添加但从未移除
public void observeKey() {
    service.getOnKeyObserver().addListener(this);  // ❌ 无对应的 removeListener
}

public void observeTouch() {
    mTouchObserver.setOnTouchEventListener(this);  // ❌ 无清理
    mTouchObserver.observe();
}

5.2 主线程阻塞风险

位置问题严重程度
HttpUtil.java同步HTTP请求🔴 高
Drawables.java网络图片加载🟡 中
FeatureActivity.javaWebView加载HTTP🟡 中
// HttpUtil.java - 主线程网络请求
public static String doPost(String posturl) {
    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
    urlConnection.setReadTimeout(5000);   // 可能阻塞5秒
    urlConnection.setConnectTimeout(5000);
    urlConnection.connect();  // ❌ 同步阻塞
    // ...
}

5.3 ProGuard/R8 混淆配置

严重问题:Release 版本未启用混淆!

// app/build.gradle.kts
named("release") {
    isShrinkResources = false
    isMinifyEnabled = false  // ❌ 生产环境未混淆!
}

过度宽泛的 keep 规则:

# proguard-rules.pro - 整个包都被保留
-keep class org.mozilla.javascript.** { *; }
-keep class com.stardust.automator.** { *; }
-keep class com.stardust.autojs.** { *; }

5.4 网络安全问题

flowchart LR subgraph SecurityIssues["安全问题"] S1["❌ 硬编码HTTP URL"] S2["❌ 无 network_security_config"] S3["❌ WebView JS桥接漏洞"] S4["⚠️ SharedPreferences未加密"] end S1 --> Risk1["中间人攻击"] S2 --> Risk2["明文传输"] S3 --> Risk3["XSS/注入"] S4 --> Risk4["数据泄露"]

具体问题:

// FeatureActivity.java - 硬编码HTTP
private String url = "http://mk.autoxjs.com/pages/ykapp/choiseFeature";  // ❌ HTTP

// WebView 安全配置不足
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);  // ❌ 风险

5.5 安全问题汇总

问题类型严重程度位置建议
HTTP明文传输🔴 高FeatureActivity.java强制HTTPS
未配置网络安全🔴 高缺少配置文件添加 network_security_config.xml
WebView漏洞🟡 中FeatureActivity.java添加URL白名单验证
数据未加密🟡 中SharedPreferences使用 EncryptedSharedPreferences
Release未混淆🔴 高build.gradle.kts启用 R8 混淆

六、改进建议

6.1 架构优化建议

flowchart TB subgraph Current["当前状态"] C1["混合MVC/MVVM"] C2["手动DI"] C3["RxJava + Coroutines混用"] C4["View + Compose混用"] end subgraph Target["目标状态"] T1["统一MVVM/MVI"] T2["Hilt依赖注入"] T3["纯Coroutines + Flow"] T4["纯Compose UI"] end C1 -->|重构| T1 C2 -->|引入| T2 C3 -->|迁移| T3 C4 -->|迁移| T4

6.2 技术债务清单

优先级债务项工作量影响范围
P0启用Release混淆安全
P0修复内存泄漏稳定性
P1HTTP→HTTPS安全
P1添加网络安全配置安全
P2提升测试覆盖率质量
P2清理过时TODO可维护性
P3拆分大型类可维护性
P3统一异步方案一致性

6.3 迁移建议

Java → Kotlin 迁移路径

gantt title Java到Kotlin迁移计划 dateFormat X axisFormat %s section 第一阶段 工具类迁移 :a1, 0, 1 数据模型迁移 :a2, 1, 2 section 第二阶段 Service层迁移 :b1, 2, 3 Repository层迁移 :b2, 3, 4 section 第三阶段 ViewModel迁移 :c1, 4, 5 UI层迁移 :c2, 5, 6

View → Compose 迁移策略

  1. 新功能优先使用 Compose
  2. 逐步迁移简单页面 (Settings, About)
  3. 复杂页面保持 View (Editor, Explorer)
  4. 建立 Compose 组件库

6.4 优先级排序的重构计划

timeline title 重构优先级时间线 section 紧急 (立即) 启用 R8 混淆 : 安全关键 修复监听器泄漏 : 稳定性关键 HTTPS 迁移 : 安全关键 section 高优先级 引入 Hilt DI : 架构改进 统一 Coroutines : 代码一致性 增加单元测试 : 质量保障 section 中优先级 拆分大型类 : 可维护性 移除废弃库 : 技术债务 Kotlin 迁移 : 现代化 section 低优先级 全面 Compose 化 : UI现代化 文档完善 : 可维护性

七、总结

AutoX 是一个功能强大的 Android 自动化框架,其核心 Rhino JavaScript 引擎和丰富的 API 设计体现了较高的工程水平。然而,作为一个社区维护的开源项目,它也面临着一些典型的技术债务问题:

优势:

  • 模块化设计清晰,职责分离合理
  • 多 OCR 引擎支持(Tesseract、MLKit、PaddleOCR)
  • 正在积极向现代架构迁移(Compose、Coroutines)

待改进:

  • 测试覆盖率极低(0.65%)
  • 安全配置缺失(HTTP、未混淆)
  • 存在内存泄漏风险
  • Java/Kotlin、RxJava/Coroutines 混用增加维护成本

对于想要基于此项目进行二次开发的开发者,我建议优先解决 P0 级别的安全和稳定性问题,然后逐步进行架构现代化改造。


本文基于 AutoX v6.6.8 版本源码分析

评论区
暂无评论
avatar