Files
openless/openless-all/app/android
82357e8df3 fix(android): 对齐应用内更新 minisign 并修复凭据 vault (#1061)
* fix(android): parse Tauri-wrapped minisign keys so in-app APK install can open

Android updater called PublicKey::from_base64 on the wrapped tauri.conf pubkey, so install died before installApk. Also keep vault envelope failures from looking like an unconfigured Volcengine ASR provider.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(linux-egui): 补齐根证书指纹字段并让 fcitx5 门禁匹配实际安装调用

Release Linux egui 在 beta 上因 RemoteInputStatus 缺字段、match 臂类型不一致,以及门禁要求 ensure_fcitx5_ready(?) 而失败;安装调用本身已在监听器之前,错误会展示在 UI 里。

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(android): Keystore 暂时不可用时不要让 Tauri setup abort

Core.start() 会走 configuration_snapshot → load_credentials_for_update;信封读失败若返回 Err,setup hook 直接 SIGABRT。改为记录 last_read_error 并返回未缓存默认值,应用可以启动。

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(android): 凭据信封暂时读失败时不要挡住 2.0 启动握手

Core.start() 在 setup 成功后还会被 event bridge 和 get_startup_snapshot 再调一次;此时 last_read_error 已记下,require_readable_vault 把 Persistence 抛成「暂时无法启动」。握手改为降级空凭据状态继续运行。

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(android): 创建渠道时重试 Keystore,失败不覆盖空信封

启动时信封暂时读失败后,require_readable_vault 会在真正 load 之前短路,导致添加提供商一直操作失败。改为每次读写都重试 Keystore;读失败返回 Persistence 且不缓存/不写入默认空根;前端展示后端具体错误。

Co-authored-by: Cursor <cursoragent@cursor.com>

* debug(android): 把 Keystore 暂时不可用的具体异常名带回日志

添加提供商已会重试信封,但 Keystore 仍返回 temporarily unavailable。JNI 原先丢掉 Kotlin 异常与 JNI 失败路径,无法区分 class load、status 3 还是 BackendBusy。

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(android): 无法用于 Cipher 的 Keystore 密钥按失效信封恢复

真机 open 稳定抛出 InvalidKeyException(非 UserNotAuthenticated)。继续当成 temporarily unavailable 会让已保存凭据永远读不出来。改为走密钥缺失路径,删除无法解密的信封后可以重新配置提供商。

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(android): 凭据 Keystore 写入改走主线程并换用 v3 别名

清掉失效信封后,增加提供商仍在 seal 上失败(ProviderException/KeyStoreException)。HyperOS 上 Keystore2 从 JNI 后台线程调用常失败;改为主线程执行,并换用未损坏的 v3 别名,失败时删除别名再生成一次。

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(android): KeyMint AES-GCM 失败时回退到应用私有软件密钥

HyperOS 上 seal 稳定返回 KeyStoreException 10,主线程与 v3 别名仍无法写信封。Keystore 不可用时改用 UID 私有软件 AES-GCM,避免增加提供商失败。

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(android): preserve credentials across key fallback

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Chris233 <h-chris233@outlook.com>
2026-09-13 01:58:26 +08:00
..

OpenLess Android 平台代码

Android 相关 Rust、Kotlin 与前端代码的统一入口。桌面端通过 #[cfg(not(mobile))] 分层,不受影响。

目录结构

android/
├── kotlin/              # Kotlin 模板(CI 复制到 gen/android/)
├── manifests/           # AndroidManifest snippet + res/xml
└── frontend/            # React 模块(Vite 别名 @android)

src-tauri/src/android/   # Rust 运行时模块(crate::android)

Rust(src-tauri/src/android/)

模块 职责
jni.rs JNI 工具(clipboard、overlay service、accessibility)
native_bridge.rs Kotlin ↔ Coordinator JNI 入口
overlay.rs 悬浮窗权限与 show/hide
accessibility.rs 无障碍服务状态与 paste
shizuku.rs Shizuku 状态诊断与受控无障碍恢复
insert.rs 跨 App 文本插入策略
updater.rs 应用内更新(manifest 拉取、minisign 校验、系统安装器)
updater_logic.rs 更新 URL / 版本比较纯函数(全平台可测)
types.rs Android 偏好与状态类型

主 crate 通过 mod android; 引入,常用 API 经 crate::android:: 扁平 re-export。

Kotlin(android/kotlin/)

tauri android init 后由 scripts/copy-android-scaffolding.mjs 复制到 src-tauri/gen/android/app/src/main/java/com/openless/app/。

Manifest 合并脚本:

前端(android/frontend/,别名 @android)

路径 职责
lib/androidTypes.ts Android 偏好与状态 TS 类型
lib/androidIpc.ts overlay / accessibility / Shizuku Tauri invoke
lib/androidMicrophonePermission.ts WebView 麦克风权限辅助
components/AndroidPermissionsPanel.tsx 设置页 Android 权限与 overlay 配置

src/lib/types.ts 与 src/lib/ipc.ts 保留 re-export,现有 import 路径仍可用。

构建与 CI

CI(overlay / 无障碍 ADB 测试 APK) — 合并 v1 麦克风权限 + overlay / 无障碍 manifest,用于真机 ADB 测试完整悬浮窗与无障碍能力(非仅应用内听写):

cd openless-all/app
npm ci && npm run build
CI=true npm run tauri -- android init --ci
node scripts/copy-android-scaffolding.mjs
node scripts/merge-android-v1-manifest.mjs
node scripts/merge-android-overlay-manifest.mjs
node scripts/merge-android-shizuku-manifest.mjs
node scripts/patch-android-shizuku-deps.mjs
CI=true npm run tauri:android:build

Workflow: .github/workflows/android-apk.yml

本地 overlay / 无障碍开发(v3) — 与 CI 相同的 manifest 合并链,使用本地 init / copy 脚本:

cd openless-all/app
npm run tauri:android:init
npm run copy:android-scaffolding
node scripts/merge-android-v1-manifest.mjs
node scripts/merge-android-overlay-manifest.mjs
node scripts/merge-android-shizuku-manifest.mjs
node scripts/patch-android-shizuku-deps.mjs
npm run tauri:android:build

相关文档