如何将 Android 应用程序正确连接到支持蓝牙的 Arduino 微控制器上的 RFCOMM 插座?
Posted
技术标签:
【中文标题】如何将 Android 应用程序正确连接到支持蓝牙的 Arduino 微控制器上的 RFCOMM 插座?【英文标题】:How can I properly connect an Android application to an RFCOMM socket on a Bluetooth enabled Arduino microcontroller? 【发布时间】:2011-11-02 19:52:38 【问题描述】:我正在与我大学的一些学生一起开发一个简单的蓝牙 android 应用程序,该应用程序将用于与连接有蓝牙模块的 Arduino 微控制器进行串行通信 (RFCOMM)。
据我所知,我为RFCOMM/SPP 00001101-0000-1000-8000-00805F9B34FB
使用了正确的蓝牙地址和UUID。我的应用程序启动了一个尝试使用BluetoothDevice.createRfcommSocketToServiceRecord(UUID)
连接到设备的线程。但出于某种原因,我们没有看到成功的连接。对来自上述调用的结果 BluetoothSocket
调用 connect()
时,该操作总是失败。
在我的HTC Evo 上运行 HTC 的Gingerbread 变体进行测试时,connect()
调用通常会失败并显示异常消息“无法启动服务发现”。我做了一些阅读,发现有人说 HTC 在蓝牙堆栈中对 RFCOMM 的实现有问题,所以我们决定在另一个学生的Samsung Galaxy S 上尝试一下。代码第一次运行时,一切正常。 Arduino 微控制器连接到一个小型电动机,该电动机开始按预期工作。我没有排除问题是否出在微控制器方面。
随后在三星设备上使用该应用程序失败,现在显示“服务发现失败”消息。对我来说,似乎设备端的蓝牙模块认为RFCOMM服务仍在使用中。但是我们重新启动了微控制器,仍然看到了相同的结果。
我刚刚列出了线程代码,因为它是真正相关的所有内容。我读到有一个非常常见的解决方法(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<BluetoothDevice> 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 模块。
另一个编辑: 我不是蓝牙专家,但我们能够找到解决办法。正如一些人所知道的,有一堆公共的 BluetoothDevice API,在编译时隐藏,但在运行时使用反射合法地公开。其中之一是 createRfCommSocket(int)。这个 API 没有在官方文档中,因为它是隐藏的,但是你可以阅读它here。我还没有尝试使用文档支持的 API,但问题似乎是手机和串行板之间的并发问题。手机发送了一条消息,这当然是一个阻塞呼叫,当它从那里返回时,关闭了连接。串行板上的屏蔽也会关闭连接,因此数据对 arduino 应用程序不可用。我们在 android 端在调试模式下见证成功通信时意识到这一点,但在发布模式下失败。在 android 端,在 BluetoothSocket 的传输和关闭之间添加半秒延迟修复了该问题。我不能说这个问题是否是由 arduino 代码引起的,因为我对架构不是很熟悉,但我们作为学生缺乏经验,所以这不会让我感到惊讶。
【问题讨论】:
Arduino 设备上运行的是哪个蓝牙模块和软件?您能否发布对您正在使用的设备的引用。此外,如果您可以在 Android 端发布完整的日志,它会有所帮助。 丹尼斯,感谢您的回复,请接受我的歉意,因为您花了这么长时间才回复您,考试和其他义务一直拖累我。我正在研究 arduino 的型号和软件版本,但我发布了一些关于 BT 设备的信息和一些关于该问题的新信息。 您好,我遇到了类似的问题...我正在尝试将 LG 手机连接到 TI PAN1315 Dev。板,我得到了具有相同 UUID 的套接字,但 connect() 总是抛出一个 IOException。在调试嵌入式 PAN1315 时,我将一些日志打印到控制台,试图弄清楚我是否在原始应用程序设计中搞砸了,我发现 hci/acl 断开连接请求来自电话,而不是来自嵌入式设备,在将链接密钥从嵌入式设备发送到手机之后......你能同意吗? 嗨 TacB0sS,请参阅我上面的评论。 android 蓝牙 API 对于串行板连接显然有些参差不齐,因此使用了许多解决方法。我在这里提到的是一个相当常见的问题,但除此之外,我们还遇到了主板和手机之间的一些并发问题。这可能是也可能不是您想要调查的内容。关于连接关闭和链接密钥交换,我确信任一设备都可以请求连接或关闭,并且链接密钥存储在设备上,以便它们中的任何一个稍后可以相互连接。祝你好运 虽然我承认我完全不知道如何提供帮助,但您可能想尝试electronics.stackexchange.com。 :) 【参考方案1】:Communication Between Android And Arduino With Bluetooth(1)
我认为这会对您有所帮助。 你能提供一些细节吗?我看过一个链接,你也可以看到这个。让我知道这是否有帮助? How to create Insecure RFCOMM Socket in Android?
【讨论】:
你运气好吗?请告诉我。【参考方案2】:Amarino Toolkit 专为促进 Android 设备和带有蓝牙的 Arduino 之间的串行蓝牙通信而构建。
【讨论】:
以上是关于如何将 Android 应用程序正确连接到支持蓝牙的 Arduino 微控制器上的 RFCOMM 插座?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 iOS 中使用 iphone 5 连接到支持蓝牙 2.1 的设备
Android 手机从蓝牙更改为 BLE 后无法连接到树莓派
通过蓝牙将 Android 应用程序连接到 Mac OS X 上的 Python 脚本