Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
143 commits
Select commit Hold shift + click to select a range
0bc3a97
feat(android): add OpenLess IME service scaffold
DepengWang Sep 11, 2026
d00a1c0
feat(android): refine ime panel controls and animations
DepengWang Sep 11, 2026
e108593
feat(android): add stroke input mode
DepengWang Sep 11, 2026
219769d
feat(android): align stroke keyboard layout
DepengWang Sep 11, 2026
fe9251b
fix(android): restore visible stroke key layout
DepengWang Sep 11, 2026
b19740a
fix(android): refine stroke keyboard density and actions
DepengWang Sep 11, 2026
f065f99
fix(android): show stroke action rail
DepengWang Sep 11, 2026
818ab92
feat(android): use complete offline stroke dictionary
DepengWang Sep 11, 2026
0bd0b47
perf(android): index stroke dictionary queries
DepengWang Sep 11, 2026
a7d68d3
fix(android): align stroke mode header
DepengWang Sep 11, 2026
25e5b4e
feat(android): add confirmed-text association flow
DepengWang Sep 11, 2026
75a2043
fix(android): prioritize common stroke candidates
DepengWang Sep 11, 2026
128444b
feat(android): add personalized stroke associations
DepengWang Sep 11, 2026
357647a
fix(android): continue association after longer context
DepengWang Sep 11, 2026
1ac8c27
fix(android): preserve alternate stroke codes
DepengWang Sep 11, 2026
a4056b3
fix(android): persist selected ime mode
DepengWang Sep 12, 2026
666530b
feat(android): rank stroke candidates by frequency
DepengWang Sep 12, 2026
f048153
perf(android): preload stroke index on ime startup
DepengWang Sep 12, 2026
43fee00
feat(android): add stroke numeric symbol panel
DepengWang Sep 12, 2026
0c0be5a
fix(android): restore stroke candidates after numeric panel
DepengWang Sep 12, 2026
12b3c1b
feat(android): honor chinese script preference in stroke ime
DepengWang Sep 12, 2026
0357185
fix(android): make stroke script key a toggle
DepengWang Sep 12, 2026
d9b505f
fix(android): simplify stroke script toggle label
DepengWang Sep 12, 2026
31939f0
feat(android): add stroke association preference gates
DepengWang Sep 12, 2026
914c40b
fix(android): keep stroke encoding and candidates single line
DepengWang Sep 12, 2026
770959b
fix(android): render stroke symbols in input buffer
DepengWang Sep 12, 2026
4b5de37
feat(android): polish IME keyboard interactions and visuals
DepengWang Sep 12, 2026
52a74ad
fix(android): stop backend-warmup crash loop and duplicate Tauri hosts
DepengWang Sep 12, 2026
3e70c7e
feat(android): polish stroke keyboard toggle, labels, and mic key
DepengWang Sep 12, 2026
15c3c7c
feat(android): word segmentation, richer number panel, swipe gestures…
DepengWang Sep 12, 2026
9fc3617
refactor(android): share backend warmup check across IME and runtime …
DepengWang Sep 13, 2026
68476b7
fix(settings): keep experimental state consistent (#959)
appergb Aug 18, 2026
b9849f0
feat(android): stroke keyboard polish, keyboard settings screen, corr…
DepengWang Sep 13, 2026
ecd7c67
feat(android): personal stroke ranking, light theme, voice link healt…
DepengWang Sep 13, 2026
5b00c35
feat(android): swipeable clipboard history rows, fix theme-read race
DepengWang Sep 14, 2026
6f7549e
feat(android): clipboard row favorite/delete/correction swipes, corre…
DepengWang Sep 14, 2026
96de4be
feat(android): harden runtime host Activity lifecycle (Phase 1)
DepengWang Sep 14, 2026
1d53887
feat(android): route backend recovery through runtime service (Phase 2)
DepengWang Sep 14, 2026
fe34fa1
feat(android): re-check battery/notification permissions, log recover…
DepengWang Sep 14, 2026
5939716
fix(android): prevent Tauri from exiting the shared process on window…
DepengWang Sep 14, 2026
ba88e35
feat(android): add per-process restart stats to keyboard settings
DepengWang Sep 15, 2026
4fa9498
feat(android): clipboard panel relabel, voice-correct selected text, …
DepengWang Sep 15, 2026
2cf88e9
feat(android): detailed restart-cause counters, stroke/clipboard UX f…
DepengWang Sep 15, 2026
1eb7df7
fix(android): stop using a stale cached JNI Context for Rust->Kotlin …
DepengWang Sep 15, 2026
9dbe764
fix(android): register the live Activity Context explicitly instead o…
DepengWang Sep 15, 2026
12356ad
fix(android): detect missing Activity registration, fix launcher-icon…
DepengWang Sep 15, 2026
371614b
feat(android): build-version tracking, today-only restart stats, keyb…
DepengWang Sep 15, 2026
e3a5b89
fix(android): close a race between silent backend warmup and a genuin…
DepengWang Sep 15, 2026
6f9c8cb
fix(android): resolve settings-screen black screen, keep undo across …
DepengWang Sep 15, 2026
6b15b84
feat(android): backend link indicator with heartbeat self-healing, he…
DepengWang Sep 16, 2026
66002ad
feat(android): iOS 17-style English keyboard with key preview and wor…
DepengWang Sep 16, 2026
631b115
android: redirect voice/clipboard correction flow to global Dictionary
DepengWang Sep 17, 2026
d963675
android: clipboard swipe-add writes dictionary directly, relabel keyb…
DepengWang Sep 17, 2026
c3a26c9
android: mic swipe gestures (raw-mode/cancel), warmup cold-start race…
DepengWang Sep 17, 2026
3b3c78f
feat(android): shared key-preview bubble overlay, stroke swipe-up ret…
DepengWang Sep 19, 2026
1b548fa
feat(android): mic swipe gestures deferred to release with live capsu…
DepengWang Sep 19, 2026
eda0f0d
fix(android): actkill_<reason> restart stats never reset on version bump
DepengWang Sep 19, 2026
8618891
fix(android): harden runtime lifecycle diagnostics
DepengWang Sep 21, 2026
a61d0fd
feat(android): register JNI Activity Context from OpenLessRuntimeServ…
DepengWang Sep 21, 2026
e133a60
fix(android): rebuild main webview window for a fresh warmup Activity…
DepengWang Sep 21, 2026
1608df4
fix(android): resolve activity_id collision behind settings-reopen bl…
DepengWang Sep 21, 2026
26897dc
fix(android): finish() the warmup Activity when settings is closed
DepengWang Sep 21, 2026
2797c90
fix(android): destroy() stale main window records, not close()
DepengWang Sep 21, 2026
e1d8f32
fix(android): self-restart the process when the main window label get…
DepengWang Sep 21, 2026
2acc116
fix(android): restart on the first stuck WebView, not the second
DepengWang Sep 21, 2026
8ea15a5
fix(android): actually wait for a stale main window's destroy() to land
DepengWang Sep 22, 2026
8d0af02
chore(android): remove confirmed dead code, simplify restart-watchdog…
DepengWang Sep 22, 2026
8d2bc1d
feat(android): long-press an English candidate to forget a custom word
DepengWang Sep 22, 2026
40d9cbd
feat(android): swipe-up digits on the English keyboard's top row
DepengWang Sep 22, 2026
e965a3f
Restructure English key digit hint into independent views
DepengWang Sep 23, 2026
9de377d
Retarget swipe-up digit preview across the top row while armed
DepengWang Sep 23, 2026
ffaaad6
Use sans-serif-medium for English letter keys
DepengWang Sep 23, 2026
d334803
Match bottom-row weight and add row2/row3 swipe-up symbols
DepengWang Sep 23, 2026
982bb05
Recolor swipe-up hints to match the preview bubble's red
DepengWang Sep 23, 2026
fd691c1
Revert swipe hint to gray, bump its size, nudge letter down
DepengWang Sep 23, 2026
37c6e7e
Unify English text weight in Voice and Clipboard panels
DepengWang Sep 23, 2026
77b3b56
Bump mode-toggle "笔画" label size slightly
DepengWang Sep 23, 2026
ebd360e
Reuse stroke candidate row Views instead of rebuilding every keystroke
DepengWang Sep 23, 2026
68f0f99
Preload phrase-association dictionary, add timing/result diagnostics
DepengWang Sep 23, 2026
6bcdb9a
Split stroke panel into StrokeInputController, fix 3 data-layer hotspots
DepengWang Sep 23, 2026
f205c79
Add "swipe up for Raw" hint under the voice panel's status text
DepengWang Sep 24, 2026
5507b40
Tune Raw-mode hint: 14sp -> 12sp, top gap 8dp -> 4dp
DepengWang Sep 24, 2026
3ab1b92
Raw-mode hint: 11sp/1dp, matching orange while active, auto-revert to…
DepengWang Sep 24, 2026
664dd0c
Move Raw hint under the mic icon, hide it during ordinary recording
DepengWang Sep 24, 2026
6f42944
Fix mic icon shift: buttonHolder LinearLayout -> FrameLayout
DepengWang Sep 24, 2026
b9fe1a1
Fix status text going blank: guard native capsule-state messages
DepengWang Sep 24, 2026
96319e9
Also revert "已撤销" to "点击开始说话" after 2s; extend delay to 2000ms
DepengWang Sep 24, 2026
0a42d22
Lighten dark-theme capsule/pill color one notch: rgb(54,54,54) -> rgb…
DepengWang Sep 24, 2026
8746497
Dial back dark-theme capsule lightening: 24/255 delta -> 12/255
DepengWang Sep 24, 2026
a8a6750
Add long-press-space Pinyin/English label toggle (UI only, no mode yet)
DepengWang Sep 24, 2026
8d0dbc5
Fix stuck "录音中" notification, quiet the persistent runtime one
DepengWang Sep 24, 2026
78ffea0
Add Android IME architecture/feature doc with screenshots
DepengWang Sep 24, 2026
00f9b2e
build(dict): add reproducible lightweight pinyin dictionary generator
DepengWang Sep 25, 2026
cf0d63d
feat(android-ime): add English and Pinyin mode toggle
DepengWang Sep 25, 2026
fb0bab4
fix(android-ime): make the space-key mode hint actually legible
DepengWang Sep 25, 2026
d6a2966
fix(android-ime): give the space key a real "Space" label
DepengWang Sep 25, 2026
8c1c10c
fix(android-ime): put the space-key mode hint beside "Space", not bel…
DepengWang Sep 25, 2026
cb944d3
feat(android-ime): add lightweight full-pinyin character lookup
DepengWang Sep 25, 2026
f4d9256
feat(android-ime): add high-frequency abbreviation phrases
DepengWang Sep 25, 2026
22cf975
perf(android-ime): add pinyin cache and user frequency ranking
DepengWang Sep 25, 2026
3528dbf
polish(android-ime): redesign the space-key mode hint as a dual-label
DepengWang Sep 25, 2026
d8cf4e8
perf(android-ime): widen pinyin character coverage and tune ranking
DepengWang Sep 25, 2026
ef7afce
polish(android-ime): redesign the clipboard panel's recent-clips strip
DepengWang Sep 25, 2026
1765919
feat(android-ime): scroll-aware dismiss + clear-history tab
DepengWang Sep 25, 2026
96ce12c
docs(android-ime): document the lite-pinyin mode briefly
DepengWang Sep 25, 2026
2e088a3
merge upstream/beta into feature/android-stroke-index-association
DepengWang Sep 25, 2026
1908d7c
feat(android-ime): pinyin post-commit association + self-learning com…
DepengWang Sep 25, 2026
2ec43f8
polish(android-ime): drop live debug status panel, show pinyin combo-…
DepengWang Sep 25, 2026
891b308
feat(android-ime): swipe-right on the mic for a quick-note dictation
DepengWang Sep 25, 2026
ae61271
feat(android-ime): swipe-left on the mic to submit a raw ramble via w…
DepengWang Sep 25, 2026
5a0bcc3
polish(android-ime): drop the ramble webhook's account field
DepengWang Sep 25, 2026
6c830fe
polish(android-ime): swap mic swipe-left/right and rename Ramble to I…
DepengWang Sep 25, 2026
e2e7116
polish(android-ime): rename Ingest to Cloud notes; match Quick notes …
DepengWang Sep 26, 2026
e18433c
fix(android-ime): reserve real space for the IME in native settings
DepengWang Sep 26, 2026
77ce996
polish(android-ime): move the mic gesture hint above Return, widen ca…
DepengWang Sep 26, 2026
3be28e9
polish(android-ime): tune candidate size back up, keep wider spacing
DepengWang Sep 26, 2026
4f1e414
fix(android-ime): restore pinyin post-commit association (regressed)
DepengWang Sep 26, 2026
892269c
polish(android-ime): brand accent color, breathing light everywhere, …
DepengWang Sep 26, 2026
740bcc8
revert(android-ime): restore the bitmap wordmark logo, drop the red "…
DepengWang Sep 26, 2026
6047dfc
polish(android-ime): red Return and Backspace on the English keyboard
DepengWang Sep 26, 2026
43a76f8
fix(android-ime): match the breathing dot's color to the armed waveform
DepengWang Sep 26, 2026
ecffb8b
chore(ci): sync android-apk.yml from perf/1103-android-build-time (#1…
HKLHaoBin Sep 26, 2026
ceeca02
chore(ci): bring #1106 Android APK workflow support scripts
HKLHaoBin Sep 26, 2026
7509a42
feat(android-ime): export/import personal settings across devices
DepengWang Sep 26, 2026
dfff5d6
fix(android): IME settings IA, log export, pinyin syllables, signed d…
HKLHaoBin Sep 26, 2026
12d08be
polish(android-ime): send LLM-polished text to Cloud notes, not raw
DepengWang Sep 26, 2026
ba011e3
fix(android): keep JNI context without OpenLess IME
HKLHaoBin Sep 26, 2026
cda7792
fix(android): open QA on Warmup host and add IME height
HKLHaoBin Sep 26, 2026
bbf1c3c
fix(android): resolve IME panel height from companion prefs
HKLHaoBin Sep 26, 2026
0dc8671
fix(android): add keyboard raise plus live 1:1 footprint preview
HKLHaoBin Sep 26, 2026
d015f26
fix(android): rebuild IME view when height/raise prefs change
HKLHaoBin Sep 26, 2026
195e70a
Merge test/pr-1067-android-apk into PR #1067
HKLHaoBin Sep 26, 2026
8f8cbf0
Merge beta into PR #1067 and resolve Android CI conflicts
HKLHaoBin Sep 26, 2026
76b259e
fix(linux-egui): restore remote UI test helpers for CI
HKLHaoBin Sep 26, 2026
e2d6988
fix(core): await e2ee store ops inline for TaskSpawner seam
HKLHaoBin Sep 26, 2026
db0ccb0
fix(core): keep module docs before seam test marker
HKLHaoBin Sep 26, 2026
cfd4e56
fix(core): ignore BrokenPipe in polish SSE fixture writer
HKLHaoBin Sep 26, 2026
b3070dc
merge: upstream/beta into PR #1067
HKLHaoBin Sep 27, 2026
bc24062
fix(ci): align src-tauri Cargo.toml with Linux-free beta contract
HKLHaoBin Sep 27, 2026
c5d742c
fix(android): resolve IME privacy, settings and APK review findings
H-Chris233 Sep 27, 2026
347592c
merge: sync beta into PR #1067
H-Chris233 Sep 27, 2026
b1737f8
fix(ci): correct Android transfer revisions and test context
H-Chris233 Sep 27, 2026
08acfb6
fix(e2ee): fall back when Android denies hard_link for device-id
HKLHaoBin Sep 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions .github/workflows/android-apk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ name: Android APK (debug)
# - push v*-tauri tag → signed release APK + minisign + updater manifest → GitHub Release
# - workflow_dispatch → signed release APK when ANDROID_KEYSTORE_* secrets exist
# (overlay install + user data preserved); otherwise unsigned debug APK (annotated, non-blocking)
# - workflow_dispatch + signed_debug=true — debug APK signed with the release
# keystore (when secrets exist); artifact remains openless-android-debug-*.
#
# #1103 build-time changes:
# - Do not wipe Cargo/Gradle/target before cache post-save (removed Free disk step).
Expand All @@ -26,8 +28,12 @@ on:
description: 'Dispatch-only fast release profile (no LTO, codegen-units=16). Ignored on tags.'
type: boolean
default: false
signed_debug:
description: 'Build debug mode but sign it with the release keystore (requires ANDROID_KEYSTORE_* secrets).'
type: boolean
default: false

# 同一 tag 重复推送只跑最新一次;workflow_dispatch 用 run_id 隔离避免互相取消。
# 同一 tag 重复推送只跑最新一次;手动构建按 run_id 隔离。
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && github.run_id || github.ref }}
cancel-in-progress: ${{ github.event_name == 'push' }}
Expand Down Expand Up @@ -62,6 +68,7 @@ jobs:
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
INPUT_SIGNED_DEBUG: ${{ github.event.inputs.signed_debug }}
run: |
set -euo pipefail
is_tag=false
Expand Down Expand Up @@ -89,6 +96,11 @@ jobs:
echo "label=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
echo "signing=tag-release" >> "$GITHUB_OUTPUT"
echo "signing_label=Tag release with release keystore" >> "$GITHUB_OUTPUT"
elif [[ "${INPUT_SIGNED_DEBUG:-false}" == "true" ]] && $has_keystore; then
echo "mode=debug" >> "$GITHUB_OUTPUT"
echo "label=signed-debug-run-${{ github.run_number }}" >> "$GITHUB_OUTPUT"
echo "signing=signed-debug" >> "$GITHUB_OUTPUT"
echo "signing_label=Manual dispatch debug APK signed with release keystore" >> "$GITHUB_OUTPUT"
elif $has_keystore; then
echo "mode=release" >> "$GITHUB_OUTPUT"
echo "label=dispatch-run-${{ github.run_number }}" >> "$GITHUB_OUTPUT"
Expand All @@ -100,6 +112,9 @@ jobs:
echo "signing=debug-fallback" >> "$GITHUB_OUTPUT"
echo "signing_label=Unsigned debug fallback (no keystore secrets)" >> "$GITHUB_OUTPUT"
echo "::notice title=Unsigned debug APK::ANDROID_KEYSTORE_* secrets not configured. Building debug APK without release signing. Overlay install and user data preservation require the release keystore; uninstall before installing if replacing a signed build."
if [[ "${INPUT_SIGNED_DEBUG:-false}" == "true" ]]; then
echo "::warning::signed_debug was requested but Android keystore secrets are incomplete; falling back to an unsigned debug APK."
fi
fi

- name: Resolve ABI matrix
Expand Down Expand Up @@ -286,13 +301,15 @@ jobs:
run: node scripts/merge-android-updater-manifest.mjs

- name: Configure Android release signing
if: needs.plan.outputs.mode == 'release'
if: needs.plan.outputs.mode == 'release' || needs.plan.outputs.signing == 'signed-debug'
working-directory: openless-all/app
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
# signed_debug: also wire debug buildType to the release keystore
OPENLESS_SIGN_DEBUG: ${{ needs.plan.outputs.signing == 'signed-debug' && 'true' || 'false' }}
run: node scripts/configure-android-release-signing.mjs

- name: Prime Gradle wrapper
Expand All @@ -313,6 +330,10 @@ jobs:
- name: Build Android debug APK
if: needs.plan.outputs.mode == 'debug'
working-directory: openless-all/app
env:
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: npm run tauri:android:build:debug

- name: Build Android release APK
Expand Down Expand Up @@ -378,6 +399,10 @@ jobs:
cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
> **Signed release APK** (manual dispatch). Same keystore as tag releases — supports overlay install and preserves user data when upgrading from an existing signed install.
EOF
elif [ "${{ needs.plan.outputs.signing }}" = "signed-debug" ]; then
cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
> **Signed debug APK** (manual dispatch). Debug mode is retained for diagnostics; the release keystore is used so `adb install -r` can upgrade the matching signed app without changing the debug artifact name.
EOF
fi

publish-android-release:
Expand Down Expand Up @@ -528,3 +553,4 @@ jobs:
append_body: true
body_path: ${{ runner.temp }}/android-release-body.md
files: ${{ steps.release_assets.outputs.files }}

4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ docs/plans/
/AGENTS.md
/issue-*-plan.md

# 本地会话记录(Claude Code 对话存档),仅供本人下次取用,不入库
/SESSION_NOTES.md
/SESSION_TRANSCRIPT.jsonl

# .github 内部协作 + 审计报告(ISSUE_TEMPLATE / workflows / pr template 仍保留发布)
.github/COOPER_*.md
.github/BUILD_TEST_REPORT.md
Expand Down
2 changes: 2 additions & 0 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ OpenLess 只做一件事:**把语音变成可用的书面文字(尤其是 AI 提

## 当前状态

本 Fork 的 Android 输入法架构、四个面板的使用说明、截图和从 fork 基线开始的功能时间线,见 [Android 输入法:架构、功能与 fork 演进](docs/android-ime.md)。

下面每一项,都是一层已经沉降为默认、你授权一次之后就不必再操心的能力——这就是开屏之后你所站立的基础设施:

- 共享 Rust 后端位于 `openless-core`。macOS 与 Windows 使用薄 Tauri 2 宿主和 React/TypeScript 前端;Android 暂时保留 Tauri mobile 宿主;Linux 使用独立原生宿主,不编译 Tauri 或 WebKitGTK。
Expand Down
59 changes: 59 additions & 0 deletions docs/android-ime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# OpenLess Android IME:架构、功能与 fork 演进

这份页面记录 Android 输入法分支从 `beta` fork 基线到当前实现的功能演进,并把界面截图与实际源码入口对应起来。它描述的是当前代码状态,不把构建成功等同于完整真机验收。

## 当前架构

用户操作进入 `OpenLessImeService`,它提供语音、笔画、剪贴板和英文四个输入面板,并通过 Android `InputConnection` 将结果提交到当前应用。Rust/Tauri 负责 ASR、AI 处理和共享后端;`OpenLessRuntimeService` 作为 `START_STICKY` 前台运行时监督器持有 JNI Activity Context;`OpenLessBackendWarmupActivity` 承载 Tauri/WebView 设置页与启动入口。

主要源码入口:

- `openless-all/app/android/kotlin/OpenLessImeService.kt`:四面板切换、语音生命周期、剪贴板/英文面板与跨面板 UI 基础设施。
- `openless-all/app/android/kotlin/StrokeInputController.kt`:笔画编码、候选/联想查询与提交、数字符号子面板;这是 2026-09-24 完成的第一处面板拆分。
- `openless-all/app/android/kotlin/OpenLessRuntimeService.kt`:运行时守护和 JNI Context 挂载。
- `openless-all/app/android/kotlin/OpenLessBackendWarmupActivity.kt`:Tauri host、设置页和 WebView 冷启动恢复。
- `openless-all/app/src-tauri/src/android/native_bridge.rs`:Rust ↔ Kotlin JNI 桥接。

## 已实现的 Android 输入能力

- 语音输入:录音、取消、原文/整理模式、波形/状态反馈,并通过 `commitText()` 写入当前光标位置。
- 笔画输入:离线笔画字典、单字候选、确认后的词语联想、分词、简繁偏好、数字/符号面板、上滑数字和个人词频。
- 剪贴板:历史记录、收藏/删除/分类、选择/复制/粘贴、纠正词写入全局词典。
- 英文键盘:字母/数字/符号三层布局、英文候选词、个人词频、自定义词长按删除、按键预览和上滑输入数字/符号。
- 跨应用插入:按可用性使用无障碍、Shizuku 或剪贴板回退;权限和输入法启用状态在 Android 侧单独管理。

## 2026-09-11 至 2026-09-24 的演进

`615d6ac4` 是 fork 后开发使用的 `beta` 基线,`0bc3a979` 是第一笔 Android IME 实现。之后的提交按功能阶段演进:

1. IME 服务骨架与四面板交互。
2. 笔画字典、索引、候选排序、联想、多编码、分词、简繁和个人词频。
3. 剪贴板历史、纠正词桥接、英文键盘、候选词和手势预览。
4. Runtime Service、Activity 生命周期、JNI Context、WebView 黑屏/冷启动恢复和重启诊断。
5. 2026-09-23 至 24:英文上滑数字/符号和长按删词;候选 View 复用;联想词典预热、缓存和 Trie 建索引优化;新增 `StrokeInputController`。

完整提交时间线可用以下命令复核:

```text
git log --reverse --format='%h %ad %s' --date=short 615d6ac4..HEAD
```

## 截图与使用说明

![OpenLess Android 架构与使用指南](images/android-ime/android-architecture-guide.png)

| 面板 | 截图 |
| --- | --- |
| 语音:待机、录音、思考 | ![语音待机](images/android-ime/voice-idle-green.jpg) ![录音](images/android-ime/voice-recording-red.jpg) ![思考](images/android-ime/voice-thinking.jpg) |
| 笔画:中文与数字/符号 | ![中文笔画](images/android-ime/stroke-chinese.jpg) ![数字面板](images/android-ime/stroke-numeric.jpg) |
| 剪贴板与英文 | ![剪贴板](images/android-ime/clipboard.jpg) ![英文键盘](images/android-ime/english.jpg) |

## 小米/Redmi 真机边界

现有开发记录确认 APK 已安装到包含小米设备在内的测试设备;但候选栏复用、控制器拆分和英文/笔画手势仍需要完整真机回归。正式发布前应继续覆盖:正常输入、分词联想、退格、数字/符号切换、简繁切换、跨键滑动、后台恢复、Activity 被系统回收后的冷启动,以及不同 OEM 的插入权限路径。

## 相关文档

- [Android 源码架构与开发记录](../openless-all/app/android/README.md)
- [根 README 的 Android 状态说明](../README.md#android-input-method)
- [Android 架构总览](architecture.md)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/android-ime/clipboard.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/android-ime/english.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/android-ime/stroke-chinese.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/android-ime/stroke-numeric.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/android-ime/voice-idle-green.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/android-ime/voice-idle-orange.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/android-ime/voice-recording-red.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/android-ime/voice-thinking.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions openless-all/app/android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ Manifest 合并脚本:
- [`scripts/merge-android-shizuku-manifest.mjs`](../scripts/merge-android-shizuku-manifest.mjs) — Shizuku Provider / 授权 Activity
- [`scripts/patch-android-shizuku-deps.mjs`](../scripts/patch-android-shizuku-deps.mjs) — Shizuku Gradle 依赖

### 轻量拼音输入(Pinyin,可选模式)

英文键盘长按空格可在英文 / 拼音之间切换。拼音模式为离线精确匹配查找(单字全拼 + 高频简拼词语),不含 NDK / JNI / librime / 语言模型,不新增联网权限。核心类:`LitePinyinController`(编码缓冲 + 查询)、`LitePinyinRepository`(词库索引 + 排序)、`LitePinyinUserFrequency`(本地选择频率)。词库资源 `android/assets/pinyin_chars.tsv`(约 8105 字)与 `pinyin_phrases.tsv`(约 2000 词),由 [`scripts/generate-pinyin-characters.mjs`](../scripts/generate-pinyin-characters.mjs) / [`scripts/generate-pinyin-phrases.mjs`](../scripts/generate-pinyin-phrases.mjs) 从三方开源数据生成,来源、版本与许可证见同目录下的 `pinyin_chars.LICENSE.txt` / `pinyin_phrases.LICENSE.txt`。

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

| 路径 | 职责 |
Expand Down
17 changes: 17 additions & 0 deletions openless-all/app/android/assets/english-frequency.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
english-frequency.tsv — attribution and license
================================================

Source: hermitdave/FrequencyWords
https://github.com/hermitdave/FrequencyWords
content/2018/en/en_50k.txt (English, OpenSubtitles-2018 corpus)

License: MIT License, Copyright (c) 2016 Hermit Dave. Full text:
https://github.com/hermitdave/FrequencyWords/blob/master/LICENSE

Generation: this repo's scripts/generate-english-dictionary.mjs filters the
source list to plain lowercase English words (rejecting subtitle-tokenizer
contraction fragments such as "'s"/"n't", numbers, and non-letter tokens),
keeps the top 20,000 by frequency, and writes them as tab-separated
"word<TAB>count" rows sorted by descending frequency. No runtime code in
OpenLess downloads, modifies, or redistributes the original source files —
only this generated, filtered derivative ships in the app.
Loading
Loading