13

有谁知道如何在 API 级别 2.3.3 的 2 个 Android 设备之间创建不安全的 RFCOMM 连接,同时使用任意声明的服务名称?(不是随机的或更改的服务名称,只是我自己定义的服务名称)

细节

我正在尝试在 2 个 Android 设备之间创建不安全的 Rfcomm 连接:Droid X2 和 Asus Transformer。我假设这两种设备都具有 Android 2.3.3 级别的功能,以实际获得使用不安全 Rfcomm 的能力。

当我尝试按照此处所述创建蓝牙连接时,使用现在公共的 createInsecureRfcommSocketToServiceRecord() 和 listenUsingInsecureRfcommWithServiceRecord(SERVICE, UUID),我收到报告:

java.io.IOException: Service discovery failed
at android.bluetooth.BluetoothSocket$SdpHelper.doSdp(BluetoothSocket.java:377)
at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:201)
at com.s4d.bluenomad.DeviceConnections$ClientThread.run(DeviceConnections.java:406)

我发现了一个相关的问题,其中创建正常连接的人收到此错误并使用反射来调用私有方法。但是,我不知道现在哪种私有方法对应于启动“不安全”连接。我尝试使用该相关问题中提出的解决方案,但 Android 要求我配对设备,这正是我需要避免的。我真的需要不安全的方法。

我什至尝试了此处概述的官方解决方案和黑客解决方案的组合

相关代码片段

创建 ServerThread 来监听连接

Log.i(TAG, "Constructing a ServerThread");
// Use a temporary object that is later assigned to serverSocket,
// because serverSocket is final
BluetoothServerSocket tmp = null;
try {
    // MY_UUID is the app's UUID string, also used by the client code
    tmp = btAdapter.listenUsingInsecureRfcommWithServiceRecord(SERVICE_NAME, SERVICE_UUID);
    Log.i(TAG,"Started listening on insecure RFCOMM channel for service requests for: " + SERVICE_NAME);
} catch (IOException e) { }
serverSocket = tmp;

ServerThread 监听连接

BluetoothSocket socket;
while(true)
{
    try
    {
        socket = serverSocket.accept();
    }
    catch( IOException e)
    {
        break;
    }

    if( socket != null )
    {
        Log.i(TAG, "Received new socket connection requesting service: " + SERVICE_NAME);
    }
    else
    {
        Log.i(TAG, "Socket connection attempted, but socket received is NULL.");
    }
}

创建 ClientThread 以启动连接

Log.i(TAG, "Constructing a ClientThread");
BluetoothSocket tmp = null;
try {
    // MY_UUID is the app's UUID string, also used by the server code
    tmp = device.createInsecureRfcommSocketToServiceRecord(SERVICE_UUID);
    Log.i(TAG,"Created client socket on insecure RFCOMM channel for service requests for: " + SERVICE_NAME);
} 
catch (IOException e) 
{ 
    Log.i(TAG, "Failed to createInsecureRfcommSocket() against MAC: " + device.getAddress());
}
clientSocket = tmp;

ClientThread 连接服务器

try
{
    clientSocket.connect();
}
catch( final IOException e)
{
    DeviceConnections.this.runOnUiThread(new Runnable()
    {

        @Override
        public void run() 
        {
            console.append("Client unable to connect to service.");
            Log.i(TAG, "Client socket unable to connect() to: " + clientSocket.getRemoteDevice().getAddress());
            e.printStackTrace();
        }

    });

}

我确实得到了日志输出“客户端套接字无法连接()到:[MY_MAC_ADDRESS]”,然后我得到了“服务发现失败”异常的堆栈跟踪。

4

5 回答 5

15

看来问题是在我打电话之前

clientSocket.connect()

我需要打电话

btAdapter.cancelDiscovery()

我在文档中看到了这一点,但它被列为“性能”问题——就我而言,这似乎实际上是一个“功能”问题。一旦我添加了取消发现调用,套接字连接立即工作。

于 2012-01-06T01:25:41.677 回答
5

需要检查的几件事

  • 在客户端和服务器上使用相同且唯一的 UUID。
  • 拥有蓝牙权限
  • 尝试使用众所周知的标准 SPP UUID 00001101-0000-1000-8000-00805F9B34FB

如果您可以将完整的日志粘贴到客户端和服务器端打印 API 错误代码(如果有)上,也会有所帮助。

于 2011-12-15T16:18:52.853 回答
3

“服务发现失败”仅仅意味着我们的设备无法在任何其他设备中找到具有相同 UUID 的服务。

在您尝试从第一个设备调用“createInsecureRfcommSocketToServiceRecord”之前,第二个设备尚未调用“listenUsingInsecureRfcommWithServiceRecord”方法。

在尝试从第一个设备连接之前,请确保此代码已在第二个设备中执行(如 onResume() 或按钮/optionsItem 单击)。

 if ((mChatService != null) &&  (mBluetoothAdapter.isEnabled())) {
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mChatService.start();
            }
        }
于 2011-12-28T07:43:51.710 回答
0

您应该将 8ce255c0-200a-11e0-ac64-0800200c9a66 更改为任何其他 UUID,并且您可以使用您的服务名称,因为 8ce255c0-200a-11e0-ac64-0800200c9a66 用于预定义的服务 BluetoothChatInsecure

于 2013-02-25T13:24:07.057 回答
0

Android 蓝牙实现很痛苦,因为它可能因设备而异。

我遇到了同样的问题。在我的具体情况下,当至少有一个设备BluetoothAdapter.getScanMode()设置为时发生错误BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE(即该设备既可发现又可从远程蓝牙设备连接)。

这很奇怪,因为设备应该是可连接的,但事实并非如此。

如果设备getScanMode() ==SCAN_MODE_CONNECTABLE,则不会发生错误。

到目前为止,我找到的解决方案是向用户显示警告,因此他们只连接到配对设备。如果设备未配对,用户应使用 Android 设置并完成这项工作。

仅为配对设备启用蓝牙通信消除了可发现的需要,然后避免“服务发现失败”。

同样,这是我在特定设备上的特定情况。这可能不是一般规则,但希望这对遇到相同错误的人有所帮助。

于 2013-11-07T12:25:56.910 回答