mainThread6 = threads.start(function () {
console.log(11111);
className('android.view.View').depth(19).indexInParent(0).desc('泡泡玛特').findOne();
console.log('下单成功,请付款!🎁');
// 商品名称
const productName1 = className('android.widget.TextView').depth(20).indexInParent(1).findOnce();
const productName = productName1 && productName1.text();
// 商品总额
const productAmount1 = className('android.widget.TextView').depth(19).indexInParent(8).findOnce();
const productAmount = productAmount1 && productAmount1.text();
http.post('http://192.168.1.150:3000/api/purchase-records', {
deviceBrand: device.brand,
deviceModel: device.product,
purchaseTime: new Date().toISOString(),
productName: productName,
productAmount: productAmount
});
if (isRing) playMusic();
});
这段代码报错Thread[ScriptThread-30[684f7c2d29cc438f9ade8304.js] (Spawn-3),5]: Wrapped java.lang.NullPointerException: value == null (file:///android_asset/modules/http.js#130)
Wrapped java.lang.NullPointerException: value == null
at fillPostData (file:///android_asset/modules/http.js:130:0)
at file:///android_asset/modules/http.js:23:0
at 684f7c2d29cc438f9ade8304.js:2646:0
回答
文档地址 https://docs.hamibot.com/
你遇到的错误是:
Wrapped java.lang.NullPointerException: value == null
at fillPostData (file:///android_asset/modules/__http__.js#130)
这说明你在调用 http.post() 时,请求体中的某个字段值为 null,而 Hamibot 的 http 模块在序列化请求数据时不允许 null 值。
❌ 问题定位
你的代码中以下部分可能返回 null 或 undefined:
const productName1 = className('android.widget.TextView').depth(20).indexInParent(1).findOnce();
const productName = productName1 && productName1.text();
const productAmount1 = className('android.widget.TextView').depth(19).indexInParent(8).findOnce();
const productAmount = productAmount1 && productAmount1.text();
如果控件未找到,productName1 或 productAmount1 就是 null,导致 text() 调用失败或返回 undefined,最终传入 http.post 的 productName 或 productAmount 为 null,触发异常。
✅ 解决方案
你需要确保所有发送的数据都是非 null 的字符串。建议对可能为空的字段做默认值处理。
修改后的代码如下:
// 文档地址 https://docs.hamibot.com/
mainThread6 = threads.start(function () {
console.log(11111);
className('android.view.View').depth(19).indexInParent(0).desc('泡泡玛特').findOne();
console.log('下单成功,请付款!🎁');
// 商品名称(提供默认值)
const productName1 = className('android.widget.TextView').depth(20).indexInParent(1).findOnce();
const productName = productName1 ? productName1.text() : '未知商品';
// 商品总额(提供默认值)
const productAmount1 = className('android.widget.TextView').depth(19).indexInParent(8).findOnce();
const productAmount = productAmount1 ? productAmount1.text() : '0';
// 确保不发送 null,全部转为字符串
const postData = {
deviceBrand: (device.brand || 'unknown'),
deviceModel: (device.product || 'unknown'),
purchaseTime: new Date().toISOString(),
productName: String(productName),
productAmount: String(productAmount)
};
http.post('http://192.168.1.150:3000/api/purchase-records', postData);
if (isRing) playMusic();
});
🔍 关键修改点说明:
-
使用三元运算符防止
null:const productName = productName1 ? productName1.text() : '未知商品'; -
兜底转换为字符串:
使用String(...)包裹确保不会传null。 -
设备信息也加容错:
device.brand和device.product虽然通常存在,但加上|| 'unknown'更安全。 -
避免异步风险:
当前逻辑依赖 UI 查找,建议在findOne()后加超时控制或判断是否存在,例如:const targetView = className('android.view.View').desc('泡泡玛特').findOne(5000); if (!targetView) { console.error('未找到目标页面,可能下单失败'); return; }
✅ 最佳实践建议
- 所有传递给
http请求的数据必须做空值校验。 - 在关键节点打印日志便于调试:
console.log('准备发送数据:', JSON.stringify(postData)); - 使用
try-catch捕获网络请求异常:try { http.post(url, postData); } catch (e) { console.error('网络请求失败:', e.message); }
这样可以避免因个别字段为空导致脚本崩溃。