自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。

  1. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  2. 0x09, 0x02, // USAGE (Mouse)
  3. 0xa1, 0x01, // COLLECTION (Application)
  4. 0x85, 0x01, // REPORT_ID (1)
  5. 0x75, 0x10, // REPORT_SIZE (16)
  6. 0x95, 0x01, // REPORT_COUNT (1)
  7. 0x15, 0x0b, // LOGICAL_MINIMUM (11)
  8. 0x25, 0x1c, // LOGICAL_MAXIMUM (28)
  9. 0x09, 0x30, // USAGE (X)
  10. 0x81, 0x22, // INPUT (Data,Var,Abs,NPrf)
  11. 0xc0, // END_COLLECTION
  12. 0x09, 0x06, // USAGE (Keyboard)
  13. 0xa1, 0x01, // COLLECTION (Application)
  14. 0x85, 0x02, // REPORT_ID (2)
  15. 0x75, 0x08, // REPORT_SIZE (8)
  16. 0x95, 0x01, // REPORT_COUNT (1)
  17. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  18. 0x25, 0x40, // LOGICAL_MAXIMUM (64)
  19. 0x09, 0x31, // USAGE (Y)
  20. 0x81, 0x02, // INPUT (Data,Var,Abs)
  21. 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模拟蓝牙键盘鼠标相关推荐

  1. 蓝牙HID——Android手机注册HID时出现 Could not bind to Bluetooth (HID Device) Service with Intent * 的问题分析

    异常描述 在蓝牙HID的开发过程中,使用红米K30手机 MIUI12.5(Android 11) 系统,打算将手机打造成蓝牙外设(键盘.触摸板.游戏手柄等).首先调用下面的方式与系统蓝牙HID服务绑定 ...

  2. android hid 编程,Android Bluetooth HID完成详解,androidhid

    Android Bluetooth HID完成详解,androidhid Android Bluetooth HID落实详解 Android 关于蓝牙的局部运用的是BlueZ协定栈.然而直到眼前2.3 ...

  3. Android Bluetooth HID实现详解

    Android Bluetooth HID实现详解 Android 关于蓝牙的部分使用的是BlueZ协议栈.但是直到目前2.3.3都没有扩展HID的profile,只是实现了最基本的Handset和d ...

  4. android hid自动重连,Android Bluetooth HID

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? HID (Human Interface Device) 定义了蓝牙在人机接口设备中的协议.特征和使用规程.典型的应用包 ...

  5. 蓝牙键盘 android手机游戏,使用BluetoothHidDevice将安卓手机同时模拟成鼠标和键盘...

    一直以来就有一种想法,就是自己写一个APP将安卓手机模拟成鼠标/键盘,应急的时候可以用来代替鼠标/键盘.之前也在国内外的网站上找了各种方案,但是这些方案不是很好,直到谷歌发布的API28后终于有了很好 ...

  6. android hid 鼠标,使用BluetoothHidDevice将安卓手机同时模拟成鼠标和键盘

    一直以来就有一种想法,就是自己写一个APP将安卓手机模拟成鼠标/键盘,应急的时候可以用来代替鼠标/键盘.之前也在国内外的网站上找了各种方案,但是这些方案不是很好,直到谷歌发布的API28后终于有了很好 ...

  7. 仅通过蓝牙HID将安卓手机模拟成鼠标和键盘

    相关文章:<蓝牙HID TouchScreen协议让你的安卓手机变成触摸屏> 本文源码下载地址:<仅通过蓝牙HID将安卓手机模拟成鼠标和键盘>源码 多文源码打包下载: < ...

  8. android变身蓝牙键鼠,使用BluetoothHidDevice将安卓手机同时模拟成鼠标和键盘

    一直以来就有一种想法,就是自己写一个APP将安卓手机模拟成鼠标/键盘,应急的时候可以用来代替鼠标/键盘.之前也在国内外的网站上找了各种方案,但是这些方案不是很好,直到谷歌发布的API28后终于有了很好 ...

  9. android 连接ble键盘,如何在Android上以编程方式配对和连接HID蓝牙设备(蓝牙键盘)...

    它表示Android蓝牙API提供以下蓝牙配置文件的实现,但您可以实现接口BluetoothProfile编写自己的类以支持特定的蓝牙配置文件 . 耳机 A2DP Health 设备 没有关于如何为H ...

最新文章

  1. html5自定义属性作用,html5自定义属性:如何获取自定义属性值(附代码)
  2. KVM Vhost-net 和 Virtio-net代码详解(十八)
  3. codevs1217 借教室 题解
  4. java如何实现乌龟爬行_乌龟是怎样爬行的
  5. linux vim 常用命令
  6. 复制百度文库及其他收费文档的方法
  7. 卡方分布、t分布、F分布
  8. Pr剪辑上分攻略 -- 动漫电影混剪
  9. PHP月考---给自己建个错题本
  10. linux系统连接不上wifi
  11. verilog语言的ps2键盘驱动设计
  12. perl bless
  13. SAP ABAP——SAP简介(一)【SAP发展历程】
  14. 远程教学,微信群里就能上课、培训
  15. Faiss 相似度搜索使用余弦相似性
  16. ery validator addMethod 方法的使用
  17. 那些年,我们一起写过的“单例模式”
  18. 使用STM32hal库usart的接收中断分析及出现部分问题的解决
  19. 作业盒子生端AndrOid,作业盒子小学下载安装学生版
  20. 【智慧消防】安科瑞智慧消防综合管理云平台解决方案

热门文章

  1. FLASH鼠绘入门教程,主要让大家熟悉一下简单图形的绘制!
  2. [原创] 鼠绘美女全攻略
  3. UX、UI、 IA和IxD傻傻分不清
  4. 实时传输协议——RTP协议
  5. 常用jQuery web工具集4
  6. Matplotlib饼图注释
  7. indexedDB 存储 js文件 xml文件 大文件缓存 并导出使用
  8. 阿里云视觉智能平台高校学生专访|臧家河:疫情在家,我的视觉AI实践之旅
  9. 华中科技大学计算机学院刘明,关于拟确定刘明圆等26位同志为发展对象的公示...
  10. 三极管电路必懂的几种分析方法