Skip to content

feat(android): Android 应用内自动更新与 release JNI 修复#664

Open
HKLHaoBin wants to merge 9 commits into
Open-Less:betafrom
HKLHaoBin:feat/android-auto-update
Open

feat(android): Android 应用内自动更新与 release JNI 修复#664
HKLHaoBin wants to merge 9 commits into
Open-Less:betafrom
HKLHaoBin:feat/android-auto-update

Conversation

@HKLHaoBin

@HKLHaoBin HKLHaoBin commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

User description

摘要

Fixes #。

为 Android APK 补齐应用内自动更新(Stable / Beta 渠道、后台检查、手动检查、自动下载安装),并修复 release 构建下 JNI 桥接被 R8 裁剪、更新签名校验不一致、overlay 前台服务误启动等真机问题。

修复 / 新增 / 改进

  • 自动更新updateChannelAutoUpdateGate 对齐;高级页 Beta 开关 + 自动更新开关;关于页 / 高级页分别手动查 Stable / Beta;Android 检查到新版本后可自动下载并打开系统安装器。
  • Rust 更新器:抽取 updater_logic.rs(manifest URL、版本比较、单测);Android updater.rs 拉取 GitHub Release manifest、minisign 校验、系统安装器安装。
  • 公钥与安装器UPDATER_PUBKEY_B64tauri.conf.json 同步;installApk 返回 false 时向前端报错;新增 check-android-updater-pubkey.mjs 与 CI 检查。
  • 真机崩溃修复Build.SUPPORTED_ABIS 改读 static field;无障碍状态改 JNI 直读 Settings.Secure;release APK 为 JNI 入口加 @Keep / @JvmStatic;overlay 默认 startService,仅录音 action 在 API 26+ 使用 startForegroundService,前台失败则取消录音并 stopSelf
  • UI:高级页 Beta 区块置于自动更新之上;Beta Toggle 独立 SettingRow,避免窄屏挤压。
  • CIworkflow_dispatch 在 keystore secrets 齐全时构建 signed release APK(可覆盖安装);否则回退 unsigned debug 并写 job summary。

兼容

  • 不包含:桌面 updater 行为变更(仍走 plugin-updater);Kotlin 安装流程重写;minisign 密钥轮换。
  • 对现有用户 / 本地环境 / 构建流程的影响:
    • Android 用户需授予「安装未知应用」权限才能完成 in-app 更新;无权限时会跳转设置且 UI 显示错误、可重试。
    • 手动 dispatch CI 在 secrets 齐全时产出 release 签名 APK,与 debug 签名不同,跨签名升级需先卸载(与既有 release 行为一致)。
    • 新增 CI 步骤 npm run check:android-updater-pubkey,公钥与 tauri.conf.json 不一致时构建失败。

测试计划

  • 命令:npm run build

  • 结果:通过

  • 证据路径:本地 / CI Android cargo check job

  • 命令:npm run check:android-updater-pubkey

  • 结果:通过

  • 证据路径:CI android-check job

  • 命令:cargo test updater_logic(Linux CI)

  • 结果:通过

  • 证据路径:CI Linux / macOS checks

  • 命令:CI workflow Android APK (debug) + CI(run 27503851924 / 27503852955)

  • 结果:success

  • 证据路径:https://github.com/HKLHaoBin/openless/actions

  • 命令:真机 adb install -r release APK,冷启动 25s logcat

  • 结果:无 NoSuchMethodErrorForegroundServiceDidNotStartInTimeExceptionFATAL EXCEPTION

  • 证据路径:dex 扫描确认 onCapsuleStateChanged 等 6 个 JNI 方法名存在

  • 命令:禁止「安装未知应用」后触发更新 → 授权后重试;Stable / Beta 手动检查回归

  • 结果:待 reviewer 真机复测

  • 证据路径:—


PR Type

Enhancement, Bug fix


Description

  • Android 应用内自动更新

  • 修复 release JNI 崩溃

  • Beta 渠道开关与 UI

  • 提取更新逻辑与测试


Diagram Walkthrough

flowchart LR
  A[AutoUpdateGate] -- background check --> B{Found update?}
  B -- Yes --> C[Download + verify APK]
  C --> D[Open system installer]
  B -- No --> E[Idle]
Loading

File Walkthrough

Relevant files
Bug fix
7 files
jni.rs
修复 overlay 前台服务与 accessibility JNI                                             
+136/-23
updater.rs
使用 updater_logic 并修复 ABI 读取                                                           
+19/-65 
OpenLessAccessibilityService.kt
为 JNI 入口添加 @Keep 注解                                                                           
+3/-0     
OpenLessOverlayBridge.kt
为 JNI 入口添加 @Keep 注解                                                                           
+4/-0     
OpenLessOverlayService.kt
修复录制动作前台服务失败处理                                                                                     
+37/-18 
OpenLessPermissionBridge.kt
添加 @Keep 注解                                                                                           
+3/-0     
OpenLessUpdateInstaller.kt
添加 @Keep 与 @JvmStatic 注解                                                                 
+4/-0     
Enhancement
9 files
mod.rs
添加 updater_logic 模块声明                                                                       
+1/-0     
updater_logic.rs
新增更新逻辑纯函数与单元测试                                                                                     
+123/-0 
AutoUpdate.tsx
添加 autoInstallAndroid 选项                                                                 
+80/-54 
AutoUpdateGate.tsx
后台检查传入 autoInstallAndroid                                                               
+6/-9     
en.ts
添加 Beta 与自动更新翻译                                                                                   
+12/-1   
AutoUpdateSection.tsx
新增 Android 自动更新开关                                                                               
+36/-0   
BetaChannelSection.tsx
重构 Beta 渠道开关与按钮布局                                                                               
+12/-15 
CheckUpdateButton.tsx
根据渠道显示不同按钮标签                                                                                         
+5/-9     
tabs.tsx
高级页添加 AutoUpdateSection                                                                   
+2/-0     
Documentation
1 files
types.rs
更新 UpdateChannel 注释                                                                           
+9/-11   
Configuration changes
2 files
android-apk.yml
workflow_dispatch 支持 release 签名                                                   
+64/-10 
ci.yml
添加 updater pubkey 检查步骤                                                                     
+3/-0     
Tests
1 files
check-android-updater-pubkey.mjs
新增 pubkey 一致性检查脚本                                                                               
+37/-0   
Additional files
8 files
android-mobile-apk-overlay-plan.md +26/-2   
README.md +2/-0     
package.json +2/-1     
ja.ts +12/-1   
ko.ts +12/-1   
zh-CN.ts +12/-1   
zh-TW.ts +12/-1   
types.ts +8/-6     

HKLHaoBin and others added 9 commits June 14, 2026 20:58
Align updateChannel prefs with background AutoUpdateGate, add symmetric manual stable/beta check buttons, Android auto-download after check, and settings toggle; extract updater_logic helpers with unit tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
call_static_method caused NoSuchMethodError on Thread-8 during AutoUpdateGate background check, killing the app ~4s after launch.

Co-authored-by: Cursor <cursoragent@cursor.com>
Manual workflow_dispatch builds signed release APKs when ANDROID_KEYSTORE_* is configured (overlay install, data preserved); otherwise falls back to unsigned debug with job summary notice. Tag releases still require all secrets; minisign/manifest/GitHub Release remain tag-only.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sync UPDATER_PUBKEY_B64 with tauri.conf.json; fail download when installApk returns false; put Beta channel above auto-update toggle; add pubkey CI check script.

Co-authored-by: Cursor <cursoragent@cursor.com>
Avoid squeezing the toggle beside long description text on narrow mobile layouts; align with AutoUpdateSection pattern.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Exclude Playwright/ui-check-screenshots outputs from version control and update the lockfile after tauri-nspanel resolution.

Co-authored-by: Cursor <cursoragent@cursor.com>
Avoid NoSuchMethodError when installed APK dex lacks OpenLessAccessibilityService.isEnabled static bridge; query enabled services and heartbeat prefs directly.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add @keep and @JvmStatic on Rust-invoked bridge methods; default overlay service starts to startService and only START_RECORDING uses startForegroundService on API 26+; abort recording when foreground promotion fails.

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

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant