Skip to content

About

Android 熄屏相机控制:音量键单击切前后摄、双键拍照;HyperOS/Android 16 + Shizuku,无需 root。Screen-off camera control via volume keys.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

ScreenOffCam / 熄屏快门

Android 熄屏相机控制小工具:屏幕完全关闭后,用音量键控制前后摄像头并拍照。 自用侧载项目,目前仅在一台 Redmi Turbo 4(HyperOS 3 / Android 16)上完成真机验证。

English: Screen-off camera control for Android. A single volume key toggles the front/rear camera;

pressing both volume keys captures a photo. Tested on Redmi Turbo 4 / HyperOS 3 / Android 16, requires Shizuku (no root). Screen-off only; after reboot you must restart Shizuku and arm again.

功能

  • 熄屏单击音量上 / 音量下:切换前置 / 后置摄像头(toggle)
  • 熄屏同时按音量上 + 音量下:拍照,保存到 DCIM/ScreenOffCam/
  • 仅熄屏生效:屏幕亮起时不拦截音量键,正常调节音量
  • 按需打开相机:拍照完成后释放相机,减少待机耗电
  • 独立反馈开关:拍照震动 / 快门音都有自己的开关
  • 通道自愈:Shizuku 被杀或 rish 进程退出后自动重连,并更新常驻通知状态

支持的设备与系统

项目 状态
已验证机型 红米 Turbo 4(代号 rodin,型号 24129RT7CC)
已验证系统 HyperOS OS3.0.304.0.WOJCNXM / Android 16 (API 36)
compileSdk / targetSdk / minSdk 36 / 36 / 34
构建工具 Gradle 8.14.5、AGP 8.13.2、Kotlin 2.2.20、JDK 17、Build-Tools 36.0.0
必须依赖 Shizuku(adb/无线调试模式,shell uid 2000)
root / 解锁 BL / Xposed 不需要
其他 Android 14+ 机型 理论上可移植,但未验证;不同 OEM 的 evdev 节点、锁屏/后台策略可能不同

重要限制:目标机是目前唯一验证环境。换机型后,/dev/input 事件、HyperOS/MIUI 的后台冻结策略、 锁屏行为都可能需要重新适配。

工作原理

  1. 用户从可见界面点「武装」,启动 camera 类型前台服务 + Partial WakeLock;
  2. App 通过 Shizuku 的官方 rish 客户端,以 shell 身份运行一个常驻 getevent, 动态探测带 KEY_VOLUMEUP 的 evdev 节点并读取音量键事件;
  3. ComboDetector 做纯逻辑判定:
    • 单键 DOWN → UP ≤ 800ms,进入 350ms 待确认窗口,无第二颗键则 toggle 前后摄;
    • 另一颗键最近 DOWN ≤ 300ms 或刚 UP ≤ 350ms,则触发快门;
    • 亮屏、长按、重复 DOWN、Deep Doze 无 reader 等场景都有防护;
  4. 触发拍照后 CameraController 打开相机 → ImageReader 取 JPEG → 写入 MediaStore;
  5. FeedbackPlayer 按设置触发震动 / 快门音。

更详细的通道设计与实验记录见 docs/:

构建

前置:JDK 17、Android SDK(platform 36 + build-tools 36.0.0)。

cd android
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

首次配置(HyperOS / MIUI)

  1. 安装并启动 Shizuku:
    • 在 Shizuku 内点「View command」,从电脑 adb 或无线调试执行;
    • 保持 USB 调试 / 开发者选项开启,否则 Shizuku 可能随机停止。
  2. 打开「熄屏快门」:
    • 允许相机、通知权限;
    • 点「Shizuku 授权」并允许;
    • 点「澎湃OS 设置引导」,按提示设置:
      • 自启动:开启
      • 省电策略:无限制(本 app 和 Shizuku 都要)
      • 最近任务:锁定后台
      • 通知:允许
      • 相机「街拍模式」:建议关闭,避免与音量键冲突
  3. 点「武装」启动 camera 前台服务,确认通知常驻。
  4. 熄屏后:
    • 单击音量上 / 下 → 切换摄像头;
    • 同时按音量上 + 下 → 拍照。

重启手机后需要重新做两步:① 按 Shizuku 的「View command」重新启动 Shizuku; ② 回到本 app 点「武装」。camera 前台服务不能开机自启,这是 Android 14+ 的系统限制。

已知代价与注意事项

  • 音量键不会被吞掉:读取 /dev/input 是旁路监听,按音量键会真实改变媒体音量;
  • 通知不可隐藏:常驻通知是前台服务与 App Standby working set 的锚点;
  • 相机占用:武装期间 app 可能短时占用相机,微信/系统相机可能受影响;
  • 每次重启需重新武装 + 重新启动 Shizuku;
  • 无障碍通道不可用为正式通道:实验证明无障碍在浅熄屏/锁屏可收到音量键, 但 Deep Doze 下收不到,因此最终仍使用 Shizuku;
  • 未上架任何应用商店:这是自用侧载工具,商店合规不是设计约束;
  • 换机型需要通过 getevent -pl 确认音量键 evdev 节点,并实测锁屏/Doze 行为。

项目结构

screen-off-camera/
├── android/                 # Android 应用(Kotlin)
│   └── app/src/main/
│       ├── java/.../        # MainActivity、CameraArmedService、ComboDetector 等
│       ├── res/xml/         # 无障碍实验配置
│       └── assets/shizuku/  # 随包分发的 rish(Apache-2.0)
├── docs/                    # 架构、通道设计、真机实验记录、证据
├── scripts/
│   ├── standby-power-test.sh
│   ├── keytest.sh
│   ├── sdk-setup.sh
│   └── sdk-remove.sh
└── tests/                   # 无额外依赖的 JVM 纯逻辑测试

测试

纯逻辑测试覆盖 ComboDetector 与 getevent 行解析,不需要 JUnit/第三方依赖:

bash tests/run-tests.sh
# RESULT passed=19 failed=0

免责声明

本项目仅供个人学习与自用侧载,不保证兼容其他机型和系统版本。 使用前请确认你了解相机前台服务、Shizuku/ADB 调试、HyperOS 后台策略带来的隐私与权限影响。

第三方与许可

  • 本项目代码:Apache License 2.0,见 LICENSE 与 NOTICE;
  • 随包分发的 rish / rish_shizuku.dex 来自 Shizuku,Apache-2.0;
  • 依赖 dev.rikka.shizuku:api / provider,Apache-2.0;
  • 详见 THIRD_PARTY_NOTICES.md。

About

Android 熄屏相机控制:音量键单击切前后摄、双键拍照;HyperOS/Android 16 + Shizuku,无需 root。Screen-off camera control via volume keys.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages