如何在 Android 上以编程方式配对和连接 HID 蓝牙设备(蓝牙键盘)
How to programmatically pair and connect a HID bluetooth device(Bluetooth Keyboard) on Android
我可以配对蓝牙键盘但无法连接以使其成为输入设备。
我浏览了开发者网站上提供的文档 - http://developer.android.com/guide/topics/connectivity/bluetooth.html#Profiles
它说 Android 蓝牙 API 提供以下蓝牙配置文件的实现,但您可以实现接口 BluetoothProfile 来编写您自己的 类 以支持特定的蓝牙配置文件。
- 耳机
- A2DP
- 健康设备
没有关于如何为 HID 蓝牙设备(键盘)实现 BluetoothProfile 的文档
Android 本身为 HID 设备实现了蓝牙连接,但那些 API 是隐藏的。我也尝试过反射来使用它们。我没有收到任何错误,但键盘没有作为输入设备连接。这就是我所做的 -
private void connect(final BluetoothDevice bluetoothDevice) {
if(bluetoothDevice.getBluetoothClass().getDeviceClass() == 1344){
final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
Log.i("btclass", profile + "");
if (profile == getInputDeviceHiddenConstant()) {
Class instance = null;
try {
//instance = Class.forName("android.bluetooth.IBluetoothInputDevice");
instance = Class.forName("android.bluetooth.BluetoothInputDevice");
Method connect = instance.getDeclaredMethod("connect", BluetoothDevice.class);
Object value = connect.invoke(proxy, bluetoothDevice);
Log.e("btclass", value.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
@Override
public void onServiceDisconnected(int profile) {
}
};
mBluetoothAdapter.getProfileProxy(this, mProfileListener,getInputDeviceHiddenConstant());
}
}
public static int getInputDeviceHiddenConstant() {
Class<BluetoothProfile> clazz = BluetoothProfile.class;
for (Field f : clazz.getFields()) {
int mod = f.getModifiers();
if (Modifier.isStatic(mod) && Modifier.isPublic(mod) && Modifier.isFinal(mod)) {
try {
if (f.getName().equals("INPUT_DEVICE")) {
return f.getInt(null);
}
} catch (Exception e) {
Log.e("", e.toString(), e);
}
}
}
return -1;
}
出于安全原因,第三方应用程序无法连接到蓝牙键盘,因为该应用程序可能是键盘记录器。所以只能由用户手动完成。
这是我在 Android Marshmallow (6.0) 上使用的代码。启动 L2CAP 连接(HID 需要)
public static BluetoothSocket createL2CAPBluetoothSocket(String address, int psm){
return createBluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false,false, address, psm);
}
// method for creating a bluetooth client socket
private static BluetoothSocket createBluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, int port){
Log.e(TAG, "Creating socket with " + address + ":" + port);
try {
Constructor<BluetoothSocket> constructor = BluetoothSocket.class.getDeclaredConstructor(
int.class, int.class,boolean.class,boolean.class,String.class, int.class);
constructor.setAccessible(true);
BluetoothSocket clientSocket = (BluetoothSocket) constructor.newInstance(type,fd,auth,encrypt,address,port);
return clientSocket;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Boolean connect(View v) {
try {
// TODO: Check bluetooth enabled
mDevice = getController();
if (mDevice != null) {
Log.e(TAG, "Controller is paired");
// Create socket
mSocket = createL2CAPBluetoothSocket(mDevice.getAddress(), 0x1124);
if (mSocket != null) {
if (!mSocket.isConnected()) {
mSocket.connect();
}
Log.e(TAG, "Socket successfully created");
ConnectedThread mConnectedThread = new ConnectedThread(mSocket);
mConnectedThread.run();
}
} else {
showToast("Controller is not connected");
}
return true;
} catch (Exception e) {
e.printStackTrace();
if (e instanceof IOException){
// handle this exception type
} else {
// We didn't expect this one. What could it be? Let's log it, and let it bubble up the hierarchy.
}
return false;
}
}
private BluetoothDevice getController() {
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
if (device.getName().equals("Wireless Controller")) // Change to match DS4 - node name
{
Log.d(TAG, "Found device named: " + device.getName());
return device;
}
}
}
return null;
}
创建服务仍然有问题,您需要为设备设置正确的 L2CAP PSAM,但希望它能帮助..
我可以配对蓝牙键盘但无法连接以使其成为输入设备。 我浏览了开发者网站上提供的文档 - http://developer.android.com/guide/topics/connectivity/bluetooth.html#Profiles
它说 Android 蓝牙 API 提供以下蓝牙配置文件的实现,但您可以实现接口 BluetoothProfile 来编写您自己的 类 以支持特定的蓝牙配置文件。
- 耳机
- A2DP
- 健康设备
没有关于如何为 HID 蓝牙设备(键盘)实现 BluetoothProfile 的文档
Android 本身为 HID 设备实现了蓝牙连接,但那些 API 是隐藏的。我也尝试过反射来使用它们。我没有收到任何错误,但键盘没有作为输入设备连接。这就是我所做的 -
private void connect(final BluetoothDevice bluetoothDevice) {
if(bluetoothDevice.getBluetoothClass().getDeviceClass() == 1344){
final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
Log.i("btclass", profile + "");
if (profile == getInputDeviceHiddenConstant()) {
Class instance = null;
try {
//instance = Class.forName("android.bluetooth.IBluetoothInputDevice");
instance = Class.forName("android.bluetooth.BluetoothInputDevice");
Method connect = instance.getDeclaredMethod("connect", BluetoothDevice.class);
Object value = connect.invoke(proxy, bluetoothDevice);
Log.e("btclass", value.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
@Override
public void onServiceDisconnected(int profile) {
}
};
mBluetoothAdapter.getProfileProxy(this, mProfileListener,getInputDeviceHiddenConstant());
}
}
public static int getInputDeviceHiddenConstant() {
Class<BluetoothProfile> clazz = BluetoothProfile.class;
for (Field f : clazz.getFields()) {
int mod = f.getModifiers();
if (Modifier.isStatic(mod) && Modifier.isPublic(mod) && Modifier.isFinal(mod)) {
try {
if (f.getName().equals("INPUT_DEVICE")) {
return f.getInt(null);
}
} catch (Exception e) {
Log.e("", e.toString(), e);
}
}
}
return -1;
}
出于安全原因,第三方应用程序无法连接到蓝牙键盘,因为该应用程序可能是键盘记录器。所以只能由用户手动完成。
这是我在 Android Marshmallow (6.0) 上使用的代码。启动 L2CAP 连接(HID 需要)
public static BluetoothSocket createL2CAPBluetoothSocket(String address, int psm){
return createBluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false,false, address, psm);
}
// method for creating a bluetooth client socket
private static BluetoothSocket createBluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, int port){
Log.e(TAG, "Creating socket with " + address + ":" + port);
try {
Constructor<BluetoothSocket> constructor = BluetoothSocket.class.getDeclaredConstructor(
int.class, int.class,boolean.class,boolean.class,String.class, int.class);
constructor.setAccessible(true);
BluetoothSocket clientSocket = (BluetoothSocket) constructor.newInstance(type,fd,auth,encrypt,address,port);
return clientSocket;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Boolean connect(View v) {
try {
// TODO: Check bluetooth enabled
mDevice = getController();
if (mDevice != null) {
Log.e(TAG, "Controller is paired");
// Create socket
mSocket = createL2CAPBluetoothSocket(mDevice.getAddress(), 0x1124);
if (mSocket != null) {
if (!mSocket.isConnected()) {
mSocket.connect();
}
Log.e(TAG, "Socket successfully created");
ConnectedThread mConnectedThread = new ConnectedThread(mSocket);
mConnectedThread.run();
}
} else {
showToast("Controller is not connected");
}
return true;
} catch (Exception e) {
e.printStackTrace();
if (e instanceof IOException){
// handle this exception type
} else {
// We didn't expect this one. What could it be? Let's log it, and let it bubble up the hierarchy.
}
return false;
}
}
private BluetoothDevice getController() {
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
if (device.getName().equals("Wireless Controller")) // Change to match DS4 - node name
{
Log.d(TAG, "Found device named: " + device.getName());
return device;
}
}
}
return null;
}
创建服务仍然有问题,您需要为设备设置正确的 L2CAP PSAM,但希望它能帮助..