Skip to content

About

No description, website, or topics provided.

Resources

Stars

106 stars

Watchers

0 watching

Forks

Latest commit

 

History

26 Commits

Folders and files

Repository files navigation

考研英语单词小组件 (kaoyan-widget)

一个运行在 Android 上的 考研英语单词定时推送 桌面小组件 + App。 每天按计划推送一组单词(桌面小组件 + 通知),并根据距离初试的天数自动倒推每日新学词量。

📖 详细说明见 docs/项目说明.md —— 功能、算法、状态字段、构建方式、版本历史都在里面。

⚠️ 本项目由 AI 辅助构建 本仓库的源码、构建脚本与文档均经由 AI(大语言模型) 辅助,经人工测试与调试后开源。 仅供学习交流使用,请自行评估(尤其是定时/通知/权限相关行为)后再安装使用。


📦 下载

最新版本见 Releases:

# 安装 / 覆盖升级
pm install -r -d kaoyan-widget-v1.3.2-repair.apk

📸 截图

开屏提醒(每日首次打开) 权限引导(首次启动) 主界面 · 今日单词 仅英文(自测模式) 设置
开屏提醒 权限引导 主界面 仅英文 设置

截图为实机运行效果(OnePlus / ColorOS)。首次启动会申请通知权限,并弹窗引导开启自启动、关闭电池优化。

✨ 功能特性

  • 单词显示模式切换(v1.3.2):主页「回到顶部」圆钮正上方多了一个只写一个字的小圆钮,尺寸与「回到顶部」一致(44×44), 点一下在 双语 → 仅英文 → 仅中文 → 双语 之间循环(圆钮上的字同步变成「双」/「英」/「中」)。 切到「仅英文」只留单词 + 音标、藏掉释义;切到「仅中文」只留释义(音标一起藏)—— 合上中文就能自测默写。 切换只影响「今日单词」页面:通知推送、学习弹幕、桌面小组件照旧显示中英双语; 选择写进 state.json 的 view_mode,下次打开 App 仍是上次那档。
  • 每日开屏提醒(v1.3.1):每天第一次打开 App 时全屏弹一次「距离初试还剩 N 天」动画 (数字滚动 + 当天随机 2 个单词),2 秒自动淡出,点任意处或右上角 × 可立即关闭;每天只弹一次。
  • 首次启动设置向导:第一次打开时引导设置初试日期,未设置前不会推送到通知。
  • 初试日期可配置:默认 2027-12-20,可在 App 内随时修改。
  • 按剩余天数自动倒推每日词量:
    • dailyNew = ceil((词库总数 - 已学)/剩余天数),并夹在 1 ~ 300 之间;
    • 复习上限 reviewCap = max(40, dailyNew)。
  • 词库可替换:内置考研词表(5398 词),支持导入自定义 txt(# 注释、多分隔符),也支持一键恢复内置词库。
  • 定时推送:通过 AlarmManager 定时触发,桌面小组件刷新 + 通知栏推送。
  • 推送时段可自定义:在「设置」里可设置每天的推送起止时间(默认 08:00–22:00),单词会在该时段内分批随机推送。
  • 一次推送、两种呈现:闹钟到点推送一批单词时,同一批词既进通知、也按同样顺序以弹幕划过 (批次比日常频率略快,最多 2.5 秒一个);其余时间按设定频率随机弹。
  • 单服务单通知:推送调度与学习弹幕合并进同一个前台服务 BotService, 通知栏只保留一条常驻通知(原来「推送运行中」+「学习弹幕已开启」两条)。
  • 学习弹幕(悬浮窗,v1.2):使用手机时,从屏幕右侧向左划过一条「单词 + 释义」。 全天生效,不受推送时段限制(推送时段只管通知批次)。
    • 弹出频率按 个/秒 自定义,亮屏 / 熄屏独立(熄屏默认 0 = 不弹);
    • 样式可调:字体(默认 / 衬线 / 等宽)、字号、颜色、加粗;
    • 选词与你当天的学习对齐:随机弹幕从「今天计划内的词」里抽, 并补上「已到期、但被 reviewCap 挤出今天计划」的复习词; 其中复习词权重 3×、新词 1×,所以弹幕更像复习提醒。 只有当天计划尚未生成时才退回全词库兜底。
    • 多条弹幕同时存在(最多 12 条),每条独占一条纵向「泳道」,绝不复用; 没有空泳道时宁可不弹,也不会让两条叠在同一行(叠字会造成「单词频闪」);
    • 每条都完整飞到出屏才消失,不会「刚动一点就被下一条挤掉」;
    • 需要「悬浮窗」权限,首次开启时 App 会引导授权。
  • 深色模式(v1.2):全部界面(含设置页与对话框)自动跟随系统深浅色。
  • 开机自恢复:BootReceiver 在开机后重新注册闹钟;若弹幕处于开启状态,会一并恢复弹幕服务。
  • 弹幕心跳自愈:每批推送闹钟都会顺带对齐一次弹幕服务,被系统冻结/杀进程后无需重新打开 App 即可恢复。
  • 随剩余天数动态调整:每天根据已学进度重新推算当天计划。

🧱 项目结构

kaoyan-widget/
├─ AndroidManifest.xml
├─ build.sh                     # 构建脚本(密码/密钥由环境变量传入,仓库不含密钥)
├─ assets/words.txt             # 内置考研词表(5398 词)
├─ res/                         # 资源(布局 / 图标 / 字符串 / 小组件信息)
└─ src/com/kaoyan/widget/
   ├─ MainActivity.java         # App 主界面入口
   ├─ HtmlView.java             # 基于 WebView 的界面与设置向导
   ├─ SplashView.java           # 每日开屏提醒(倒计时 + 随机词,纯 Java 拼 HTML)
   ├─ Bridge.java               # JS 与原生交互桥(定时任务用命名静态内部类)
   ├─ Engine.java               # 学习计划推算核心(天数/每日词量/复习上限)
   ├─ Words.java                # 词库加载(内置 / 自定义)
   ├─ Store.java                # 本地状态存储(state.json)
   ├─ Scheduler.java            # 定时调度(AlarmManager)
   ├─ Notifier.java             # 通知
   ├─ WidgetProvider.java       # 桌面小组件
   ├─ BatchReceiver.java        # 定时批量推送接收器(兼作弹幕心跳)
   ├─ BootReceiver.java         # 开机自恢复
   ├─ BotService.java           # 唯一的常驻前台服务(推送调度 + 学习弹幕)
   ├─ DanmakuOverlay.java       # 弹幕悬浮层(普通类:泳道 / 动画 / 批次队列)
   └─ Perms.java                # 权限申请与首次启动引导

🔧 构建

环境要求:Termux(或 Linux)+ 可用的 aapt2 / javac / d8 / zipalign / apksigner, 以及 Android SDK 的 android.jar;Python3 用于把 classes.dex 注入 APK。

注意:需使用本机 OS 的 shell 内置 >> 读取 heredoc;d8 建议使用不针对匿名内部类报错的版本(本项目源码已避免使用匿名内部类)。

若 ANDROID_JAR 是只有 class、没有资源表的 android.jar(例如 App 自带的 $HOME/android.jar), aapt2 link 会报 Theme.Material.Light.NoActionBar not found。build.sh 会自动检测并改用 /system/framework/framework-res.apk 做资源链接(可用 AAPT_I 手动指定)。

# 1) 指定 android.jar 与你的签名密钥(密钥请自行生成,勿提交到仓库)
export ANDROID_JAR=$HOME/sdk/ex/android-34/android.jar
export KS=/path/to/your.jks
export KS_PASS=你的密钥库口令
export KEY_PASS=你的密钥口令

# 2) 构建
bash build.sh
# 产物:out/app.apk

安装(示意):

adb install -r -d out/app.apk
# 或手机本地:
pm install -r -d out/app.apk

🔒 隐私说明

本仓库不包含任何签名密钥、口令、Token 或用户数据:

  • 签名密钥(*.jks / *.keystore 等)与口令一律 不提交(已列入 .gitignore);
  • 运行数据(state.json、history.jsonl、自定义词库等)不提交;
  • 仓库中不含任何账号、Token、API Key、个人身份信息。

🗓 更新日志

  • v1.3.2-repair
    • 修复多音标词的中英文划分(issue #1):pretend[priˈtend, priː-] 这类给两个读音、音标里带空格的词, 原来按第一个空格切单词,正好切在音标中间 —— 单词带走半截音标、释义带走另一半,加粗范围和 「仅英文 / 仅中文」的隐藏全跟着串位。现在先按 [ 定界、把音标整段吃到 ] 再分释义。
    • 内置词库里 553 条带空格音标的词全部修正;顺手修掉没有音标的词「单词+释义」粘在一起的问题 (approximatea.近似的 → approximate a.近似的)。
    • 老记录自动还原:已经推出去的粘连行(history.jsonl 里的历史数据)在渲染时按当前词库反查还原, 不用等下一次推送、也不用清数据。
  • v1.3.2
    • 单词显示模式切换:主页「回到顶部」正上方新增一个只写一个字的圆钮 —— 尺寸与「回到顶部」一致(44×44), 点一下在 双语 → 仅英文 → 仅中文 → 双语 之间循环,圆钮文字同步变「双」/「英」/「中」。
    • 仅英文只留「单词[音标]」,仅中文只留释义(音标一起藏):合上中文就能自测默写。
    • 切换即时生效(不重载页面),只影响「今日单词」页面:通知推送、学习弹幕、桌面小组件照旧双语; 选择存进 state.json 的 view_mode,重开 App 仍是上次那档。
  • v1.3.1
    • 每日开屏提醒:每天第一次打开 App 时全屏弹一次开屏动画 —— 紫渐变背景上 「距离初试」大数字从 0 滚到实际天数,再按阶段给一句鼓励语;同时从当天要学的词里随机挑 2 个 展示「单词 / 音标 / 释义」。
    • 2 秒后自动淡出,点屏幕任意处或右上角 × 可立即关闭;一天只弹一次(state.json 的 splash_day), 第二天自动恢复,首次设置日期前不弹;深色模式单独配色,读屏可识别为对话框。
    • 每天第一次打开顺便记两个词,比纯倒计时多一点用处;
    • 每次想更新日志怎么写总是头疼,于是看了看国民级的软件:修复了一些已知问题。
  • v1.3
    • 侧边栏改为底部 Dock:原来左侧抽屉的 5 个菜单项拆成 Dock 的两项 —— 「今日单词」(回主页 / 回顶部)和「设置」。 原抽屉里的「立即推送一批」「刷新数据」移到设置页的「快捷操作」卡片; 原「设置 / 换词库」就是 Dock 的「设置」本身。
    • 回到顶部改为悬浮按钮:位于 Dock 上方,只在页面不在顶部时出现且可点击, 滚回顶部后自动隐藏。
    • 设置页标题改为「设置」:去掉首次向导时期的「欢迎使用 · 考研单词」和那段引导语。
    • 首页精简:去掉「推送时段 / 初试 / 每日词量」那一行, 初试倒计时改为标题行最右侧的斜体小字。
    • Dock 两项加了 role="button" / aria-current,读屏(TalkBack)能正确识别为按钮。
    • 新增 docs/项目说明.md:功能、学习计划算法、弹幕渲染、状态字段、构建与版本历史。
  • v1.2.1
    • 弹幕弹出频率改成「分档滑条」:原来是数字输入框(手机上要弹键盘、还能填出 0.37 这种无意义值), 现在是滑条 + 实时数值 + 刻度标签,固定 7 档:0(不弹)/ 0.05 / 0.1 / 0.2 / 0.5 / 1 / 2,亮屏 / 熄屏各一条。
    • 弹幕动画改为全局共享的 ~60fps 循环。原来用 ViewPropertyAnimator,它跟 Choreographer 走, 在本机 120Hz 屏上跑到约 91fps,同屏 1 条弹幕就吃掉约 30% 单核。 改为所有在飞弹幕共用一个固定帧间隔的循环后:帧率 91→42fps,动画期间进程 CPU 30.6%→17.9%。
    • 弹幕关闭时定时器完全停下:原来即使关掉弹幕也每 5 秒空转一次(读 state.json + 查亮屏), 一天约 1.7 万次无谓唤醒。现在实测0 帧 / 0.00% CPU。
    • 调度:推送一批不再重排当天全部闹钟(原来每次推送都会把 20+ 个精确闹钟 cancel + 重新 set 一遍)。已排好的闹钟本来就是「醒来推下一批」,不依赖当前进度。
    • 调度:当天计划推完后撤销剩余批次闹钟(保留每日 ROLL 闹钟),不再白唤醒设备。
  • v1.2
    • 新增 学习弹幕:使用手机时从屏幕右侧向左划过「单词 + 释义」, 全天生效、不受推送时段限制(推送时段只管通知批次)。
    • 弹幕频率按 个/秒 自定义,亮屏 / 熄屏分别独立(0 = 不弹); 样式(字体 / 字号 / 颜色 / 加粗)可调,用描边阴影保证任意背景可读。
    • 推送与弹幕整合:两者合并进唯一的常驻前台服务 BotService, 通知栏从两条常驻通知并为一条;推送一批单词时,同一批词既进通知、也按同样顺序以弹幕划过。
    • 弹幕选词对齐当天学习:随机词池 = 今天计划内的词 + 已到期但被 reviewCap 挤出计划的复习词 (复习词权重 3×、新词 1×),当天计划尚未生成时才退回全词库兜底,不再从 5398 词纯随机。
    • 新增 深色模式:全部界面(含设置页与对话框)自动跟随系统深浅色。
    • 多条弹幕同时存在(最多 12 条),每条独占一条纵向「泳道」且绝不复用, 没有空泳道时宁可不弹;各自飞完才消失。
    • 新增首次开启弹幕时的「悬浮窗」权限引导。
    • 修复:高频「单词频闪」——泳道 8→12 且不再复用已占泳道,并去掉「新弹幕一来就删掉半路那条」的淘汰。
    • 修复:弹幕被「推送时段」闸掉(设好频率却因时段已过而完全不弹,且界面无任何提示)。
    • 修复:弹幕服务被系统杀进程后静默停摆(要重新打开 App 才恢复)。
    • 修复:在设置页点「保存并开始」时,若初试日期没变不再清空当天计划。
  • v1.1.1
    • 新增「每日推送时段」自定义:设置页可调整起止时间(默认 08:00–22:00),按新时段重排当天剩余批次。
    • 修复:重复点击通知进入 App 后,返回键会停留在旧推送、无法回到桌面的问题。改为单实例(singleTask)+ 返回键直接退出;再次点击通知自动刷新到最新推送。
  • v1.1
    • 首次启动申请通知权限,并引导开启自启动 / 关闭电池优化。
    • README 增加实机截图。

📄 许可证

MIT License,详见 LICENSE。

🤖 声明

本项目(含代码与文档)由 AI 生成。

About

No description, website, or topics provided.

Resources

Stars

106 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages