把安卓手机变成蓝牙键盘 + 蓝牙触控板外设的极简 App:黑白主题、大面积极简、无缝键帽、苹果式设计语言、OLED 省电纯黑背景。
配对 iPad / iPhone / Mac / Windows 等设备后,手机即可作为它们的蓝牙键盘与触控板使用,支持同时与多台设备配对并按需切换控制目标。
English version: README.en.md
| 配对页 | 键盘页(竖屏融合布局) |
|---|---|
![]() |
![]() |
| 融合页 + 系统输入法 | 数字小键盘 |
|---|---|
![]() |
![]() |
- 蓝牙 HID 外设:基于系统
BluetoothHidDeviceprofile 注册键盘 + 触控板复合外设(含标准 HID 报告描述符),配对后被控设备将其识别为蓝牙键盘/触控板 - 广播名与手机区分:App 启动后把本机蓝牙名设为
PocketKeyboard_<品牌>(按系统品牌自动适配,如PocketKeyboard_Huawei/PocketKeyboard_Redmi),被控设备蓝牙菜单里一眼认出这是口袋键鼠而不是手机本体 - 配对页:显示固定配对码
0000;配对进行中实时显示当次真实 SSP 数字(与被控设备上显示的完全一致,见「配对码说明」);支持同时与多台设备配对;首次连接某设备时选择「苹果设备 / 其他设备」以适配布局与手势(选择持久化,不重复询问) - 添加被控设备:App 内扫描附近蓝牙设备并直接发起配对(
createBond),添加、连接、断开、删除被控设备全程不离开 App;行内「连接 / 断开」按钮管理连接(断开是粘性的,对端回连也不会自动恢复);左滑删除解除配对 - 连接可靠性(断联全面自愈):连接带 9 秒看门狗(回调丢失 / 对端不接受自动判失败并退避重试,「连接中」绝不永久挂住)+ 每 3 秒按系统真值对账;重复派发的断开回调自动去重(MIUI 实测会把同一次回调派发两遍);重连永不放弃(退避 15s 封顶后一直守护重连);发送失败即自愈——「系统说已连接却发不出报告」自动重注册 HID(锁屏 / 后台被系统收走注册的确定性恢复),死链自动断开重连并补发刚才的输入;回前台自动探活(两份零位移鼠标报告);对端陈旧会话自动摁掉重连;注册楔死(部分 ROM 会在进程被杀后卡死 HID 注册)自动自愈,root 设备可重启蓝牙栈恢复
- CONTROL 按钮:未连接任何设备时灰色不可用,连接成功后变黑可点击进入控制界面
- 五指挥势(全局,任意页面生效,带动效与文字提示):
- 五指短按(5 指同时按下、快速原地抬起)→ 返回键盘页面
- 刻意只保留这一个简单手势:收缩 / 张开 / 横滑那类复杂几何判定在真机上太难触发、互相误判,已整体移除
- 竖屏融合布局(键盘页 / 触控板页共用):上半触控板(右上角「123」小键盘开关、底部短竖线分割的左右点击区、当前设备名)+ 下半 26 键手机输入法风格 QWERTY(三行字母 10/9/7 + shift / 退格 / 空格 / 回车,shift 轻点粘滞一次、按住组合大写);键帽一律大写显示
- 87 键键盘页(横屏全屏):TKL 无小键盘区布局,苹果 / Windows 双套键位;黑底白字、键间无缝;按压有下陷视觉效果 + 触觉反馈
- 横屏全屏:横屏下键盘模式铺满 87 键 TKL、触控板模式铺满触控板(manifest 声明 configChanges,旋转不重建 Activity)
- dock 自动隐藏:底部模式切换栏在键盘 / 触控板页默认隐藏、把空间腾给键盘与触控板;单指从屏幕左缘或右缘向内滑过 24dp 即以苹果式 spring 唤出,切换页面模式后再次自动隐藏
- fn 组合功能(fn 粘滞,顶部有提示):
fn + 空格:循环调节屏幕背光亮度(iOS 风格亮度 HUD)fn + C:循环切换键帽字体颜色(白 / 橙 / 红)fn + S:循环切换键帽字号(小 / 中 / 大)fn + V:循环切换震感强度(关 / 弱 / 中 / 强),与触控板反馈强度同步
- F 行媒体键:默认行为为音量加减、静音、亮度加减、上一首/下一首、播放暂停等常用快捷键;与
fn同按才是本义 F1–F12 - 触控板页:适配两套手势集——
- Windows 模式:底部左右按键模拟区(左键/右键,可拖拽)、双指滚动、双指缩放(映射 Ctrl+滚轮)、三指上滑/下滑/左右滑、四指点击 = Win 键
- Apple 模式:单指点击 = 左键、双指点击 = 右键、双指滚动、双指捏合/旋转(映射 Ctrl+滚轮)、三指上滑/左右滑
- 数字小键盘:触控板右上角「123」极简开关,底部 sheet 滑入 4×6 数字键盘(含 0/00、退格、回车、运算符、清空),服务大量数字输入场景
- OLED 省电:整体纯黑背景,白色文字与图标
- JDK 17、Android SDK(Platform 35、Build-Tools 35.x)
- minSdk 28(Android 9)· targetSdk 35 · Kotlin 2.0.21 · AGP 8.7.2 · Gradle 8.11.1(wrapper 已内置)
# 克隆后直接用 wrapper 构建(无需预装 Gradle)
git clone https://github.com/haohaoo3o/PocketKeyboard.git
cd PocketKeyboard
./gradlew assembleDebug
# 产物:app/build/outputs/apk/debug/app-debug.apk
adb install -r app/build/outputs/apk/debug/app-debug.apk或直接用 Android Studio 打开工程目录。
./gradlew testDebugUnitTest # 386 个单元测试(含 Robolectric Compose UI 冒烟测试)
./gradlew lintDebug # 静态检查- 安装后打开 App,按提示授予蓝牙相关权限;本机蓝牙名会自动设为
PocketKeyboard_<品牌> - 添加被控设备(二选一):
- 在 App 里点「添加被控设备」→ 从扫描列表里选择对端,App 直接发起配对;
- 或在配对页点「可被发现」,然后在被控设备(iPad / Mac / Windows 等)的蓝牙菜单里选择本设备
- 按提示完成配对(见下方「配对码说明」);连接成功后设备行显示「已连接」
- 首次连接时 App 会询问「这是苹果设备还是其他设备」,选择后自动适配键盘布局与触控板手势
- 点 CONTROL 进入控制界面;五指短按随时返回键盘页面;设备行「断开 / 连接」按钮管理连接,左滑删除解除配对
配对页展示的数字就是当次配对真实使用的数字:
- 固定配对码
0000(空闲时显示):被控设备要求输入 PIN / 配对码时输入它; - 配对进行中:页面会实时显示系统生成的真实 SSP 数字——与被控设备屏幕上的一模一样,核对一致即可;
- 需要点击确认时(数字比较 / Just Works),在系统弹出的配对确认框里点「配对」。
平台限制说明:Android 将
setPairingConfirmation/setPin收在BLUETOOTH_PRIVILEGED(signature|privileged 权限)之后,普通应用无法代替用户完成最终确认——因此最后一步确认由系统配对框承接,但数字的唯一来源是 App(与对端显示严格一致)。
app/src/main/java/com/pocketkeyboard/app/
├── MainActivity.kt # 唯一 Activity:权限申请、五指挥势层、页面容器
├── hid/ # 蓝牙 HID 后端:HidDeviceTransport(系统 profile)+ NullHidTransport 兜底
├── gesture/ # 五指挥势引擎(五指短按)、手势仲裁器(滑动凑指窗口)、HUD、页面转场
├── keyboard/ # 87 键 / 26 键布局数据模型、无缝键帽、fn 组合功能、竖屏融合页、HID 报告引擎
├── trackpad/ # 触控板手势、Win/Apple 手势集、数字小键盘 sheet
└── ui/ # MainViewModel、配对页、主题
app/src/test/ # 386 个单元测试(布局/手势/HID 报文/dock 策略/Robolectric UI)
详见代码内注释与 跨模块契约。
| # | 限制 | 现状 |
|---|---|---|
| 1 | 配对最终确认需要系统框 | setPairingConfirmation / setPin 需要 BLUETOOTH_PRIVILEGED(Android 平台封锁普通应用);App 展示的即真实 SSP 数字,最终在系统配对框点「配对」即可 |
| 2 | 多设备切换依赖 registry 已知地址 | 从未连接过的对端不会主动 connectHost,需先在配对页点选一次 |
| 3 | HID 外设注册唯一性 | 系统同一时刻只允许一个 App 注册 HID 外设;若被其他输入法占用,注册被拒后回到前台会自动重试 |
| 4 | 注册楔死的 root 增强 | 部分 ROM(实测 MIUI)在进程被强杀后会卡死 HID 注册;普通设备提示开关蓝牙恢复,root 设备 App 会自动重启蓝牙栈自愈 |
| 5 | AppMode.NUMPAD 不切换页面 |
小键盘是触控板页内的底部 sheet,不触发页面转场 |
| 6 | 测试覆盖边界 | 单元测试覆盖纯逻辑层;真实蓝牙连接、手势手感、震感档位需真机验证;暂无 androidTest |
| 权限 | 用途 |
|---|---|
BLUETOOTH_CONNECT / BLUETOOTH_SCAN / BLUETOOTH_ADVERTISE |
Android 12+ 发现、连接键鼠接收端 |
BLUETOOTH / BLUETOOTH_ADMIN |
Android 11 及以下经典蓝牙 |
ACCESS_FINE_LOCATION / ACCESS_COARSE_LOCATION |
Android 11 及以下扫描所需 |
POST_NOTIFICATIONS |
Android 13+ 显示连接状态通知 |



