【问题标题】:Service discovery failed exception using Bluetooth on Android在 Android 上使用蓝牙的服务发现失败异常
【发布时间】:2011-03-24 17:57:50
【问题描述】:

我目前正在开发一个通过蓝牙连接到仪器的 Android 应用程序,需要编写字符串命令并接收返回的字符串响应。目前,我通过 Wi-Fi 为 TCP/IP 进行连接/读/写工作,现在正在尝试实现蓝牙。但我遇到了一些障碍。我一直在网上搜索,试图找到类似的例子,但没有任何运气。我一直在使用 Android 开发者资源示例:蓝牙聊天作为我的主要参考点。

我当前的代码似乎可以工作。然后它会在连接点引发服务发现失败异常。我正在使用DeviceListActivity 类来发现和选择我想要连接的设备。它返回一个ActivityResult,然后我的蓝牙类等待它处理它,然后连接到它。下面的代码几乎与蓝牙聊天应用程序相同。

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(!m_BluetoothAdapter.isEnabled())
    {
        m_BluetoothAdapter.enable();
    }
    switch (requestCode) {
        case REQUEST_CONNECT_DEVICE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                // Get the device MAC address
                String address = data.getExtras()
                                     .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
                // Get the BLuetoothDevice object
                BluetoothDevice device = m_BluetoothAdapter.getRemoteDevice(address);
                // Attempt to connect to the device
                connect(device);
            }
            break;

        case REQUEST_ENABLE_BT:
            // When the request to enable Bluetooth returns
            if (resultCode == Activity.RESULT_OK) {
                // Bluetooth is now enabled, so set up a chat session
            }
            else {
                // User did not enable Bluetooth or an error occured

                Toast.makeText(this, "Bluetooth not enabled", Toast.LENGTH_SHORT).show();
                finish();
            }
    }
}

这是我的连接函数:

private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

private void connect(BluetoothDevice device) {
    m_Device = device;
    BluetoothSocket tmp = null;

    // Get a BluetoothSocket for a connection with the
    // given BluetoothDevice
    try {
        tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
    }
    catch (IOException e) {

    }
    m_Socket = tmp;

    m_BluetoothAdapter.cancelDiscovery();

    try {
        // This is a blocking call and will only return on a
        // successful connection or an exception
        m_Socket.connect();
    }
    catch (IOException e) {
        try {
            m_Socket.close();
        }
        catch (IOException e2) {
        }
        return;
    }
}

希望,无论我做错什么都很简单,但恐怕从来没有那么容易。这是我第一次做任何蓝牙开发,也许我做错了什么……但我不确定为什么会出现服务发现失败的异常。

您可以随时在手机上手动配对/查找设备...确实需要密码,但我认为这不是我遇到的问题。

【问题讨论】:

    标签: java android bluetooth


    【解决方案1】:

    三天后,由于一些非常有用的帖子,我弄明白了。

    我不得不更换:

    tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
    

    与:

    Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
             tmp = (BluetoothSocket) m.invoke(device, 1);
    

    瞧,它的工作原理!

    【讨论】:

    • 等等,我有几个蓝牙应用程序,但我还没有发现需要使用反射 (getclass.getmethod) 的情况。你能告诉我更多关于你尝试过的硬件吗?我很想知道在某些情况下是否真的需要反思。
    • 我发现最好的方法是尝试第一种方法,它连接速度更快。然后在服务发现失败时实现异常中的反射。还发现同样的 HTC 手机也存在 UDP 检测问题,而三星和摩托罗拉设备没有问题。
    • 阅读JellyBean 中BluetoothDevice 类的源代码,这似乎在通道1 上创建了一个RFCOMM 套接字。有意跳过了javadocs,并且该方法未在API 中公开。我不知道为什么这个 hack 会起作用,但它允许我与据称缺少 SPP 配置文件的设备进行通信,在该设备上没有 UUID 起作用。
    • "Permission denied" 尽管我同时请求了 BLUETOOTHBLUETOOTH_ADMIN 权限,但我还是抛出了异常。当我将此代码更改回 BluetoothChat 中的代码时,“权限被拒绝”异常消失了,但“服务发现失败”异常又回来了。我该怎么办?
    • 这也适用于我,但这是一个 hack。这假定服务器通道是固定的。不幸的是,我不能保证该频道将是任何特定频道。有谁知道如何解决这个问题但避免这个解决方案?
    【解决方案2】:

    这是a suggested edit from an anonymous user 试图回复已接受的答案。

    之前和之后的代码之间的一大区别是您传递的 UUID。我在这里找到了答案:http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createRfcommSocketToServiceRecord(java.util.UUID)

    我不得不更换:

    tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
    

    与:

    private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    tmp = device.createRfcommSocketToServiceRecord(SPP_UUID);
    

    瞧,它起作用了! 原始代码用于点对点 android 应用程序。连接到简单的串行蓝牙设备时,使用应用程序 UUID 毫无意义。这就是发现失败的原因。

    【讨论】:

    • 现在another anonymous user comments:建议的编辑使用与不起作用的代码完全相同的方法。工作代码使用不同的非公共方法,不需要 uuid。
    • 在尝试编写连接到蓝牙扫描仪的 Android 应用程序时遇到与上述相同的错误。这个解决方案对我有用。
    • @Monsingor 我不能评论任何一种方式,我只是接受了建议的编辑 - 但请告诉我们原因,或者更好地编辑并更正答案。
    • @Rup 原始代码从一开始就使用“00001101-0000-1000-8000-00805F9B34FB”作为 createRfcommSocketToServiceRecord() 函数的 UUID 参数。我不明白为什么您添加了一个建议以稍微不同的方式做同样事情的答案。显然,这无济于事。
    • @Monsingor 我相信关键区别在于使用的 UUID,即使代码相同。上面提到的 javadoc 指出:提示:如果您要连接到蓝牙串行板,请尝试使用众所周知的 SPP UUID 00001101-0000-1000-8000-00805F9B34FB。 当我尝试这个时,它也对我有用。
    【解决方案3】:

    从 API 15 开始,您可以使用以下方法:

    尝试用BluetoothDevice 类的getUuids() 方法的返回值替换您的UUID。 对我有用的是这样的:

    UUID uuid = bluetoothDevice.getUuids()[0].getUuid();
    BluetoothSocket socket = bluetoothDevice.createRfcommSocketToServiceRecord(uuid);
    

    这样做的原因是不同的设备支持不同的 UUID,通过使用 getUuids 获取设备的 UUID,您支持所有功能和设备。

    另一个有趣的新方法(从 API 14 开始支持)是:BluetoothHealth.getConnectionState。没试过,但看起来很有希望......

    【讨论】:

      【解决方案4】:

      所以如上所述,重点是您需要使用服务器正在等待的 UUID。

      如果您要连接到蓝牙设备,例如耳机或鼠标,您需要检查设备正在侦听的 UUID。你可以像这样看到 UUID。

      UUID[] uuids = bluetoothDevice.getUuids();
      

      如果您想知道这些 UUID 的含义,请参阅 this

      【讨论】:

        【解决方案5】:

        这是一个非常古老的问题,但我发现使用 createInsecureRfcommSocketToServiceRecord() 而不是 createRfcommSocketToServiceRecord() 以及前面提到的 getUuids() 对我有用

        UUID uuid = bluetoothDevice.getUuids()[0].getUuid();
        BluetoothSocket socket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(uuid);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-02-16
          • 1970-01-01
          • 2012-08-18
          • 1970-01-01
          • 1970-01-01
          • 2012-01-20
          • 1970-01-01
          相关资源
          最近更新 更多