资讯动态

AutoJs自动化截图脚本:从原理到实战的完整指南

发布时间:2026/8/3 20:05:16 来源:尧图企业网站定制
1. 项目概述与核心价值最近在折腾手机自动化的时候发现一个高频且有点“烦人”的需求定时或按条件截图并且自动把截图整理好存到相册里。你可能也遇到过类似场景比如需要定期监控某个App的数据变化、记录游戏成就、或者备份一些重要的聊天记录。手动操作不仅枯燥还容易忘记。这时候AutoJs这个基于JavaScript的Android自动化工具就派上用场了。这个项目说白了就是用AutoJs写一个脚本让它像你的私人助理一样在指定的时间、或者满足特定条件时比如屏幕上出现了某个关键词、某个颜色自动帮你截取当前屏幕然后规规矩矩地把图片保存到手机的相册目录中。它解决的不仅仅是“自动化截图”这个动作更深层的是解决了“规律性、重复性视觉信息采集与归档”的痛点。无论是做简单的数据监控、内容收集还是为更复杂的图像识别项目准备训练数据一个可靠的自动化截图脚本都是非常棒的第一步。适合谁来玩这个呢如果你是对手机自动化感兴趣的初学者这个项目涵盖了AutoJs最基础的屏幕操作、文件处理和条件判断是个完美的练手项目。对于已经有些经验的开发者你可以把它作为一个模块集成到你的自动化工作流里比如结合OCR识别截图中的文字或者用HTTP模块将图片上传到服务器。哪怕你只是个想偷懒的普通用户想自动保存每日打卡截图或者游戏抽卡结果跟着做下来也能轻松实现。2. 自动化截图脚本的整体设计思路在动手写代码之前我们先得把整个脚本的运转逻辑想清楚。一个健壮的自动化截图脚本不能是简单粗暴地无限循环截屏那样会很快耗光电量并产生大量无用图片。我们的设计需要包含触发机制、截图执行、图片处理和异常处理这几个核心环节。2.1 核心流程与模块划分整个脚本可以抽象为以下四个模块触发监听模块负责决定“什么时候截图”。这可以是基于时间的如每5分钟一次也可以是基于事件的如检测到特定界面元素、特定颜色或网络状态变化。截图执行模块这是核心动作调用AutoJs提供的截图API获取当前屏幕的Image对象。图片处理与保存模块对截图进行必要的处理如裁剪、压缩、添加时间水印然后按照预定规则命名并保存到指定相册路径。日志与容错模块记录脚本的运行状态和每次截图的信息并在出现异常如存储权限不足、屏幕状态异常时进行优雅处理避免脚本崩溃。2.2 方案选型背后的考量为什么选择这样的结构首先模块化设计让代码更清晰易于调试和扩展。例如你可以很容易地把基于时间的触发器换成基于图像识别的触发器而无需重写截图和保存的逻辑。其次引入日志和容错是实战中的血泪教训。手机环境复杂突然来的电话、权限弹窗都可能导致截图失败。没有良好的异常处理脚本可能无声无息地停止工作而你却浑然不知。在触发方式上我优先推荐“时间触发条件检测”的复合模式。纯时间触发简单但盲目纯条件触发实时性高但可能耗电。折中的方法是每隔一段时间例如30秒检查一次条件是否满足满足则截图。这样既保证了响应速度又控制了资源消耗。对于条件检测AutoJs提供了多种方法通过text()、id()等选择器查找控件或者通过images.findImage()进行图像匹配亦或是直接分析屏幕颜色images.pixel()。具体选择哪种取决于你的目标场景是否稳定。如果目标App的界面布局固定用选择器最可靠如果目标是识别一个图标或特定图片则用图像匹配。3. 核心细节解析与实操要点理解了整体框架我们来深入每个环节的细节。这些细节直接决定了脚本的稳定性和可用性。3.1 权限获取——脚本运行的基石AutoJs脚本需要一些关键权限才能正常工作。很多新手会在这里卡住。除了在AutoJs应用内开启“无障碍服务”和“悬浮窗权限”外截图保存到相册还需要存储权限。在Android 6.0 (API 23) 及以上版本这是一个危险权限需要动态申请。// 动态申请存储权限 if (!requestPermission(“STORAGE”)) { toast(“存储权限被拒绝脚本无法保存截图”); exit(); }注意requestPermission函数在AutoJs 4.0及以上版本可用。如果你的版本较低可能需要通过app.startActivity跳转到设置页面的方式引导用户手动开启体验上会差一些。务必在脚本开头就处理好权限问题这是后续所有操作的前提。3.2 截图API的选择与区别AutoJs提供了两个主要的截图函数captureScreen()和images.captureScreen()。它们看起来相似但有细微差别。captureScreen()这是一个全局函数调用更简便直接返回一个Image对象。它截取的是当前屏幕的原始尺寸。images.captureScreen()这是images模块下的方法。在AutoJs Pro版本中它支持一个format参数可以指定截图格式如”jpg”,”png”但社区版通常与全局函数无异。在大多数情况下两者可以互换。我习惯使用images.captureScreen()因为它在images模块下语义上更清晰且为未来可能的功能扩展如指定质量、格式留有余地。截图后得到的Image对象是后续所有图像处理操作的基础。3.3 图片的命名与保存策略如何给截图文件命名看似小事却极大地影响事后查找的效率。切忌使用简单的“screenshot1.png”这样的名字。一个好的命名应包含时间戳和上下文信息。// 生成带时间戳的文件名 function generateFilename(prefix) { var now new Date(); // 格式前缀_年月日_时分秒 var timeStr now.getFullYear() “” (now.getMonth()1).toString().padStart(2, ‘0’) “” now.getDate().toString().padStart(2, ‘0’) “_” now.getHours().toString().padStart(2, ‘0’) now.getMinutes().toString().padStart(2, ‘0’) now.getSeconds().toString().padStart(2, ‘0’); return (prefix || “ScreenShot”) “_” timeStr “.png”; }保存路径也很有讲究。直接保存到/sdcard/DCIM/Camera/相机相册可能不是一个好主意因为这会和你平时拍的照片混在一起。我建议在/sdcard/Pictures/目录下创建一个专属文件夹例如/sdcard/Pictures/AutoJs_Screenshots/。这样管理起来更方便也符合Android应用的数据存储规范。var saveDir “/sdcard/Pictures/AutoJs_Screenshots/”; // 确保目录存在 files.ensureDir(saveDir); var filePath saveDir generateFilename(“WeChat_Chat”); // 保存图片 images.save(image, filePath); // 通知系统相册刷新重要 media.scanFile(filePath);提示media.scanFile(filePath)这一行至关重要。如果不调用你保存的图片文件虽然存在于文件夹中但系统的“相册”或“图库”App可能无法立即扫描到它需要重启手机或等待系统自动扫描可能很久。调用这个函数后相册几乎能立即显示新图片。4. 完整脚本实现与分步解读下面我将结合一个具体的场景展示一个功能相对完整的自动化截图脚本。这个场景是监控微信某个群聊的入群欢迎消息假设欢迎消息包含“欢迎”二字一旦出现就截图保存。4.1 脚本初始化与主循环结构首先搭建脚本的骨架包括权限检查、变量初始化和主循环。// 1. 初始化与权限检查 auto.waitFor(); // 等待无障碍服务开启 if (!requestPermission(“STORAGE”)) { toastLog(“存储权限是必需的脚本退出”); exit(); } toastLog(“AutoJs自动化截图脚本启动”); // 2. 定义配置参数 var CHECK_INTERVAL 3000; // 检查间隔3秒 var TARGET_TEXT “欢迎”; // 要查找的目标文本 var SAVE_DIR “/sdcard/Pictures/WeChat_Welcome_Screenshots/”; // 保存目录 files.ensureDir(SAVE_DIR); // 创建目录如果不存在 // 3. 主循环 while (true) { try { // 检查当前是否在微信界面可根据实际情况调整判断条件 if (currentPackage() “com.tencent.mm”) { // 执行核心的检查与截图逻辑 checkAndCapture(); } else { log(“当前不在微信界面跳过本次检查”); } // 等待指定间隔后继续循环 sleep(CHECK_INTERVAL); } catch (e) { log(“主循环发生异常: ” e); // 简单的异常处理防止脚本因未知错误退出 sleep(5000); } }4.2 核心的检查与截图函数这是脚本的大脑负责判断条件并执行截图。function checkAndCapture() { // 4.2.1 查找目标文本 var target textContains(TARGET_TEXT).findOne(1000); // 查找1秒 if (target) { log(“发现目标文本:【” TARGET_TEXT “】, 准备截图…”); // 4.2.2 执行截图 // 为了确保截到完整界面可以在截图前加一个短暂延迟 sleep(500); var screenImage images.captureScreen(); if (screenImage) { // 4.2.3 生成文件名并保存 var fileName generateFilename(“WeChat_Welcome”); var filePath SAVE_DIR fileName; var success images.save(screenImage, filePath, “png”, 100); // 保存为PNG质量100 if (success) { log(“截图保存成功: ” filePath); // 通知媒体库刷新 media.scanFile(filePath); toast(“已保存欢迎消息截图”); // 4.2.4 截图后可以做一些清理或状态重置例如点击返回或等待一段时间 // 这里简单等待5秒避免短时间内对同一条消息重复截图 sleep(5000); } else { log(“截图保存失败”); } // 释放图像对象避免内存泄漏重要 screenImage.recycle(); } else { log(“截图失败未获取到图像对象”); } } else { // 未找到目标本次检查结束 // log(“未发现目标文本”); // 调试时可开启正常运行时建议关闭以免日志刷屏 } } // 辅助函数生成带时间戳的文件名 function generateFilename(prefix) { var d new Date(); return prefix “_” d.getFullYear() “” (d.getMonth()1).toString().padStart(2, ‘0’) “” d.getDate().toString().padStart(2, ‘0’) “_” d.getHours().toString().padStart(2, ‘0’) d.getMinutes().toString().padStart(2, ‘0’) d.getSeconds().toString().padStart(2, ‘0’) “.png”; }4.3 脚本的启动与停止控制一个长期运行的脚本需要有可控的启动和停止机制。AutoJs本身提供了“运行”和“停止”按钮。但在脚本内部我们也可以设计一个优雅的退出方式例如通过监听特定按键事件。// 在脚本开头部分主循环之前添加退出监听 threads.start(function() { // 设置一个按键例如音量下键作为停止脚本的快捷键 events.observeKey(); events.onKeyDown(“volume_down”, function(event) { toastLog(“检测到停止指令脚本将在本次循环后退出”); exit(); // 退出整个脚本 }); }); log(“按住音量下键可以停止脚本”);5. 进阶功能与优化方案基础功能实现后我们可以让脚本变得更聪明、更强大。这里分享几个我实践中觉得非常有用的进阶点子。5.1 基于图像识别的智能触发文本查找text()依赖于控件的文本属性如果文本是图片形式或者控件无法识别就会失效。这时图像识别images.findImage()是更好的选择。你可以事先截取一个“欢迎横幅”的小图作为模板然后让脚本在屏幕上寻找它。var template images.read(“/sdcard/template_welcome.png”); // 读取模板图片 if (template) { var result images.findImage(captureScreen(), template); if (result) { log(“通过图像识别找到目标位置” result); // … 执行截图逻辑 } template.recycle(); }注意图像识别对屏幕分辨率、颜色和模板图片的尺寸非常敏感。最好在同一台设备、同一屏幕分辨率下制作模板。为了提高识别率可以尝试对截图和模板都进行灰度化处理images.grayscale()并适当调整images.findImage的阈值参数。5.2 截图后的简单图像处理有时我们可能只想保存屏幕的一部分或者给截图加上水印。AutoJs的images模块提供了基础的图像处理功能。裁剪图片如果你只想保存屏幕上某个区域例如一个聊天窗口可以先获取该控件的边界然后进行裁剪。var uiObject text(“目标控件”).findOne(); if (uiObject) { var bounds uiObject.bounds(); // 截取全屏 var fullScreen images.captureScreen(); // 裁剪出目标区域 var croppedImage images.clip(fullScreen, bounds.left, bounds.top, bounds.width(), bounds.height()); // 保存 croppedImage fullScreen.recycle(); }添加时间水印虽然文件名包含了时间但在图片上直接印出时间更直观。这需要用到images.drawText()函数稍微复杂一些需要处理字体和位置。5.3 状态持久化与去重在监控场景下我们可能不希望针对同一事件重复截图。例如同一条欢迎消息在屏幕上停留了10秒脚本每3秒检查一次就会产生3张相同的截图。为了解决这个问题可以引入简单的状态记录。一个简单的办法是记录上次截图时的“特征”。对于文本触发可以记录触发控件的id()或文本内容哈希对于图像触发可以记录匹配到的坐标。如果本次检测到的特征与上次相同且在设定的“冷却时间”内则跳过截图。var lastCaptureFeature null; var lastCaptureTime 0; var COOLDOWN_MS 10000; // 10秒内不对同一目标重复截图 function checkAndCapture() { var target textContains(TARGET_TEXT).findOne(1000); if (target) { var currentFeature target.id() || target.text(); // 以id或文本作为特征 var currentTime new Date().getTime(); // 判断是否为同一目标且未过冷却时间 if (currentFeature lastCaptureFeature (currentTime - lastCaptureTime) COOLDOWN_MS) { log(“同一目标仍在冷却期内跳过截图”); return; } // 执行截图… // 截图成功后更新状态 lastCaptureFeature currentFeature; lastCaptureTime currentTime; } }6. 常见问题排查与实战心得脚本写好了跑起来却可能遇到各种妖魔鬼怪。下面是我踩过的一些坑和对应的解决办法希望能帮你快速排雷。6.1 截图失败或图片全黑/全白现象images.captureScreen()返回null或者保存的图片是纯黑或纯白。排查无障碍服务确保AutoJs的无障碍服务已开启并且授予了足够的权限。有时服务会意外停止重启一下AutoJs或重新开关无障碍服务。屏幕状态在锁屏状态下出于安全考虑可能无法截图。确保脚本运行时屏幕是亮屏且解锁状态。可以考虑用device.wakeUp()唤醒屏幕但解锁通常需要更复杂的模拟操作或root权限。安全策略某些银行类、支付类App或安全键盘界面会禁止截图这是系统级保护无法绕过。内存问题连续快速截图可能导致内存不足。确保在保存图片后调用image.recycle()释放内存。6.2 图片保存了但相册里看不到现象通过文件管理器能在/sdcard/Pictures/…目录下找到图片但系统自带的“相册”或“Google照片”App里没有。解决这就是前面强调过的保存后一定要调用media.scanFile(filePath)。这个函数会发送一个广播通知媒体扫描器有新的媒体文件加入。如果还不行可以尝试重启手机或者检查保存的目录是否被.nomedia文件标记该文件会阻止媒体扫描。6.3 脚本运行一段时间后自动停止现象脚本运行几小时或几天后无声无息地停止了。排查系统省电策略这是最常见的原因。手机厂商为了省电会限制后台应用的运行。你需要去手机的“设置”-“电池”-“应用启动管理”或“后台耗电管理”里找到AutoJs将其设置为“允许后台活动”或“手动管理”允许自启动、关联启动、后台运行。AutoJs自身被清理同样在手机管家的“清理加速”或“内存优化”中将AutoJs加入白名单。逻辑死循环或内存泄漏检查代码中是否有无限循环且没有sleep或者Image对象没有正确recycle()。使用log()输出关键节点状态有助于定位问题。6.4 文本或图像查找不到现象明明肉眼能看到屏幕上有“欢迎”二字但textContains(“欢迎”).findOne()就是返回null。排查控件识别问题使用AutoJs提供的“布局范围分析”功能悬浮窗菜单里查看目标文本是否真的被识别为一个TextView控件。有时文字可能是画在Canvas上的无法通过控件选择器获取。延迟问题网络加载慢文字可能还没显示出来。在查找前适当增加sleep或者使用waitFor()函数等待控件出现。多语言或编码确保脚本中的文本字符串与屏幕上显示的完全一致包括空格和标点。图像识别阈值对于images.findImage()默认的匹配阈值相似度可能太高。可以尝试降低阈值例如images.findImage(screen, template, {threshold: 0.7})但太低会增加误报。6.5 实战心得与建议日志是你的眼睛在关键节点循环开始、条件判断、截图前后、保存前后使用log()输出信息。调试时可以将日志级别调高稳定运行后可以减少日志输出以提升性能。从简单开始逐步复杂化先实现一个最简单的定时截图并保存的功能。确保这个基础流程稳定后再加入条件判断、图像处理等复杂逻辑。这样出了问题更容易定位。考虑使用Pro版本AutoJs Pro版本提供了更稳定的服务、更丰富的API如OCR识别和云控功能。对于需要长期稳定运行或功能更复杂的项目Pro版本是值得投资的。电量与性能平衡检查间隔CHECK_INTERVAL不宜设置过短如小于1秒会非常耗电。根据实际需求30秒到5分钟通常是比较合理的范围。在非活跃期如深夜可以通过代码动态延长检查间隔。代码版本管理即使是小脚本也建议使用Git或简单地将代码备份到云端。在修改代码之前先备份一份能工作的版本。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价