AI SDK 统一就绪门禁设计

1. 目标

为菜品管理、菜品学习、菜品识别等依赖银歌 AI SDK 的业务建立统一的前置检查,确保只有在“插件可用、SDK 初始化成功、设备真实已激活”后才进入具体业务。

本设计解决以下问题:

2. 已确认的产品规则

  1. 检查顺序固定为:插件可用性、SDK 初始化、插件强制升级状态、SDK 真实激活状态、具体业务。
  2. DishManagementActivity 在门禁通过前不请求菜品及学习数据,不执行校正。
  3. 设备未激活时弹出不可通过点击外部区域关闭的提示框。
  4. 用户选择“前往设置”时,进入基础设置并定位 AI 菜品识别激活项。
  5. 用户拒绝处理或选择“返回主页”时,明确返回 MainActivity
  6. 从设置页返回后必须重新查询 SDK 真实激活状态,不能仅相信页面返回值或本地缓存。
  7. 不在业务页面自动使用保存的激活码激活;激活由用户在设置页主动完成。

3. 方案选择

采用在 AiSdkManager 中建设统一“AI 就绪门禁”的方案。

不采用以下方案:

4. 就绪条件与状态模型

AI 业务真正可用必须同时满足:

插件已安装
+ 插件版本不要求强制升级
+ SDK 服务初始化成功
+ queryAiActiveStatus() 返回已激活
= READY

统一状态定义:

enum AiReadyState {
    IDLE,
    INITIALIZING,
    CHECKING_ACTIVE,
    READY,
    NOT_ACTIVE,
    PLUGIN_NOT_INSTALLED,
    UPGRADE_REQUIRED,
    INIT_TIMEOUT,
    SERVICE_ERROR
}

SETTING_AI_DISH_ACTIVATED 只作为设置页展示缓存,不能作为业务放行依据。业务放行以本次 SDK 会话中的 queryAiActiveStatus() 结果为准。

5. 总体流程

进入 AI 业务页面
  -> 请求统一门禁 ensureAiReady()
  -> 初始化 SDK 服务
  -> SDK 回调插件未安装:提示安装,拒绝则返回主页
  -> SDK 回调必须升级:提示升级,拒绝则返回主页
  -> SDK 初始化成功:调用 queryAiActiveStatus()
  -> 已激活:状态置为 READY,继续业务
  -> 未激活:提示前往设置,拒绝则返回主页
  -> 设置页激活成功返回:使旧状态失效并重新执行完整门禁

不能在插件未安装时先查询激活状态,因为激活状态由插件服务提供;插件服务不可用时,查询结果不可信。

6. AiSdkManager 设计

6.1 对外接口

public interface ReadyCallback {
    void onReady(@NonNull YingeoAiSDK sdk);

    void onBlocked(
            @NonNull AiReadyState state,
            @NonNull String message
    );
}

public void ensureAiReady(
        @NonNull Activity activity,
        @NonNull ReadyCallback callback
);

public void invalidateReadyState();

public void markNotActive(@Nullable String message);

public AiReadyState getReadyState();

页面只消费统一结果,不再自行组合初始化、插件、升级和激活判断。

6.2 单次并发机制

同一时间只允许一次初始化或激活状态查询:

6.3 初始化处理

  1. 调用 initAiService()
  2. 收到 onInitSuccess() 后再查询激活状态。
  3. 收到 SDK_PLUGIN_NOT_INSTALL,进入 PLUGIN_NOT_INSTALLED
  4. 收到 PLUGIN_MUST_UPGRADE,进入 UPGRADE_REQUIRED
  5. 初始化超过 10 秒且没有进入插件安装交互时,进入 INIT_TIMEOUT
  6. 用户正在安装或升级插件时暂停普通初始化超时;安装完成后重新开始初始化计时。

6.4 激活状态查询

SDK 初始化成功后,在后台线程调用 queryAiActiveStatus()

所有页面回调切回主线程。

6.5 状态失效

以下情况必须清除 READY

7. DishManagementActivity 流程

7.1 页面启动

当前的启动顺序需要由:

初始化 SDK -> 注册监听 -> 立即 syncDishList()

调整为:

初始化页面 -> 注册监听 -> ensureAiReady()
                         -> READY 后 syncDishList()

门禁检查期间:

7.2 门禁成功

onReady() 后:

  1. 关闭就绪检查提示。
  2. 启用业务按钮。
  3. 执行现有菜品及学习数据同步。
  4. 下载和保存完成后执行 learnDateRivise()

7.3 运行中状态失效

即使门禁曾通过,learnDateRivise() 仍需处理 NOT_ACTIVE

  1. 调用 markNotActive()
  2. 停止后续处理,不自动重试。
  3. 显示未激活弹框。
  4. 用户完成设置后重新从完整同步流程开始。

8. 未激活弹框与导航

提示文案:

AI 菜品识别设备尚未激活,暂时无法进行菜品学习和数据校正。
请前往设置页填写激活码并完成激活。

按钮:

行为:

9. 设置页集成

SettingActivity 使用专用流程参数进入激活处理:

EXTRA_AI_DISH_ACTIVATION_FLOW = true;

该流程固定展示基础设置,并向 SettingsBasicFragment 传递定位参数。基础设置页收到参数后:

如果用户取消、激活失败或直接退出设置页,返回 RESULT_CANCELED

10. 从设置页返回

业务页面使用 Activity Result 接收结果:

不单独依赖普通 onResume(),避免弹框、权限页或屏幕切换造成重复检查。

11. 插件未安装与强制升级

11.1 插件未安装

提示用户安装银歌 AI 插件:

插件安装成功后重新执行“初始化 -> 版本检查 -> 激活状态查询”。

11.2 插件必须升级

提示当前版本无法继续使用:

升级完成后旧的初始化和激活缓存全部失效,必须重新走完整门禁。

11.3 统一下载与安装弹框

项目不再直接展示 SDK 内置下载弹框,由 AiPluginUpdateDialogAiPluginUpdateManager 统一承接安装、强制升级和基础设置激活中的插件更新流程:

  1. 后台调用 SDK 的版本查询能力获取 AppInfoBean
  2. 弹框展示版本号和更新内容;真实下载地址仅供后台校验与下载,不在界面显示。
  3. 下载统一调用 PluginManager.downloadFile(),将 onProgress(int) 映射为 0 至 100 的进度条和百分比。
  4. 下载中与正在拉起安装器时禁止取消,避免业务页在插件状态不确定时继续运行。
  5. 下载失败可在原弹框重试;下载完成后按钮切换为“立即安装”。
  6. 目标设备通过 SmdtManagerNew.sys_doSilentInstallApp() 后台安装,项目弹框在安装阶段 切换为“AI算法SDK更新”,不再展示 Android 系统安装器。
  7. 安装完成后同时校验实际已安装包版本,并向统一 SDK 门禁发送安装成功事件;SDK 自身 的包安装广播作为补充,两类事件去重后触发完整门禁复查。

下载前必须校验地址为带有效主机名的 HTTPS URL;下载完成后必须校验文件存在、非空, 且 APK 包名为 com.yingeo.ai.sdk。后台安装前必须确认主板服务可用,安装后必须确认目标 插件版本已生效;任一校验失败均停止流程并在项目弹框显示明确错误。

11.4 弹框风格统一

AI 门禁与插件更新流程的弹框统一复用项目现有视觉基线:固定 common_pop_width、白色圆角 卡片、白色标题栏与黑色标题文字、标题分隔线、灰色正文、左侧次按钮和右侧橙色主按钮。 覆盖范围包括:

AI 服务检查和基础设置激活中的等待提示直接复用 NewSingleTipPopsingle_tip_pop_layout.xml,仅隐藏底部操作区,不再维护独立加载弹框或显示系统样式的 圆形进度控件,确保其卡片尺寸、白色标题栏、分隔线和正文排版与项目提示框完全一致。

弹框外部区域均不可关闭;下载中和安装中禁用取消。未激活提示的返回键、返回主页及前往 设置行为不变,插件安装和升级提示在打开下载弹框后继续保留业务阻断。

12. 数据安全

当前校正流程会在 SDK 校正前清理现有学习图片。实施时应改为临时目录准备和成功后替换:

  1. 下载远端图片到临时目录。
  2. 验证图片数量、编码和文件可读性。
  3. 门禁仍为 READY 时执行 SDK 校正。
  4. SDK 校正成功后再替换正式学习图片目录。
  5. 任一步失败都保留原有正式目录。

这部分与就绪门禁同时实施,避免解决激活问题后仍存在数据破坏风险。

13. 错误映射与日志

页面提示必须区分:

状态 用户提示
PLUGIN_NOT_INSTALLED 未安装 AI 插件
UPGRADE_REQUIRED AI 插件版本过低,必须升级
NOT_ACTIVE 设备尚未激活,请前往设置处理
INIT_TIMEOUT AI 服务初始化超时,请重试
SERVICE_ERROR AI 服务异常,请重启插件或设备
网络失败 菜品数据请求失败,请检查网络
图片下载失败 学习图片下载失败
图片保存失败 学习图片保存失败,请检查存储空间
SDK 校正失败 显示 SDK 返回的具体错误信息

日志至少包含:页面、操作、门禁状态、SDK code、SDK message、耗时和本地数据准备状态。禁止记录激活码。

14. 测试范围

14.1 单元测试

14.2 页面测试

14.3 数据安全测试

15. 验收标准

  1. 所有依赖银歌 AI SDK 的页面统一通过 AiSdkManager.ensureAiReady() 放行业务。
  2. 插件未安装时绝不先查询激活状态。
  3. 未激活时 DishManagementActivity 不发起菜品学习业务请求。
  4. 未激活弹框的“前往设置”和“返回主页”行为符合已确认规则。
  5. 设置页返回后以 SDK 真实状态重新校验。
  6. 页面不再把 10041010 等错误统一显示为“学习数据校正失败”。
  7. 并发进入多个 AI 页面不会重复初始化 SDK。
  8. 同步或校正失败不会破坏原有可用学习数据。

16. 预计修改范围

17. 风险与边界

18. 实施结果

2026-07-21 已按本设计完成项目落地:

设备侧插件安装、强制升级和激活交互尚未安装本次 APK 实测,仍需在目标设备上完成五类场景验收。