如何在支持蓝牙的Arduino微控制器上将Android应用程序正确连接到RFCOMM插槽?

我正在和我大学的一些学生一起开发一个简单的蓝牙Android应用程序,该应用程序将用于串行通信(RFCOMM)到连接了蓝牙模块的Arduino微控制器。

据我所知,我正在使用RFCOMM/SPP 00001101-0000-1000-8000-00805F9B34FB的正确蓝牙地址和UUID。 我的应用程序启动一个尝试使用BluetoothDevice.createRfcommSocketToServiceRecord(UUID)连接到设备的线程。 但由于某种原因,我们没有看到成功的联系。 在上面的调用产生的BluetoothSocket上调用connect()时,操作总是失败。

在我的HTC Evo上测试,运行HTC的Gingerbread变种时, connect()调用通常会失败,并显示exception消息“服务发现无法启动”。 我做了一些阅读,发现有人说HTC在蓝牙堆栈中对RFCOMM的实现是错误的,所以我们决定在另一个学生的三星Galaxy S上试用它。 代码第一次运行,一切都很完美。 Arduino微控制器连接到一个小电动机,开始按预期工作。 我还没有排除问题是否可以在微控制器方面。

随后在Samsung设备上使用该应用程序失败,现在显示“Service Discovery Failed”消息。 对我来说,似乎设备端的蓝牙模块可能认为RFCOMM服务仍在使用中。 但是我们重新启动了微控制器并且仍然看到了相同的结果。

我刚刚列出了线程代码,因为它是真正相关的。 我已经读过使用reflection这些问题有一个非常常见的解决方法(hack)。 我对它的尝试也失败了但是在那里并且被注释掉了。 希望有人能引导我朝着正确的方向前进。 另请注意,我确实在清单中启用了必要的权限,在这两种情况下,设备都使用Android的用户界面成功与Arduino配对。

 private class ClientThread extends Thread { private String _btAddress; /** * A handle to the local device's Bluetooth adapter hardware. */ private BluetoothAdapter _btAdapter = BluetoothAdapter.getDefaultAdapter(); /** * A handle to the remote device Bluetooth context. */ private BluetoothDevice _btRemoteDevice; /** * A handle to the Bluetooth serial socket. */ private BluetoothSocket _btSocket; /** * Constructor. * @param btAddress The BluetoothHardware address. */ public ClientThread(String btAddress) { _btAddress = btAddress; } public void run() { // Retrieves the device identified by the _btAddress property. _btRemoteDevice = retrieveDevice(); if ( _btRemoteDevice == null ) sendUIMessage( CONNECTION_BT_DEVICE_NOT_BONDED ); else sendBeacon(); } /** * Retrieves the device associated with this client thread. * @return */ private BluetoothDevice retrieveDevice() { Set btDevices = _btAdapter.getBondedDevices(); for (BluetoothDevice btd : btDevices) { String addr = btd.getAddress(); String name = btd.getName(); if ( addr.equalsIgnoreCase(_btAddress) ) return btd; } return null; } /** * Sends the beacon to the Bluetooth device. */ private void sendBeacon() { // Holds the output stream of the BluetoothDevice. OutputStream os = null; try { _btSocket = _btRemoteDevice.createRfcommSocketToServiceRecord( UUID.fromString( "00001101-0000-1000-8000-00805F9B34FB" ) ); //Method m = _btRemoteDevice.getClass().getMethod("createInsecureRfcommSocket", new Class[] {int.class}); //_btSocket = (BluetoothSocket) m.invoke(_btRemoteDevice, 1); _btSocket.connect(); os = _btSocket.getOutputStream(); os.write('L'); } catch (IOException e) { String message = e.getMessage(); e.printStackTrace(); sendUIMessage(CONNECTION_FAILURE_IO); } catch (Exception e) { e.printStackTrace(); sendUIMessage(CONNECTION_FAILURE_UNKNOWN); } finally { try { if (_btSocket != null) _btSocket.close(); } catch (IOException e) { System.out.println("Failed closing Bluetooth output stream."); e.printStackTrace(); } } } } 

编辑:蓝牙模块是MDFLY RF-BT0417CB。 我知道在arduino上运行的代码并不多,只是使用Serial.available()和Serial.read()与BT模块进行通信。 但是,我有一条可能更有用的新信息。 当我的应用程序安装在三星设备上时,它只工作一次,并在后续试验中失败。 不久之后,我正在使用的另一名学生使用Android App Inventor(一种拖放式GUI工具,也可以创建逻辑工作工件)来创建一个连接相同BT模块/ arduino板的简单应用程序。 他说当安装我的应用程序时,另一个应用程序无法连接到BT模块,这让我相信系统仍然认为资源已分配给我的应用程序。 在他卸载我的应用程序后,另一个能够连接。 他没有其他应用程序的源代码,但我将自己尝试使用App Inventor来查看它生成的源代码是否生成了不同的内容。 据我所知,我遵守Android文档中定义的大多数标准实践,所以也许BT模块或者arduino代码不一定以编程方式控制BT模块这一事实。

另一个编辑:我不是蓝牙专家,但我们能够find一个解决方案。 有些人都知道,有许多公共BluetoothDevice API在编译时隐藏,但在运行时使用reflection合法公开。 其中之一是createRfCommSocket(int)。 此API不在官方文档中,因为它是隐藏的,但您可以在此处阅读。 我还没有尝试使用文档支持的API,但问题似乎是手机和串行板之间的并发问题。 手机发送了一条消息,这当然是一个阻塞呼叫,当它从那里返回时,关闭了连接。 然后,串行板上的屏蔽也将关闭连接,因此arduino应用程序无法获得数据。 我们在android端调试模式下见证成功通信时意识到这一点,但在发布模式下失败了。 在android端添加半秒延迟,在BluetoothSocket的传输和关闭之间修复了这个问题。 我不能说这个问题是否归因于arduino代码,因为我对这个架构不是很熟悉,但是我们学生们缺乏经验,所以我不会感到惊讶。

Solutions Collecting From Web of "如何在支持蓝牙的Arduino微控制器上将Android应用程序正确连接到RFCOMM插槽?"

Android和Arduino之间的通信与蓝牙(1)

我想这会对你有所帮助。 你能提供一些关于这方面的细节。我看过一个链接,你也可以看到这个。 让我知道这是有帮助还是没有? 如何在Android中创建不安全的RFCOMM套接字?

Amarino工具包专为促进Android设备和带蓝牙的Arduino之间的串行蓝牙通信而构建。