一、技术背景与核心价值
在移动端自动化场景中,短信和电话功能的调用是高频需求,例如验证码自动读取、紧急呼叫触发或批量消息发送。Auto.js作为基于JavaScript的无障碍自动化工具,通过模拟用户操作或直接调用系统API,可实现非Root环境下的功能集成。其核心价值在于:
- 非侵入式操作:无需修改系统底层,通过无障碍服务模拟点击;
- 跨应用兼容性:支持短信App、拨号界面等系统原生功能;
- 脚本化控制:通过代码逻辑动态触发操作,适配复杂业务场景。
二、权限配置与前置条件
1. 基础权限要求
Android系统对短信、电话功能的调用有严格权限限制,需在AndroidManifest.xml中声明以下权限:
<uses-permission android:name="android.permission.SEND_SMS" /><uses-permission android:name="android.permission.CALL_PHONE" />
动态权限申请:Android 6.0+需在运行时请求权限,示例代码如下:
function requestPermission(permission) {if (!device.isPermissionGranted(permission)) {toast("请求权限: " + permission);device.requestPermissions([permission], function(result) {if (result === "granted") {toast("权限已授予");} else {toast("权限被拒绝");}});}}// 调用示例requestPermission("android.permission.SEND_SMS");
2. Auto.js环境依赖
- Auto.js版本要求:建议使用4.1.1+版本,支持更稳定的无障碍服务;
- 无障碍服务开启:需在系统设置中启用Auto.js的无障碍权限,否则无法模拟点击。
三、短信功能调用实现
1. 直接发送短信(需权限)
通过SmsManager API实现,代码示例:
function sendSMS(phoneNumber, message) {if (!device.isPermissionGranted("android.permission.SEND_SMS")) {toast("缺少短信发送权限");return;}try {const SmsManager = android.telephony.SmsManager;const smsManager = SmsManager.getDefault();smsManager.sendTextMessage(phoneNumber,null,message,null,null);toast("短信发送成功");} catch (e) {toast("发送失败: " + e);}}// 调用示例sendSMS("13800138000", "测试短信内容");
注意事项:
- 短信内容长度超过70字时需自动分段;
- 部分厂商系统可能限制后台发送短信。
2. 模拟点击短信App发送
适用于无Root权限的场景,通过无障碍服务模拟操作:
function sendSMSViaApp(phoneNumber, message) {// 启动短信Appapp.startActivity({action: "VIEW",data: "sms:" + phoneNumber,packageName: "com.android.mms"});// 等待界面加载(需根据实际设备调整延迟)sleep(2000);// 模拟输入内容(需定位EditText控件)const editText = className("EditText").findOne(1000);if (editText) {editText.setText(message);// 点击发送按钮(需定位Button控件)const sendButton = className("Button").text("发送").findOne(1000);if (sendButton) {sendButton.click();toast("短信已通过App发送");}}}
优化建议:
- 使用
id()或desc()替代className()提高控件定位准确性; - 添加超时重试机制。
四、电话功能调用实现
1. 直接拨号(需权限)
通过Intent调用系统拨号界面:
function makePhoneCall(phoneNumber) {if (!device.isPermissionGranted("android.permission.CALL_PHONE")) {toast("缺少拨号权限");return;}try {const intent = new Intent("android.intent.action.CALL");intent.setData(uri.parse("tel:" + phoneNumber));intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(intent);toast("拨号中...");} catch (e) {toast("拨号失败: " + e);}}// 调用示例makePhoneCall("10086");
2. 模拟点击拨号界面
适用于需要控制拨号后操作的场景:
function makeCallViaApp(phoneNumber) {// 启动拨号Appapp.startActivity({action: "android.intent.action.DIAL",data: "tel:" + phoneNumber});sleep(1500);// 模拟点击拨号按钮(需根据实际界面调整)const dialButton = className("ImageView").desc("拨号").findOne(1000);if (dialButton) {dialButton.click();toast("已触发拨号");}}
五、异常处理与安全实践
1. 权限拒绝处理
当用户拒绝权限时,应提供友好提示并引导至设置页:
function handlePermissionDenied(permission) {toast("权限被拒绝,请手动开启");const intent = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS");intent.setData(uri.parse("package:" + context.getPackageName()));intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(intent);}
2. 安全合规建议
- 敏感操作二次确认:在发送短信或拨号前弹出确认对话框;
- 日志脱敏:避免在日志中记录完整的电话号码或短信内容;
- 最小权限原则:仅申请必要的权限,避免过度授权。
六、性能优化与兼容性
-
控件定位优化:
- 优先使用
id()或text()定位控件; - 对动态界面添加
bounds()或clickable()条件过滤。
- 优先使用
-
多设备适配:
- 针对不同厂商ROM(如MIUI、EMUI)调整超时时间;
- 使用
auto.waitFor()确保界面加载完成。
-
后台服务稳定性:
- 避免在脚本中执行耗时操作,防止被系统回收;
- 对关键操作添加重试机制(最多3次)。
七、总结与扩展应用
通过Auto.js调用系统短信和电话功能,可实现以下典型场景:
- 自动化测试:验证短信验证码接收流程;
- 智能提醒:根据日程自动发送会议通知;
- 紧急求助:在特定条件下触发紧急呼叫。
进阶方向:
- 结合OCR技术读取短信验证码;
- 通过语音识别实现语音拨号;
- 与云端服务联动实现远程控制。
开发者需严格遵守Android权限规范,确保脚本行为符合用户预期,避免因滥用功能导致账号封禁或法律风险。