Mousekey 是一个面向 Android / HarmonyOS 平板远程桌面场景的小工具。它通过无障碍服务和悬浮窗小窗,尽量拦截鸿蒙 4.2 等设备上“鼠标中键被系统识别为返回/最近任务”的行为,让外接鼠标在远程桌面里更接近完整鼠标体验。
当前结论:普通 APK 能消费应用层可见的虚拟返回键,但无法彻底消费鸿蒙系统层“双击中键打开最近任务”的隐藏动作。本项目对该动作采用检测后快速关闭的补救策略。
在部分鸿蒙平板上,通过远程桌面使用外接鼠标时,鼠标滚轮中键会被系统合成为返回键;连续触发时还可能打开最近任务界面。这会打断远程桌面中的中键拖拽、视角旋转、CAD/建模软件导航等操作。
本项目最初尝试使用 Android 无障碍服务的 onKeyEvent() 直接过滤鼠标来源的 KEYCODE_BACK。后续日志显示,鸿蒙把鼠标 0x100 按钮链路包装成 Virtual KEYCODE_BACK,且双击触发最近任务的动作并不完全通过普通应用可消费的按键事件分发。
因此最终方案收敛为:
- 使用无障碍服务请求按键过滤能力。
- 使用可获得焦点的悬浮窗接收并消费可见的虚拟返回键。
- 检测到虚拟返回双击后,通过无障碍
GLOBAL_ACTION_BACK多次快速关闭可能弹出的最近任务界面。 - 以半透明可吸边气泡形式运行,减少对远程桌面画面的遮挡。
- 小窗返回拦截:消费可见的
KEYCODE_BACK、KEYCODE_HOME、KEYCODE_APP_SWITCH、KEYCODE_ESCAPE。 - 双击补救:检测到虚拟返回双击后,在短时间内多次执行全局返回,尽量关闭鸿蒙最近任务界面。
- 悬浮气泡:默认只显示应用图标和绿点,降低透明度避免遮挡。
- 展开胶囊:点击气泡后展开为“拦截中 + 关闭按钮”。
- 自动吸边:拖动小窗后松手,会自动吸附到左右屏幕边缘。
- 状态栏/导航栏适配:主界面避开挖孔、状态栏和底部手势条区域。
- 本地日志:保留运行日志,便于判断无障碍服务和小窗事件链路。
Mousekey 不是系统级输入映射工具,不能修改鸿蒙底层按键映射。
已经验证的限制包括:
- 普通 APK 可以消费进入悬浮窗/无障碍链路的
KEYCODE_BACK。 - 双击中键打开最近任务的系统动作没有稳定暴露为可消费的
KEYCODE_APP_SWITCH或KEYCODE_HOME。 - 对“最近任务”只能做弹出后的快速关闭,无法保证从根源阻止。
彻底解决通常需要以下路径之一:
- root 后修改系统 keylayout。
- 系统签名应用或厂商级权限。
- 鸿蒙系统层输入映射调整。
- 远程桌面应用自身提供鼠标中键重映射。
- 安装调试 APK。
- 打开 Mousekey。
- 授权悬浮窗权限。
- 打开无障碍设置,启用
Mousekey 返回键拦截服务。 - 回到 Mousekey,点击
启动小窗返回拦截。 - 进入远程桌面应用测试鼠标中键。
小窗交互:
- 默认显示半透明气泡。
- 点击气泡展开胶囊。
- 拖动小窗后松手自动吸边。
- 展开后点击
×关闭小窗拦截服务。
项目是最小原生 Android 工程,使用 Java,不依赖 Kotlin、Compose 或第三方 UI 库。
要求:
- JDK 17
- Android SDK
- Android Gradle Plugin 8.13.2
- Gradle 8.13 或项目 Gradle Wrapper
构建调试 APK:
./gradlew.bat assembleDebug构建产物:
app/build/outputs/apk/debug/app-debug.apk
app/src/main/
├── AndroidManifest.xml
├── java/com/fall/mousekey/
│ ├── MainActivity.java # 主界面、权限状态和启动入口
│ ├── OverlayGuardService.java # 悬浮气泡、小窗拦截和双击补救
│ ├── MouseBackBlockService.java # 无障碍服务和全局返回动作
│ ├── MousekeySettings.java # 简单运行设置
│ ├── MousekeyLogStore.java # 本地日志写入
│ └── ContextLogger.java # 日志回调接口
├── res/values/
│ ├── strings.xml
│ ├── styles.xml
│ └── colors.xml
└── res/xml/
└── mouse_back_block_service.xml # 无障碍服务能力声明
android.permission.SYSTEM_ALERT_WINDOW
android.permission.BIND_ACCESSIBILITY_SERVICESYSTEM_ALERT_WINDOW:显示可获得焦点的小窗,用于接收并消费可见按键事件。BIND_ACCESSIBILITY_SERVICE:声明无障碍服务,用于请求按键过滤和执行全局返回动作。
项目不读取窗口内容,不申请手势注入,不上传任何数据。
日志用于判断事件是否进入应用层,以及双击补救是否触发。
常见日志含义:
overlayKey keyCode=4(KEYCODE_BACK), consumed=true
表示可见虚拟返回键已被悬浮窗消费。
检测到虚拟返回双击,安排多段全局返回清理
表示识别到双击,开始执行最近任务补救。
执行无障碍全局返回 ... result=true
表示无障碍服务成功执行全局返回动作。
本项目采用 MIT License。详见 LICENSE。