原版 Hamibot 原生是否在 AndroidManifest 内置声明了 MANAGE_EXTERNAL_STORAGE(管理所有文件)权限?启动 / 下载脚本时会不会主动弹窗申请该权限?
如果二次打包修改包名 / 应用名(你们改成 WLmob_AI),是否会丢失权限声明、导致无法申请全量文件读写权限,进而不能写入 Android/data/com.mzgy.svji/files/scripts 目录?
当 App 仅拥有媒体存储权限、没有全部文件权限时,脚本市场下载脚本是否会写入失败,scripts 文件夹空白?有无适配方案?
当前设备脚本市场点安装,前端显示安装成功,但 Android/data/com.mzgy.svji/files/scripts 文件夹为空,读文件直接返回不存在,是不是权限缺失导致写入拦截?

HAMI_6893877807 · 1 天前
第 1 条补充
·
19 小时前

环境说明
使用官方原版 Hamibot 1.6.7,Windows 网页后台发布脚本,安卓手机登录同一账号测试;
分为两个脚本:
守护大脚本:负责轮询读取/sdcard/Download/wla_command.json通讯文件,接收启停指令后拉起业务子脚本;
业务子脚本:网页发布为公开脚本,短识别码uzSy5,长市场 ID 6a4520ea0a9d685af56dd98f。
操作现象
通讯链路正常:守护可以完整读取、解析 json 文件内的启动 / 停止指令,指令识别无报错;
子脚本手动运行正常:手机脚本市场下载完成后,手动点击「运行」能正常打印日志、执行逻辑;
守护代码使用files.getInternalFilesDir()拼接scripts/长ID.js完整本地路径,调用files.exists()判断结果永远为 false;
使用files.listDir()遍历scripts目录,无任何文件输出,目录为空;
执行engines.execScriptFile(拼接好的本地完整路径),直接报错「云端脚本未同步,路径不存在」,拉起失败。
疑问与推测
网页公开下载到本地的市场脚本,是否不会持久化写入/data/user/0/com.hamibot.hamibot/files/scripts/目录?
files.exists、files.listDir 文件 API 是否无法读取市场下载脚本的私有缓存分区?仅能读取手动新建的本地脚本?
市场发布下载的脚本,是否不能使用execScriptFile本地文件接口拉起,只能通过短识别码engines.execScript("uzSy5", 传参)方式启动?
手动点击市场「运行」能执行,是走云端临时缓存,并非读取本地持久化文件?

回答

Hamibot AI
1
· 1 天前

原版 Hamibot 的 AndroidManifest.xml未内置声明 MANAGE_EXTERNAL_STORAGE 权限。Hamibot 严格遵循 Android 分区存储规范,脚本默认下载并保存在应用私有目录,无需也不依赖“管理所有文件”权限。启动或下载脚本时不会主动弹窗申请该权限。

针对你提出的四个问题,具体解答如下:

1. 原版是否声明全量文件权限及弹窗申请?
未声明,也不会弹窗申请。Hamibot 的脚本存储完全基于应用私有沙盒目录,系统默认授予该目录的读写权限,不需要动态申请 MANAGE_EXTERNAL_STORAGE 或外部存储权限。

2. 二次打包修改包名/应用名是否会导致权限丢失或写入失败?
会引发路径错配,而非权限丢失。修改包名(如 com.mzgy.svji)属于非官方二次打包行为。如果打包过程中未全局替换代码中硬编码的包名引用、未同步更新资源路径配置,会导致下载模块计算出的写入路径与实际运行环境不一致。这会造成“前端提示安装成功,但文件未落到预期位置”的现象。官方不保证二次打包版本的存储逻辑兼容性。

3. 仅有媒体权限时脚本市场下载是否会失败?有无适配方案?
不会失败。脚本市场下载仅依赖应用私有存储,与媒体权限或全量文件权限完全无关。若出现文件夹空白,根本原因是存储路径获取逻辑错误或二次打包配置遗漏。
适配方案:

  • 停止硬编码路径,全部改用 Android Context 动态获取。
  • 确保 AndroidManifest.xml 未错误配置 android:requestLegacyExternalStorage 等与目标 Android 版本冲突的属性。
  • 脚本文件读写统一使用 Hamibot 内置的 files 模块或 context.getFilesDir()

4. 前端显示安装成功但 Android/data/.../scripts 为空,是否为权限拦截?
不是权限拦截,而是目录认知偏差。Hamibot 脚本实际默认存储在应用内部私有目录 /data/data/<包名>/files/scripts,该目录受系统保护,普通文件管理器无法直接访问,也不位于外部存储的 Android/data/ 路径下。你在 Android/data/com.mzgy.svji/files/scripts 看不到文件是正常现象,因为脚本根本不会写入该位置。

排查与验证建议:

  1. 以 Hamibot 客户端「脚本管理」列表能否正常显示和运行为准,不要依赖第三方文件管理器查看外部目录。
  2. 在脚本开头添加以下代码,打印真实工作路径进行核对:
// 文档地址 https://docs.hamibot.com/
toastLog('当前工作目录: ' + files.cwd());
toastLog('内部私有目录: ' + context.getFilesDir().getAbsolutePath());
  1. 若需验证文件是否真实写入,可通过 adb shell run-as <包名> ls files/scripts 查看,或直接在 Hamibot 脚本中使用 files.listDir() 读取。
  2. 建议优先使用官方原版 Hamibot 进行功能验证。非官方修改版因包名替换、签名变更或配置遗漏引发的存储异常不在官方支持范围内。

如有原版 Hamibot 的脚本开发或路径调用问题,可提供具体日志,我会为你进一步定位。

ℹ️ 内容由 AI 生成,可能不准确,请注意核实
Hamibot AI
1
· 19 小时前

你的推测基本正确。Hamibot 的市场脚本(云端脚本)不会以明文 .js 文件形式持久化写入 /data/data/com.hamibot.hamibot/files/scripts/ 目录。files.exists()files.listDir() 无法读取是正常现象,engines.execScriptFile() 报错也是预期行为。以下是具体机制和正确做法。


市场脚本的存储与运行机制

1. 本地脚本 vs 云端脚本

  • files 模块能访问的 scripts/ 目录,仅用于本地脚本(在手机上手动新建或导入的脚本)。本地脚本以 .js 文件明文存储,可用 execScriptFile 直接执行。
  • 从脚本市场下载的公开脚本是云端脚本,其脚本内容加密存储在应用私有缓存区,不暴露给文件系统,也不在 scripts/ 目录下。这是为了保障脚本作者的知识产权和运行一致性。

2. 手动点击“运行”为什么能执行?
手动点击市场脚本的「运行」按钮,Hamibot 客户端会从云端拉取脚本内容到内存中执行,不依赖本地持久化文件。这个过程是云端同步 + 内存执行,所以你看到的“运行成功”不代表文件已经落盘到 scripts/

3. 为什么 execScriptFile 失败?
engines.execScriptFile(path) 的参数要求是一个本地文件系统的绝对路径,且该文件必须真实存在。由于市场脚本根本不在这个路径下,所以引擎抛出“云端脚本未同步,路径不存在”的错误。


正确拉起市场脚本的方式

使用 engines.execScript(name, config),通过短识别码市场 ID 启动云端脚本,并可以传递参数。

// 文档地址 https://docs.hamibot.com/

// 方式一:短识别码启动(推荐)
var result = engines.execScript("uzSy5", {
    arguments: {
        cmd: "start",
        from: "守护脚本"
    }
});

// 方式二:通过市场 ID 启动
// var result = engines.execScript("6a4520ea0a9d685af56dd98f", {
//     arguments: { cmd: "start" }
// });

if (result === true) {
    toastLog("子脚本已启动");
} else {
    toastLog("启动失败,请检查脚本是否存在或网络连接");
}

被调起的子脚本中,通过 engines.myEngine().execArgv 接收参数:

var execArgv = engines.myEngine().execArgv;
var args = execArgv.arguments || {};
var cmd = args.cmd; // "start"
var from = args.from; // "守护脚本"
toastLog("收到指令:" + cmd + ", 来源:" + from);

关键建议

  • 停止使用 files.getInternalFilesDir() 拼接路径去探测市场脚本,这条路走不通。
  • 云端脚本的启动、停止、传参全部交给 engines 模块的 execScriptstopAll 等接口完成,无需关心文件位置。
  • 守护脚本中如果需要根据指令停止子脚本,可以通过 engines.myEngine().id 记录引擎 ID,或使用 engines.all() 遍历查找并停止,避免文件依赖。

这样可以彻底解决“路径不存在”和“目录为空”的问题,让守护脚本稳定拉起业务子脚本。

ℹ️ 内容由 AI 生成,可能不准确,请注意核实