java - 区分 "out of range"或 "in range, but no listening server socket"? (蓝牙)

标签 java android sockets bluetooth android-bluetooth

问题

我如何区分无法与远程 Android 设备建立蓝牙连接是因为:

  • 场景 1:远程设备不在范围内,或者其蓝牙已禁用。
  • 场景 2:远程设备在范围内,但远程设备上没有服务器套接字来接受我的连接。

我尝试过的

  1. 我无法区分连接时抛出的异常,因为它在两种情况下抛出了相同的异常:

    java.io.IOException: read failed, socket might closed or timeout, read ret -1
    
  2. 我无法使用fetchUuidsWithSdp() 来检查远程设备是否支持我的 UUID,因为它在任何一种情况下的行为都相同... according to the documentation :

    This API is asynchronous and {@link #ACTION_UUID} intent is sent, with the UUIDs supported by the remote end. If there is an error in getting the SDP records or if the process takes a long time, {@link #ACTION_UUID} intent is sent with the UUIDs that is currently present in the cache...

    根据 this SO thread,它的行为似乎也有点不可预测。

  3. 最后,我不想使用sdpSearch来区分两者,因为它是在 API 23 中添加的,我希望能够支持低至 API 19。

最佳答案

您可以通过尝试连接到通常在 Android 设备上可用的标准 UUID 来确定设备是否在范围内。如果调用连接:

  • 失败,然后远程设备超出范围或其蓝牙被禁用。
  • 成功,则远程设备在范围内,您应该关闭连接,然后尝试连接到您应用的 UUID...如果失败,则没有监听套接字...如果成功,则一切正常好吧。

示例代码:

public BluetoothSocket connect(BluetoothDevice remoteDevice) throws IOException
{
    OPP_UUID = UUID.fromString("00001105-0000-1000-8000-00805f9b34fb");

    // check if remote device is in range...throw exception if out of range
    try
    {
        BluetoothSocket socket = remoteDevice
            .createRfcommSocketToServiceRecord(OPP_UUID);
        socket.connect();
        socket.close();
    }
    catch(IOException ex)
    {
        throw new IOException("out of range",ex);
    }

    // try to connect to service on remote device...throw exception if UUID
    // is not available
    try
    {
        BluetoothSocket socket = remoteDevice
            .createRfcommSocketToServiceRecord(MY_UUID);
        socket.connect();
        return socket;
    }
    catch(IOException ex)
    {
        throw new IOException("no listening server socket",ex);
    }
}

我用了BluetoothDevice.getUuids()获取我的一台 Android 设备上可用的 UUID。它给了我这个列表:

0000110a-0000-1000-8000-00805f9b34fb - Advanced Audio Distribution Profile (0x110a)
00001105-0000-1000-8000-00805f9b34fb - Object Push Profile (0x1105) // least invasive one...it seems
00001115-0000-1000-8000-00805f9b34fb - Personal Area Networking Profile (0x1115)
0000112f-0000-1000-8000-00805f9b34fb - Phonebook Access (0x112f) // this works!
00001112-0000-1000-8000-00805f9b34fb - Headset - Audio Gateway (0x1112)
0000111f-0000-1000-8000-00805f9b34fb - Handsfree Audio Gateway (0x111f)
00001132-0000-1000-8000-00805f9b34fb - Message Access Profile (0x1132) // this works too!
00000000-0000-1000-8000-00805f9b34fb - Base UUID (0x0000) // couldn't get this to work :(

Standard UUIDs from Bluetooth spec.

关于java - 区分 "out of range"或 "in range, but no listening server socket"? (蓝牙),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45251790/

相关文章:

java - android:根据FCM通知的数据采取行动

android - 将您的当前位置从一项 Activity 发送到另一项 Activity

将对等方的 IPv6 地址与本地主机进行比较

java - Spring RestTemplate readtimeout 属性无法正常工作-奇怪的问题

java - HashMap 中存储的重复值

java - 是否可以更改垃圾收集器线程的优先级?

java - 通过 XSLT 编码到 HTML 表中的 JAXB 包含空值

java - 由于以下错误,无法加载数据集[country_name] 参数没有值[par_country];

android - 屏幕 ImageView 中的替代图像

ruby-on-rails - Ruby Rails - Cloud9 - (SocketError)