function autoSerivce() {
if (auto.service !== null) {
return;
}
auto.waitFor();
}
function launch(appName) {
if (typeof appName !== "string") {
return;
}
let name;
if (appName) {
if (appName.startsWith("com.")) {
name = appName;
}
else {
name = app.getPackageName(appName);
if (name == null) {
return;
}
}
app.launchApp(name);
util.debuglog(app.getPackageInfo(name));
return name;
}
}
function controlClick(selector, retry = 3) {
while (retry--) {
if (selector.exists()) {
break;
}
selector.waitFor(1000);
}
if (retry < 0) {
throw new Error("元素未找到");
}
let flag = selector.click();
if (flag) {
console.log("点击成功");
return;
}
throw new Error("点击失败");
}
function whileClick(selector, number) {
if (number == 0) {
return;
}
selector = uiselector.className('android.widget.TextView').clickable().text(`剩${number}次`).findOne();
controlClick(selector);
whileClick(selector, number - 1);
}
function getControlText(selector) {
let text = selector.text();
if (text == '' && selector.exists()) {
throw new Error("控件无文本或者控件不存在");
}
return text;
}
setScreenMetrics(1440, 3200);
const main = () => {
device.keepScreenDim(3600 * 1000);
autoSerivce();
let appName = "com.eg.android.AlipayGphone";
appName = launch(appName);
// let i = app.intent({
// action: 'VIEW',
// packageName: appName,
// className: 'com.alipay.mobile.nebulax.xriver.activity.XRiverActivity'
// });
// Context.startActivity(i);
// let uisel = uiselector.className('android.widget.Button').clickable().text('福利').findOne();
// uiselClick(uisel);
// whileClick(uisel,);
// device.cancelKeepingAwake();
}
main();
回答
根据你提供的代码和报错信息“形参后缺少')'”,表面上看是某个函数的参数定义有语法错误,但实际上你的代码中并没有明显的语法问题。这可能是由于某些隐藏字符或代码编辑器的问题导致的误报。
以下是逐步排查和解决问题的方法:
1. 检查是否是隐藏字符导致的问题
有时,脚本文件中可能包含不可见的特殊字符(如 BOM 头或其他编码问题),这些字符可能导致解析器在处理代码时出错。解决方法如下:
- 将代码复制到一个新的文件中。
- 使用一个可靠的文本编辑器(如 VS Code、Notepad++ 等)重新保存文件,确保文件编码为 UTF-8(无 BOM)。
- 再次运行脚本,看看问题是否解决。
2. 逐行注释排查
如果问题仍然存在,可以尝试通过注释掉部分代码来定位具体出错的位置:
- 在
main
函数中注释掉所有调用的函数,仅保留device.keepScreenDim(3600 * 1000);
和autoSerivce();
。 - 如果此时脚本可以正常运行,则逐步取消注释其他函数调用,直到找到触发错误的具体代码。
例如:
const main = () => {
device.keepScreenDim(3600 * 1000);
autoSerivce();
// let appName = "com.eg.android.AlipayGphone";
// appName = launch(appName);
};
3. 检查疑似问题点
虽然从语法上看没有明显错误,但以下几处可能需要特别注意:
(1) whileClick
函数中的递归调用
function whileClick(selector, number) {
if (number == 0) {
return;
}
selector = uiselector.className('android.widget.TextView').clickable().text(`剩${number}次`).findOne();
controlClick(selector);
whileClick(selector, number - 1); // 递归调用
}
这里需要注意:
- 如果
selector
在递归过程中变为无效值,可能会导致后续调用失败。 - 你可以尝试将
selector
的赋值移到函数外部,避免重复查找。
修改后的代码:
function whileClick(number) {
if (number == 0) {
return;
}
let selector = uiselector.className('android.widget.TextView').clickable().text(`剩${number}次`).findOne();
controlClick(selector);
whileClick(number - 1); // 递归调用
}
(2) controlClick
函数中的 while
循环
function controlClick(selector, retry = 3) {
while (retry--) {
if (selector.exists()) {
break;
}
selector.waitFor(1000);
}
if (retry < 0) {
throw new Error("元素未找到");
}
let flag = selector.click();
if (flag) {
console.log("点击成功");
return;
}
throw new Error("点击失败");
}
这里的逻辑应该没有问题,但如果你担心 selector
对象的状态变化,可以在每次循环中重新获取 selector
。
修改后的代码:
function controlClick(selector, retry = 3) {
while (retry--) {
selector = selector.selector; // 确保 selector 是最新的
if (selector.exists()) {
break;
}
selector.waitFor(1000);
}
if (retry < 0) {
throw new Error("元素未找到");
}
let flag = selector.click();
if (flag) {
console.log("点击成功");
return;
}
throw new Error("点击失败");
}
4. 验证工具或环境版本
如果你确认代码没有语法问题,但仍然报错,可能是运行环境(如 Hamibot 或 Hamibot)的版本问题:
- 检查你使用的工具版本是否是最新的。
- 查阅相关工具的官方文档或社区论坛,确认是否有类似问题的报告。
5. 调试信息输出
在关键位置添加调试日志,帮助定位问题。例如:
console.log("执行 autoSerivce 函数");
autoSerivce();
console.log("尝试启动应用");
let appName = "com.eg.android.AlipayGphone";
appName = launch(appName);
console.log("应用启动完成:", appName);
console.log("尝试点击控件");
let selector = uiselector.className('android.widget.Button').clickable().text('福利');
controlClick(selector);
6. **总结
本回答由 AI 生成,内容仅供参考
ℹ️ 本回答由 AI 生成,内容仅供参考
function autoSerivce() {
if (auto.service !== null) {
return;
}
auto.waitFor();
}
function getAppPackageName(appName) {
if (!appName) {
throw new Error("appName参数不能为空");
}
if (typeof appName !== "string") {
throw new Error("appName参数必须为字符串");
}
let name;
if (appName.startsWith("com.")) {
name = appName;
}
else {
name = app.getPackageName(appName);
if (name == null) {
throw new Error("应用不存在");
}
}
return name;
}
function launch(appName) {
let name = getAppPackageName(appName);
app.launchApp(name);
util.debuglog(app.getPackageInfo(name));
return name;
}
function getControlExists(selector) {
if (selector.exists()) {
return true;
}
return false;
}
function controlClick(selector, retry = 3) {
if (getControlExists(selector) == false) {
return;
}
while (retry--) {
if (selector.exists()) {
break;
}
selector.waitFor(1000);
}
if (retry < 0) {
throw new Error("元素未找到");
}
let flag = selector.click();
if (flag) {
console.log("点击成功");
return;
}
throw new Error("点击失败");
}
function whileClick(selector, number) {
if (getControlExists(selector) == false) {
return;
}
if (number == 0) {
return;
}
selector = uiselector.className('android.widget.TextView').clickable().text(`剩${number}次`).findOne();
controlClick(selector);
whileClick(selector, number - 1);
}
function getControlText(selector) {
let text = selector.text();
if (text == '' && selector.exists()) {
throw new Error("控件无文本或者控件不存在");
}
return text;
}
setScreenMetrics(1440, 3200);
const main = () => {
device.keepScreenDim(3600 * 1000);
autoSerivce();
let appName = "com.eg.android.AlipayGphone";
appName = launch(appName);
// let i = app.intent({
// action: 'VIEW',
// packageName: appName,
// className: 'com.alipay.mobile.nebulax.xriver.activity.XRiverActivity'
// });
// Context.startActivity(i);
// let uisel = uiselector.className('android.widget.Button').clickable().text('福利').findOne();
// uiselClick(uisel);
// whileClick(uisel,);
// device.cancelKeepingAwake();
}
main();
还是报错:运行的形参后缺少")".(脚本id.js#32)形参后缺少")"
确认hamibot版本为最新
function controlClick(selector, retry = 3)
不支持默认参数值,把 retry = 3 改掉