Android Bluetooth HID Device模拟蓝牙键盘鼠标
自Android 9开放BluetoothHidDevice功能后,Android平台可以很简单的通过BluetoothHidDevice模拟键盘鼠标等蓝牙hid device角色。
Step 1:获取BluetoothHidDevice实例
mBluetoothAdapter.getProfileProxy(ctx, mProfileServiceListener, BluetoothProfile.HID_DEVICE);
Step 2:注册/解除注册HID实例
public BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() {@Overridepublic void onServiceDisconnected(int profile) {if (profile == BluetoothProfile.HID_DEVICE) {//解除hid device注册mHidDevice.unregisterApp();}}@Overridepublic void onServiceConnected(int profile, BluetoothProfile proxy) {if (profile == BluetoothProfile.HID_DEVICE) {mHidDevice = (BluetoothHidDevice) proxy;//注册hid deviceBluetoothHidDeviceAppSdpSettings sdp = new BluetoothHidDeviceAppSdpSettings(HidConfig.NAME, HidConfig.DESCRIPTION, HidConfig.PROVIDER, BluetoothHidDevice.SUBCLASS1_COMBO, HidConfig.KEYBOARD_DESCRIPTOR);mHidDevice.registerApp(sdp, null, null, Executors.newCachedThreadPool(), mCallback);}}};public final BluetoothHidDevice.Callback mCallback = new BluetoothHidDevice.Callback() {@Overridepublic void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered) {IsRegisted = registered;}@Overridepublic void onConnectionStateChanged(BluetoothDevice device, int state) {if (state == BluetoothProfile.STATE_DISCONNECTED) {connected = false;Log.d(TAG, "hid state is disconnected");} else if (state == BluetoothProfile.STATE_CONNECTED) {connected = true;Log.d(TAG, "hid state is connected");} else if (state == BluetoothProfile.STATE_CONNECTING) {Log.d(TAG, "hid state is connecting");}}};
在获取到BluetoothHidDevice实例后通过registerApp注册hid device,此时hid host角色会被禁用,因此在不需要hid device功能时要及时解除hid device的注册。
registerApp函数中最重要的一个参数BluetoothHidDeviceAppSdpSettings,主要是给对端host提供hid device角色的名称,描述信息,供应商信息,以及Hid device的Reports Descriptor。
Hid report description描述符生成工具:USB官网HID报告描述符生成工具 - USB中文网
public class HidConfig {public final static String NAME = "My Keyboard";public final static String DESCRIPTION = "Lgd's Keyboard";public final static String PROVIDER = "Lgd";public static final byte[] KEYBOARD_DESCRIPTOR ={(byte) 0x05, (byte) 0x01, // USAGE_PAGE (Generic Desktop)(byte) 0x09, (byte) 0x06, // USAGE (Keyboard)(byte) 0xa1, (byte) 0x01, // COLLECTION (Application)(byte) 0x85, (byte) 0x02, //REPORT_ID (2)(byte) 0x05, (byte) 0x07, // USAGE_PAGE (Keyboard)(byte) 0x19, (byte) 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)(byte) 0x29, (byte) 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)(byte) 0x15, (byte) 0x00, // LOGICAL_MINIMUM (0)(byte) 0x25, (byte) 0x01, // LOGICAL_MAXIMUM (1)(byte) 0x75, (byte) 0x01, // REPORT_SIZE (1)(byte) 0x95, (byte) 0x08, // REPORT_COUNT (8)(byte) 0x81, (byte) 0x02, // INPUT (Data,Var,Abs)(byte) 0x95, (byte) 0x01, // REPORT_COUNT (1)(byte) 0x75, (byte) 0x08, // REPORT_SIZE (8)(byte) 0x81, (byte) 0x03, // INPUT (Cnst,Var,Abs)(byte) 0x95, (byte) 0x05, // REPORT_COUNT (5)(byte) 0x75, (byte) 0x01, // REPORT_SIZE (1)(byte) 0x05, (byte) 0x08, // USAGE_PAGE (LEDs)(byte) 0x19, (byte) 0x01, // USAGE_MINIMUM (Num Lock)(byte) 0x29, (byte) 0x05, // USAGE_MAXIMUM (Kana)(byte) 0x91, (byte) 0x02, // OUTPUT (Data,Var,Abs)(byte) 0x95, (byte) 0x01, // REPORT_COUNT (1)(byte) 0x75, (byte) 0x03, // REPORT_SIZE (3)(byte) 0x91, (byte) 0x03, // OUTPUT (Cnst,Var,Abs)(byte) 0x95, (byte) 0x06, // REPORT_COUNT (6)(byte) 0x75, (byte) 0x08, // REPORT_SIZE (8)(byte) 0x15, (byte) 0x00, // LOGICAL_MINIMUM (0)(byte) 0x25, (byte) 0x65, // LOGICAL_MAXIMUM (101)(byte) 0x05, (byte) 0x07, // USAGE_PAGE (Keyboard)(byte) 0x19, (byte) 0x00, // USAGE_MINIMUM (Reserved (no event indicated))(byte) 0x29, (byte) 0x65, // USAGE_MAXIMUM (Keyboard Application)(byte) 0x81, (byte) 0x00, // INPUT (Data,Ary,Abs)(byte) 0xc0 // END_COLLECTION};}
上面的描述符只是适配键盘,可以不定义report id,如果是多个hid功能复合的设备,例如复合键盘鼠标,就需要再添加鼠标的报告描述符,同时每个功能都需要有对应的report id。
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0x15, 0x0b, // LOGICAL_MINIMUM (11)
0x25, 0x1c, // LOGICAL_MAXIMUM (28)
0x09, 0x30, // USAGE (X)
0x81, 0x22, // INPUT (Data,Var,Abs,NPrf)
0xc0, // END_COLLECTION
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x02, // REPORT_ID (2)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x40, // LOGICAL_MAXIMUM (64)
0x09, 0x31, // USAGE (Y)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0
Setp 4:通过sendReport想host发送按键信息
第二个参数是report description中定义的report id,如果没有定义传入0。
第三个参数是按键数据,根据report description,总共有8字节,前2字节是功能键,后6字节是对应的键值信息
mHidDevice.sendReport(device, 2, new byte[]{0, 0, (byte) code, 0, 0, 0, 0, 0});
Hid相关资料请参考:HID 简介 - USB中文网
Android Bluetooth HID Device模拟蓝牙键盘鼠标相关推荐
- 蓝牙HID——Android手机注册HID时出现 Could not bind to Bluetooth (HID Device) Service with Intent * 的问题分析
异常描述 在蓝牙HID的开发过程中,使用红米K30手机 MIUI12.5(Android 11) 系统,打算将手机打造成蓝牙外设(键盘.触摸板.游戏手柄等).首先调用下面的方式与系统蓝牙HID服务绑定 ...
- android hid 编程,Android Bluetooth HID完成详解,androidhid
Android Bluetooth HID完成详解,androidhid Android Bluetooth HID落实详解 Android 关于蓝牙的局部运用的是BlueZ协定栈.然而直到眼前2.3 ...
- Android Bluetooth HID实现详解
Android Bluetooth HID实现详解 Android 关于蓝牙的部分使用的是BlueZ协议栈.但是直到目前2.3.3都没有扩展HID的profile,只是实现了最基本的Handset和d ...
- android hid自动重连,Android Bluetooth HID
8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? HID (Human Interface Device) 定义了蓝牙在人机接口设备中的协议.特征和使用规程.典型的应用包 ...
- 蓝牙键盘 android手机游戏,使用BluetoothHidDevice将安卓手机同时模拟成鼠标和键盘...
一直以来就有一种想法,就是自己写一个APP将安卓手机模拟成鼠标/键盘,应急的时候可以用来代替鼠标/键盘.之前也在国内外的网站上找了各种方案,但是这些方案不是很好,直到谷歌发布的API28后终于有了很好 ...
- android hid 鼠标,使用BluetoothHidDevice将安卓手机同时模拟成鼠标和键盘
一直以来就有一种想法,就是自己写一个APP将安卓手机模拟成鼠标/键盘,应急的时候可以用来代替鼠标/键盘.之前也在国内外的网站上找了各种方案,但是这些方案不是很好,直到谷歌发布的API28后终于有了很好 ...
- 仅通过蓝牙HID将安卓手机模拟成鼠标和键盘
相关文章:<蓝牙HID TouchScreen协议让你的安卓手机变成触摸屏> 本文源码下载地址:<仅通过蓝牙HID将安卓手机模拟成鼠标和键盘>源码 多文源码打包下载: < ...
- android变身蓝牙键鼠,使用BluetoothHidDevice将安卓手机同时模拟成鼠标和键盘
一直以来就有一种想法,就是自己写一个APP将安卓手机模拟成鼠标/键盘,应急的时候可以用来代替鼠标/键盘.之前也在国内外的网站上找了各种方案,但是这些方案不是很好,直到谷歌发布的API28后终于有了很好 ...
- android 连接ble键盘,如何在Android上以编程方式配对和连接HID蓝牙设备(蓝牙键盘)...
它表示Android蓝牙API提供以下蓝牙配置文件的实现,但您可以实现接口BluetoothProfile编写自己的类以支持特定的蓝牙配置文件 . 耳机 A2DP Health 设备 没有关于如何为H ...
最新文章
- html5自定义属性作用,html5自定义属性:如何获取自定义属性值(附代码)
- KVM Vhost-net 和 Virtio-net代码详解(十八)
- codevs1217 借教室 题解
- java如何实现乌龟爬行_乌龟是怎样爬行的
- linux vim 常用命令
- 复制百度文库及其他收费文档的方法
- 卡方分布、t分布、F分布
- Pr剪辑上分攻略 -- 动漫电影混剪
- PHP月考---给自己建个错题本
- linux系统连接不上wifi
- verilog语言的ps2键盘驱动设计
- perl bless
- SAP ABAP——SAP简介(一)【SAP发展历程】
- 远程教学,微信群里就能上课、培训
- Faiss 相似度搜索使用余弦相似性
- ery validator addMethod 方法的使用
- 那些年,我们一起写过的“单例模式”
- 使用STM32hal库usart的接收中断分析及出现部分问题的解决
- 作业盒子生端AndrOid,作业盒子小学下载安装学生版
- 【智慧消防】安科瑞智慧消防综合管理云平台解决方案