在 Android 行业开发场景中,大量工具类、运营类、测试类 App 存在标准化重复操作需求:如批量数据采集、自动表单填写、定时任务执行、APP 内部流程自动化测试等。传统实现方案分为两类,各自存在明显短板:第一种是独立自动化工具(AutoJS、Hamibot 等),用户需要同时安装主业务 App 与自动化工具,切换操作繁琐;且第三方工具无法和自研 App 做账号打通、权限隔离、业务数据互通,无法实现一体化产品体验;同时独立脚本工具存在分发、管控、脚本安全管控难题,企业级场景难以落地。第二种是基于 Android 原生无障碍、Airtest、Appium 自行封装脚本引擎,从零开发需要处理权限检测、JS 解析引擎、设备操作底层封装、脚本生命周期管理、前后端通信等大量底层逻辑,开发周期长、兼容性差,多机型适配、权限弹窗自动处理、定时任务调度等细节需要大量踩坑调试,中小开发团队投入成本极高。本文从环境准备、工程集成、生命周期调用、脚本交互、生产落地问题优化完整梳理集成全流程,为 Android 开发者提供可落地的工程实践方案。
一、SDK 核心能力与适用开发环境说明
(一)SDK 核心功能边界
冰狐移动端 SDK 完整继承独立 APP 全部核心自动化能力,对外提供标准化 Java 调用接口,核心能力覆盖:
- 引擎生命周期管理:初始化、登录、登出、页面生命周期绑定(Activity onCreate/onResume/onPause/onDestroy);
- 账号体系:自动登录、手动账号密码登录、子账户绑定、全局用户名 / 设备名读取;
- 脚本执行核心接口 exeScript:支持本地文件、Asset 资源、手机绝对路径、在线远程脚本四种加载方式,支持多任务抢占、执行后置默认任务、执行结果回调;
- 双向通信机制:setStateListener 全局状态监听、setMessageListener 系统消息回调;addJavaObject 实现 Java 对象注入 JS,JS 直接调用原生业务代码;
- 环境管控:静态方法切换生产 / 调试模式,区分线上正式环境与本地脚本调试环境;
- 内置底层依赖封装:网络通信 Netty、HTTP 请求 OkHttp、定时任务 cron4j,提供完整底层能力支撑。
(二)官方推荐开发环境规范
根据官方 Demo 文档,稳定适配构建环境组合如下,不匹配环境极易出现编译报错、依赖冲突、引擎初始化失败问题:
- Gradle 构建工具:gradle-8.0-bin;
- JDK 版本:Java17;
- IDE:Android Studio Giraffe;
- 工程编译方式:标准 Android Application 模块,支持 AAR 本地引入、本地 Maven 两种集成模式。
二、工程完整集成步骤与代码配置详解
集成分为SDK 文件导入、Gradle 依赖配置、底层第三方库引入三大基础步骤,同时提供两种依赖优化方案规避依赖冗余问题。
3.1 第一步:导入 SDK 本地 AAR 文件
从官方文档链接下载 Demo 包,提取 aznfz.aar 核心库文件,在项目 app 模块下新建 libs 文件夹,将 aar 文件完整拷贝至该目录,目录结构如下:
app/
└── libs/
└── aznfz.aar
3.2 第二步:配置 Gradle 读取本地 AAR 库
打开 app 模块 build.gradle,在 dependencies 代码块中添加本地文件树依赖,读取 libs 下所有 aar 库:
dependencies {
// 读取libs目录下所有AAR文件
implementation(fileTree("libs"))
// 业务自身其他依赖...
}
配置完成后点击 Android Studio 右侧 Maven Projects 面板刷新,同步 Gradle 工程,此时 IDE 可识别 SDK 内所有 Java 类与接口。
3.3 第三步:引入 SDK 必需底层第三方依赖
aznfz.aar 仅封装上层引擎业务逻辑,网络、定时、通信底层依赖未内置,必须手动添加三方库,否则运行时会抛出 ClassNotFound 异常,标准依赖配置如下:
implementation ('io.netty:netty-all:4.1.36.Final')
implementation ('com.squareup.okhttp3:okhttp:3.8.1')
implementation ('it.sauronsoftware.cron4j:cron4j:2.2.5')
3.4 两种优化集成方案(规避大量依赖配置)
官方文档提供两种方案,无需手动添加三个底层依赖,适合大型多模块项目:
- Fat AAR 全量包:下载打包完成的 Fat 版本 aznfz.aar,内部已内嵌所有第三方依赖,仅需引入文件树,无需额外配置 netty、okhttp、cron4j;缺点是 AAR 包体积增大,适合小型单模块项目。
- 本地 Maven 仓库:将 SDK 及依赖上传至项目本地 Maven 库,通过 maven 坐标引入,统一管理版本,适合多模块大型工程,便于统一升级 SDK 版本,减少重复依赖配置。
三、SDK 生命周期标准调用流程
官方 Demo 采用 StartupActivity(引擎初始化)→LoginActivity(手动登录)→MainActivity(脚本业务操作)三层页面架构,该生命周期流程是保障引擎稳定运行的核心规范,不可随意调整调用顺序,否则会出现权限检测失效、登录状态丢失、脚本无法执行等问题。
4.1 阶段一:StartupActivity 完成引擎初始化与自动登录
引擎初始化 init 方法建议在页面 onResume 中调用,支持重复调用,内部会自动校验无障碍、悬浮窗等自动化必需权限,缺失权限时主动弹窗引导用户开启。
1. init 初始化方法调用示例
SAR.getInstance().init(this, new InitListener() {
@Override
public void onInitResult(boolean success) {
if (success) {
// 初始化成功,执行自动登录
autoLogin();
} else {
// 初始化失败,权限缺失或设备不支持,跳转提示页
}
}
});
init 接收两个入参:当前 Activity 上下文、初始化结果回调 InitListener,回调返回布尔值标识引擎是否初始化就绪。
2. autoLogin 自动登录逻辑
初始化成功后执行自动登录,复用本地缓存账号,无需用户重复输入账号密码:
private void autoLogin() {
SAR.getInstance().autoLogin(getApplicationContext(), new LoginListener() {
@Override
public void onLoginResult(boolean success) {
if (success) {
// 自动登录成功,跳转MainActivity
startActivity(new Intent(StartupActivity.this, MainActivity.class));
} else {
// 自动登录失败,跳转手动登录页面
startActivity(new Intent(StartupActivity.this, LoginActivity.class));
}
}
});
}
4.2 阶段二:LoginActivity 手动账号登录(自动登录失败兜底)
当本地无缓存账号、登录凭证过期时,进入手动登录页面,调用 login 方法,支持主账户、子账户两种登录模式:
// 普通主账户登录,parentName传空
SAR.getInstance().login(username, password, "", new LoginListener() {
@Override
public void onLoginResult(boolean success) {
if (success) {
startActivity(new Intent(LoginActivity.this, MainActivity.class));
} else {
// 提示账号密码错误
}
}
});
// 子账户登录,传入父账户名称
SAR.getInstance().login(childUser, childPwd, parentAccount, listener);
4.3 阶段三:MainActivity 绑定页面生命周期,执行业务脚本
登录成功后进入主业务页面,必须完整绑定四大生命周期方法,用于引擎资源释放、状态刷新,防止内存泄漏、后台脚本卡死:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SAR.getInstance().onCreate(getApplicationContext());
}
@Override
protected void onResume() {
super.onResume();
SAR.getInstance().onResume();
}
@Override
protected void onPause() {
super.onPause();
SAR.getInstance().onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
SAR.getInstance().onDestroy();
}
生命周期绑定完成后,即可注册全局监听、执行自动化脚本、注入 Java 交互对象,开展核心业务。
四、核心业务接口深度实践:脚本执行与 Java-JS 双向通信
5.1 exeScript 脚本执行接口全场景使用
exeScript 是 SDK 最核心业务接口,支持四类脚本资源路径,覆盖本地静态脚本、在线动态下发脚本场景,完整参数包含脚本路径、目标函数、任务抢占、入参数组、执行回调、后置默认任务开关。
场景 1:读取 App 内置 Asset 本地脚本
// 执行asset目录下test.js中的main函数,传入JSON数组参数,抢占当前任务
JSONArray params = new JSONArray();
params.put("批量采集");
SAR.getInstance().exeScript(
"asset:test.js",
"main",
true,
params,
new ExecuteScriptResultListener() {
@Override
public void onResult(boolean success, String msg) {
// 脚本执行完成回调,success为执行状态,msg为返回信息
}
},
false
);
场景 2:执行手机本地存储 JS 文件
// 读取手机根目录脚本
SAR.getInstance().exeScript("/sdcard/batch_task.js", "runTask", false, params, listener, true);
场景 3:在线远程脚本(企业动态下发脚本场景)
// 直接调用后台发布的线上脚本,无需本地存储
SAR.getInstance().exeScript("online_task", "start", true, params, listener, false);
参数说明:forceRun 控制任务抢占,true 代表停止当前运行脚本立即执行新脚本;exeDefaultTaskWhenFinished 控制脚本执行完毕后是否自动执行平台默认定时任务,适合持续自动化运营场景。
5.2 全局状态与消息监听:业务联动能力
通过 setStateListener、setMessageListener 监听引擎内部状态、平台推送消息,实现业务联动:
- StateListener:监听登录状态、脚本运行状态、权限变更、生产模式切换;
- MessageListener:接收后台下发的通知、任务指令、设备告警消息。典型应用:脚本执行失败时收到状态回调,自动弹窗提示用户;后台推送新任务消息,自动触发 exeScript 执行对应脚本。
5.3 addJavaObject:Java 与 JS 双向交互(业务核心拓展能力)
该接口解决脚本无法调用 App 原生业务逻辑的痛点,允许将 Java 业务对象注入 JS 引擎,JS 脚本直接调用 Java 方法,支持数字、布尔、字符串、JS 数组、JS 对象五种数据类型互传。
1. 编写原生业务 Java 类
public class BusinessApi {
// 字符串+数字入参
public String getOrderInfo(String orderId, long userId) {
return "订单信息:" + orderId + " 用户ID:" + userId;
}
// JS数组操作
public long handleList(JSArray array) {
array.push(System.currentTimeMillis());
return array.getLength();
}
// JS对象传参
public JSObject setConfig(JSObject config) {
config.put("autoRun", true);
return config;
}
}
2. 引擎初始化完成后注入对象
SAR.getInstance().addJavaObject("businessApi", new BusinessApi());
3. JS 脚本中调用原生方法
function main() {
// 调用Java获取订单
let order = businessApi.getOrderInfo("ORD20260701", 10001);
console.log(order);
// JS数组传递至Java
let arr = ["任务1", "任务2"];
let len = businessApi.handleList(arr);
// JS对象配置参数
let cfg = {time: "09:00"};
let newCfg = businessApi.setConfig(cfg);
}
该能力大幅拓展脚本业务边界,自动化脚本可直接读取 App 本地数据库、调用原生网络接口、操作本地文件,实现纯脚本无法完成的复杂业务流程。
五、生产环境管控:生产 / 调试模式切换与设备信息读取
SDK 提供一组静态全局工具方法,用于线上环境管控、设备信息统计,无需 Activity 上下文即可调用:
- 模式切换:
SAR.toggleProdMode()静态方法切换调试 / 生产模式;调试模式开启日志、弹窗提示,生产模式屏蔽调试日志,提升运行效率; - 模式判断:
SAR.getProdMode()返回布尔值,区分线上正式环境与本地调试; - 设备标识:
SAR.getDeviceName()获取设备唯一名称,用于后台设备区分; - 账号读取:
SAR.getUsername(context)获取当前登录账号,用于业务数据绑定、权限区分。
生产环境最佳实践:App 打包 Release 版本时默认开启 Prod 生产模式,屏蔽调试弹窗与冗余日志;仅内测包开放调试模式,便于线上问题排查。
六、登出与资源释放完整逻辑
用户退出登录、切换账号时调用 logout 方法,清空本地登录缓存、停止所有运行脚本、释放引擎占用资源,避免后台持续运行造成耗电、内存占用过高:
SAR.getInstance().logout(new LogoutListener() {
@Override
public void onLogoutResult(boolean success) {
if (success) {
// 登出成功,跳转登录页,清空本地业务缓存
}
}
});
登出后如需再次使用自动化能力,必须重新走 init→autoLogin/login 完整生命周期流程。
七、工程落地常见问题与优化方案
8.1 编译阶段报错:第三方依赖类找不到
问题现象:运行时报 netty、okhttp 类不存在;解决方案:核对 build.gradle 中三个底层依赖版本号与官方文档一致,禁止修改版本号;或切换 Fat AAR 包集成方案,省去手动依赖配置。
8.2 引擎 init 初始化失败,权限弹窗不弹出
问题现象:调用 init 后 onInitResult 返回 false,无权限提示;优化方案:StartupActivity 必须为前台可见 Activity,不能使用后台 Service 调用 init;适配 Android 12 + 权限适配,提前申请悬浮窗、无障碍基础权限,减少引擎校验失败概率。
8.3 脚本执行内存泄漏、后台持续耗电
优化方案:严格在 MainActivity 的 onDestroy 中调用 SDK 对应销毁方法;页面退出前主动停止正在运行的脚本;App 完全退出时执行 logout 释放引擎资源。
8.4 Java 与 JS 传参类型转换异常
问题现象:JS 传入数字、数组时报错;规范:JS 中数组统一使用 SDK 内置 JSArray、JSObject 接收,禁止直接使用原生 Java 数组、HashMap 接收,严格遵循文档定义数据类型映射规则。
八、总结
将冰狐智能辅助移动端 SDK 集成至自研 Android 应用,整体集成流程遵循 “引擎初始化→账号登录→页面生命周期绑定→脚本执行与双向交互→登出资源释放” 标准化流程,结合生产模式管控、全局状态监听、脚本多路径加载等能力,可快速搭建一套稳定、可管控、可拓展的内置自动化脚本引擎,为 Android 应用赋予原生自动化能力。
1045

被折叠的 条评论
为什么被折叠?



