1,概述
1.1 HID协议
HID协议: Hunman Interface Device Profile人机交互设备协议
使用场景:支持人机交互设备之间的控制
市场产品:蓝牙键盘,蓝牙鼠标,蓝牙游戏手柄等。
1.2 代码路径
客户端: frameworks\base\core\java\android\bluetooth
服务端: packages\apps\Bluetooth\src\com\android\bluetooth\ hid
HidDevService.java hid协议的服务端
开发流程和健康设备类似,但是稍微麻烦
2,接口
接口如下
3,开发步骤
在官方文档中有一个建立通信的流程:
1、调用getProfileProxy(Context,BluetoothProfile.ServiceListener, int)来获取代理对象的连接。
2、创建BluetoothHidDeviceAppSdpSettings, BluetoothHidDeviceAppQosSettings对象,创建BluetoothHidDeviceCallback回调,调用registerApp方法注册
3、将手机与设备配对,并且进行连接。
4、实现BluetoothHidDeviceCallback的7个回调方法
5、调用sendReport方法分别实现蓝牙鼠标,蓝牙键盘等。
3.1 获取客户端代理对象
一般在oncreate方法中,直接调用getProfileProxy方法,这个没什么好说的。
BluetoothAdapter.getDefaultAdapter().getProfileProxy(getApplicationContext(),
mProfileServiceListener,BluetoothProfile. HID_DEVICE);
private BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.HEALTH){
mBluetoothHealth = null;
}
}
@SuppressLint("NewApi")
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEALTH) {
mHidDevice = (BluetoothHidDevice) proxy;
// 获取代理对象之后就进行注册
...
}
}
};
一般经过这个步骤,客户端的BluetoothHidDevice对象已经和服务端的HidDevService对象绑定了。
3.2 注册registerApp
BluetoothHidDeviceAppSdpSettings sdp = new BluetoothHidDeviceAppSdpSettings(
HidConsts.NAME, HidConsts.DESCRIPTION, HidConsts.PROVIDER,
BluetoothHidDevice.SUBCLASS1_COMBO, HidConsts.DESCRIPTOR);
BluetoothHidDeviceAppQosSettings inQos = new BluetoothHidDeviceAppQosSettings(
BluetoothHidDeviceAppQosSettings.SERVICE_GUARANTEED, 200, 2, 200,
10000 /* 10 ms */, 10000 /* 10 ms */);
BluetoothHidDeviceAppQosSettings outQos = new BluetoothHidDeviceAppQosSettings(
BluetoothHidDeviceAppQosSettings.SERVICE_GUARANTEED, 900, 9, 900,
10000 /* 10 ms */, 10000 /* 10 ms */);
boolean result = mHidDevice.registerApp(sdp, inQos, outQos, mCallback);
HidConsts类的定义如下:
public class HidConsts {
public final static String NAME = "HID Device Testapp";
public final static String DESCRIPTION = "";
public final static String PROVIDER = "Codeaurora";
/* @formatter:off */
public final static byte[] DESCRIPTOR = {
(byte) 0x05, (byte) 0x01, // USAGE_PAGE (Generic Desktop)
(byte) 0x09, (byte) 0x02, // USAGE (Mouse)
(byte) 0xa1, (byte) 0x01, // COLLECTION (Application)
(byte) 0x09, (byte) 0x01, // USAGE (Pointer)
(byte) 0xa1, (byte) 0x00, // COLLECTION (Physical)
(byte) 0x85, (byte) 0x02, // REPORT_ID (2)
(byte) 0x05, (byte) 0x09, // USAGE_PAGE (Button)
(byte) 0x19, (byte) 0x01, // USAGE_MINIMUM (Button 1)
(byte) 0x29, (byte) 0x03, // USAGE_MAXIMUM (Button 3)
(byte) 0x15, (byte) 0x00, // LOGICAL_MINIMUM (0)
(byte) 0x25, (byte) 0x01, // LOGICAL_MAXIMUM (1)
(byte) 0x95, (byte) 0x03, // REPORT_COUNT (3)
(byte) 0x75, (byte) 0x01, // REPORT_SIZE (1)
(byte) 0x81, (byte) 0x02, // INPUT (Data,Var,Abs)
(byte) 0x95, (byte) 0x01, // REPORT_COUNT (1)
(byte) 0x75, (byte) 0x05, // REPORT_SIZE (5)
(byte) 0x81, (byte) 0x03, // INPUT (Cnst,Var,Abs)
(byte) 0x05, (byte) 0x01, // USAGE_PAGE (Generic Desktop)
(byte) 0x09, (byte) 0x30, // USAGE (X)
(byte) 0x09, (byte) 0x31, // USAGE (Y)
(byte) 0x15, (byte) 0x81, // LOGICAL_MINIMUM (-127)
(byte) 0x25, (byte) 0x7f, // LOGICAL_MAXIMUM (127)
(byte) 0x75, (byte) 0x08, // REPORT_SIZE (8)
(byte) 0x95, (byte) 0x02, // REPORT_COUNT (2)
(byte) 0x81, (byte) 0x06, // INPUT (Data,Var,Rel)
(byte) 0x09, (byte) 0x38, // USAGE (Wheel)
(byte) 0x15, (byte) 0x81, // LOGICAL_MINIMUM (-127)
(byte) 0x25, (byte) 0x7f, // LOGICAL_MAXIMUM (127)
(byte) 0x75, (byte) 0x08, // REPORT_SIZE (8)
(byte) 0x95, (byte) 0x01, // REPORT_COUNT (1)
(byte) 0x81, (byte) 0x06, // INPUT (Data,Var,Rel)
(byte) 0xc0,