Skip to content

[Feature][Android] 手机端增加整套配置一键导入/导出,支持换机继承和分享,系统权限仍由用户授权 #1192

Closed

Description

@huxiaoyuqn

功能建议

建议在手机端(优先 Android)增加整套配置一键导出、导入功能,支持用户换机继承,也支持将已经调好的配置分享给其他用户。系统权限仍由接收者在自己的手机上逐项授权;除此之外,应用内可迁移的配置尽量都可继承,避免逐项手动重复填写。

使用背景与目前负担

希望普通用户在安装官方 APK 后导入一份完整可用的配置后,再完成系统权限授权,就可以开始正常使用。

现有手机端可以导入风格 ZIP、粘贴词库,但仍需分别设置服务渠道、接口地址、模型、API Key、当前风格和其他应用偏好。对于普通用户,步骤较多,容易漏填、选错渠道或误用接口路径。每次换机或新用户使用都要重复这一过程。

本建议以目前分发的 Android 稳定版 1.3.18 为主要使用场景。润色风格建议仍可以通过 ZIP 导入增加;希望提供无需同一账号、无需云同步即可完成的本地配置导入/导出入口。

建议支持的配置范围

  • AI 服务和渠道:ASR、LLM、适用的其他服务,协议类型、渠道名称、Base URL/完整接口地址、模型、激活渠道、启用状态及高级参数。
  • 词典和词库:通用/可选预设、用户词条、当前激活的词库和相关配置。
  • 润色配置:风格包、提示词、示例及当前默认风格,保证导入后引用关系正确。
  • 手机端应用偏好:界面语言、主题、输入与剪贴板策略、适用的录音/触发方式和其他可迁移设置。只继承功能开关和参数,不代表系统权限已经获得。
  • API Key:支持由导出者明确选择是否包含。普通分享默认脱敏;当导出者明确授权包含 Key 时,可勾选将其加入,导入后自动填入对应的 ASR/LLM 渠道,减少接收者复制粘贴负担。

建议操作流程

  1. 导出页提供“个人迁移”和“分享配置”两类用途,以及分类勾选、包含凭据的显式确认。
  2. 导出统一、带 schema/version 信息的 JSON 或 ZIP,可通过系统文件分享交给接收者;优先实现本地文件入口,链接/二维码导入可作为后续增强。
  3. 导入时显示来源、版本、包含的类别、是否含 Key 和变更摘要,允许选择合并或替换;自动备份原配置,避免覆盖用户自己的账号或密钥。
  4. 导入完成后,正确应用当前渠道、词库、风格及偏好,并提醒用户进行权限授予。
  5. 不兼容或当前设备不可用的设置明确提示并跳过/要求用户选择,不静默失败。

系统权限与安全边界

  • 麦克风、输入法启用、悬浮窗、无障碍、自启动/后台运行等权限仍由手机用户在系统中授权。配置文件不得自动授权、绕过限制或关闭系统安全保护。
  • 可以恢复“希望使用音量键/悬浮窗等功能”的应用设置,但应显示尚需授权的提示,不把开关已开启当成权限已生效。
  • 不直接复制 Android Keystore 密文到另一设备;若选择导出服务凭据,应通过明确授权的可迁移格式保存,导入后由新设备自己的安全存储保护。含凭据的导出建议支持密码加密并给出分享风险提示。
  • GitHub/OAuth 登录令牌、设备私钥、设备绑定凭据等不作为普通分享内容;历史、统计、录音也不默认随配置模板导出。服务 Key 的纳入与否单独让用户选择。
  • 设备相关路径、麦克风设备 ID 等不能直接假设在另一台手机有效,导入时应校验并提示。

期望效果/验收标准

在新手机上安装官方 APK 后,导入配置文件即可继承服务参数、被授权分享的临时 Key、词库、风格及适用偏好;接收者无需再逐项填写这些内容。用户只需完成必要的系统权限授权和首次使用测试。已有用户可保留自己的凭据,不会因导入模板而被静默覆盖。

该功能也方便配置备份、换机和多人共享,同时不依赖共用云同步账号。当前仅提出功能建议,不一定合理可行。

Activity

  1. HKLHaoBin commented on Oct 14, 2026

    @HKLHaoBin
    Collaborator

    满足你。

  2. HKLHaoBin commented on Oct 15, 2026

    @HKLHaoBin
    Collaborator

    @huxiaoyuqn 你好,完整实现已放在 PR #1199,并已完成 CI 和构建验证,麻烦你在 Android 真机上帮忙测试一下。

    测试产物与日志:

    Android 入口位置:应用设置 → Privacy → 本地配置迁移。

    重点请测试:

    1. ShareRedacted 默认脱敏分享;
    2. PersonalMigration 的密码保护凭据导出与错误密码处理;
    3. SAF 文件导入/导出、预览、Merge/Replace 和冲突选择;
    4. 导入前备份、恢复失败回滚;
    5. 所有 ASR/LLM/Omni 渠道、词典、纠错规则、风格包和 Android 应用偏好;
    6. 系统权限、OAuth 会话、设备路径和运行时状态不会被迁移;
    7. 键盘专属设置页仍正常工作且不显示迁移入口。

    真机型号、Android 版本和发现的问题请直接回复在这个 issue 中,谢谢!

  3. huxiaoyuqn commented on Oct 15, 2026

    @huxiaoyuqn
    Author

    真机测试反馈

    已在 Android 设备上测试 https://github.com/HKLHaoBin/openless/actions/runs/38686219635 构建的 APK。

    测试环境

    • APK 版本:v2.0.0-Beta.4+build.20260930
    • 测试设备:Xiaomi 13
    • Android 版本:16(Android 安全更新:2026-08-01)
    • 系统版本:HyperOS 3.0.309.0.WMCCNXM.C11
    • 处理器:第二代骁龙® 8 核动平台

    测试结果

    ✅ 导出功能正常

    • ShareRedacted 模式:成功导出 .omb 文件
    • PersonalMigration 模式:成功导出 .omb 文件(包含加密凭据)

    ❌ 导入功能存在问题

    1. PersonalMigration 模式导入失败
    Image

    • 现象:选择"合并"或"替换"后,均显示错误:
    Image
    导入未完成:migration_bundle_stale_preview
    
    • 影响:无法完成个人迁移模式的配置导入
    • 重现步骤:
      1. 导出 PersonalMigration 模式的 .omb 文件
      2. 尝试导入该文件
      3. 输入密码后,选择"合并"或"替换"
      4. 出现错误提示

    2. ShareRedacted 模式冲突处理问题

    • 现象:导入时提示冲突,显示:
    Image
    选择冲突 1/2
    channels / no_common_baseline(凭据关联渠道)
    
    • 问题:底部提示"必须选择一侧",但对话框中没有可选择的选项(无单选按钮或其他交互元素)
    • 影响:用户无法解决冲突,导入流程卡死,无法继续
    • 重现步骤:
      1. 导出 ShareRedacted 模式的 .omb 文件
      2. 尝试导入该文件
      3. 出现冲突提示,但无法进行选择

    关于 Legacy JSON 兼容性测试

    尝试导入 .omb 解压后的 documents.json,应用提示"它不是一个有效的配置文件"。从代码来看,Legacy JSON 应该指旧版 OpenLessSettingsExport 格式。

    建议:

    • 能否提供一个 Legacy JSON 样例文件用于测试?
    • 或说明如何从当前版本生成用于测试的 Legacy JSON?

    需要修复的问题

    1. 高优先级:migration_bundle_stale_preview 错误导致 PersonalMigration 模式完全无法导入
    2. 高优先级:ShareRedacted 模式冲突解决界面缺少选择按钮/选项,导致流程卡死
    3. 中优先级:补充 Legacy JSON 测试文档或样例

    @HKLHaoBin 请查看以上问题,如需 logcat 日志或更多信息请告知。

  4. HKLHaoBin commented on Oct 16, 2026

    @HKLHaoBin
    Collaborator

    感谢您的测试与日志,我将根据暴露出来的问题着手进行修复。

  5. HKLHaoBin commented on Oct 16, 2026

    @HKLHaoBin
    Collaborator

    最终 Android 构建已完成,欢迎 issue 提出者下载并测试:\n\n- Actions run:https://github.com/HKLHaoBin/openless/actions/runs/38924735891\n- 构建提交:524067a803e342957ffbdf0d14daac490366d151\n- Artifact:OpenLess_2.0.0-Beta.4+build.20260930_arm64-v8a.apk\n- SHA-256:8bb5b34664fca58d4e171fb5c0734ed596618e8cf0933282a3e289ccd06536c9\n\n请从 Actions 页面的 artifact 下载 arm64 APK,安装后进入“设置 → 权限与数据 → 本地配置迁移”,使用迁移 bundle 测试导入/导出流程。该版本已在真实 Android 设备上完成最终导入验证。

  6. huxiaoyuqn commented on Oct 19, 2026

    @huxiaoyuqn
    Author

    真机复测:导入导出已可用,几个体验点建议

    测试版本:openless-android-release-arm64-v8a(包名 com.openless.app),Xiaomi 13 / Android 16 / HyperOS 3.0.309.0。

    1. 功能本身

    导入导出基本没有问题,个人迁移和脱敏分享两种模式都很顺手,极大降低了换机 / 分享配置的门槛。之前反馈的 migration_bundle_stale_preview 和冲突选项缺失都已解决,非常感谢。

    2. 「选择冲突」的描述建议更具体

    导入过程中会连续弹出 15 个冲突确认,标题形如:

    • preferences / no_common_baseline
    Image
    • ui_preferences / no_common_baseline
    Image
    • style_packs / no_common_baseline
    Image

    no_common_baseline 这类内部枚举名对普通用户没有信息量,用户很难判断该选「保留当前设备」还是「使用迁移文件」。建议:

    • 用中文(或跟随界面语言)描述冲突类型,例如「应用偏好:本机与迁移文件均无共同基线,需选择以哪一侧为准」;
    • 直接列出该冲突涉及的文档数量或条目名,让用户知道自己在决定什么;
    • 如果整包都是同类冲突(我这次 15 个全是 no_common_baseline),可以提供「全部保留当前设备 / 全部使用迁移文件」的一键选择。

    我这边是一律选「使用迁移文件」,目前没有发现问题。

    3. 冲突选择之后,合并 / 替换还有必要吗?

    看代码后的理解:两者语义不重叠,理论上都该保留。

    • 冲突选择是逐文档的:只影响「两边都有、且无法自动判定」的条目;
    • 合并 / 替换是全局策略:决定迁移包里没有的条目,要不要保留本机现有的。

    但实际实现里有个矛盾:RestoreMode::Replace 分支直接 desired = bundle_documents 整体覆盖,preview.resolve(choices) 只在 RestoreMode::Merge 分支执行;Kotlin 侧 applyPortable = mode == "replace" || ... 也是短路成 true。

    也就是说:用户先认真选完 15 次冲突,最后再选「替换」,那些选择会被整体丢弃。 建议二选一:

    • 选「替换」时跳过冲突步骤,直接确认覆盖;
    • 或者先问合并 / 替换,再只对合并模式展开冲突。

    4. 「备份已保留」的提示容易误解

    导入成功后提示「导入完成,备份已保留」。

    Image

    我在手机上找了半天没找到,查代码后确认备份写在应用私有内部存储:

    /data/data/com.openless.app/files/OpenLess/local-migration-backups/<uuid>.omb
    

    普通用户在文件管理器里(包括 Android/data)是看不到这个路径的,而且应用内也没有任何入口可以查看或恢复这份备份。

    建议至少调整文案:

    • 最省事:「导入完成」;
    • 或明确位置:「导入完成,导入前的配置已备份至应用私有目录」;
    • 更完整的话,可以后续加一个「查看 / 恢复本地备份」入口,并给这个目录加保留策略 —— 目前每次导入都会新增一个 <uuid>.omb,只增不减,没有轮转清理。

    5.

    感谢耐心跟进和反复出包,本地迁移这块现在确实好用了,相信能让 OpenLess 被更多人认可和使用。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions