简体   繁体   English

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

[英]How can I properly connect an Android application to an RFCOMM socket on a Bluetooth enabled Arduino microcontroller?

I'm working with some students at my university developing a simple Bluetooth Android application that will be used for serial communication (RFCOMM) to an Arduino microcontroller with a Bluetooth module connected to it. 我正在和我大学的一些学生一起开发一个简单的蓝牙Android应用程序,该应用程序将用于连接到蓝牙模块的Arduino微控制器的串行通信(RFCOMM)。

To the best of my knowledge, I'm using the correct Bluetooth address and UUID for RFCOMM/SPP 00001101-0000-1000-8000-00805F9B34FB . 据我所知,我正在使用RFCOMM/SPP 00001101-0000-1000-8000-00805F9B34FB的正确蓝牙地址和UUID。 My application starts a thread that attempts to connect to the device using BluetoothDevice.createRfcommSocketToServiceRecord(UUID) . 我的应用程序启动一个尝试使用BluetoothDevice.createRfcommSocketToServiceRecord(UUID)连接到设备的线程。 But for one reason or another, we are not seeing a successful connection. 但由于某种原因,我们没有看到成功的联系。 The operation always fails upon invoking connect() on the resulting BluetoothSocket that comes from the invocation above. 在上面的调用产生的BluetoothSocket上调用connect()时,操作总是失败。

When tested on my HTC Evo , running HTC's variant of Gingerbread , the connect() call usually fails with the exception message "Service Discovery Could Not Be Started." 在我的HTC Evo上测试,运行HTC的Gingerbread变种时, connect()调用通常会失败,并显示异常消息“服务发现无法启动”。 I did some reading and found that some said that HTC's implementation for RFCOMM in the Bluetooth stack was buggy, so we decided to try it on another student's Samsung Galaxy S . 我做了一些阅读,发现有人说HTC在蓝牙堆栈中对RFCOMM的实现是错误的,所以我们决定在另一个学生的三星Galaxy S上试用它。 The first time the code ran, everything worked perfectly. 代码第一次运行时,一切都运行良好。 The Arduino microcontroller is connected to a small electric motor which began working as expected. Arduino微控制器连接到一个小电动机,开始按预期工作。 I have not ruled out whether or not the problem could be on the microcontroller's side. 我没有排除问题是否可能出在微控制器方面。

Subsequent uses of the application on the Samsung device then failed, now with a message saying "Service Discovery Failed". 随后在Samsung设备上使用该应用程序失败,现在显示“Service Discovery Failed”消息。 To me, it seems that perhaps the Bluetooth module on the device side thinks that the RFCOMM service is still in use. 对我来说,似乎设备端的蓝牙模块可能认为RFCOMM服务仍在使用中。 But we've restarted the microcontroller and still saw the same result. 但是我们重新启动了微控制器并且仍然看到了相同的结果。

I've just listed the thread code as it is all that is really relevant. 我刚刚列出了线程代码,因为它是真正相关的。 I've read that there is a pretty common workaround (hack) for these issues using reflection. 我已经读过使用反射这些问题有一个非常常见的解决方法(hack)。 My attempts at it have also failed but are there and commented out. 我对它的尝试也失败了但是在那里并且被注释掉了。 Hopefully someone can steer me in the right direction here. 希望有人能引导我朝着正确的方向前进。 Also note that I do have the necessary permissions enabled in the manifest and in both cases, the device was successfully paired to the Arduino using Android's user interface. 另请注意,我确实在清单中启用了必要的权限,在这两种情况下,设备都使用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();
            }
        }
    }
}

EDIT: The Bluetooth module is an MDFLY RF-BT0417CB. 编辑:蓝牙模块是MDFLY RF-BT0417CB。 I know that the code that is running on the arduino is not much and is simply communicating with the BT module using Serial.available() and Serial.read(). 我知道在arduino上运行的代码并不多,只是使用Serial.available()和Serial.read()与BT模块进行通信。 However I have a new piece of information that may be of more use. 但是,我有一条可能更有用的新信息。 When my application was installed on the Samsung device, it worked just once, and failed on subsequent trials. 当我的应用程序安装在三星设备上时,它只工作一次,并在后续试验中失败。 A while back, the other student I'm working with, used Android App Inventor (a drag and drop GUI tool that also can create logical working artifacts) to create a simple application that connects the same BT module/arduino board, which worked. 不久前,我正在使用的另一名学生使用Android App Inventor(一种拖放式GUI工具,也可以创建逻辑工作工件)来创建一个连接相同BT模块/ arduino板的简单应用程序。 He said that when my application was installed, that the other application was unable to ever connect to the BT module, which leads me to believe the system stayed thinking that the resource was allocated to my application. 他说,当我的应用程序安装完毕后,其他应用程序无法连接到BT模块,这让我相信系统仍然认为资源已分配给我的应用程序。 After he uninstalled my app, the other was able to connect. 在他卸载我的应用程序后,另一个能够连接。 He does not have the source code to the other application, but I am going to try App Inventor myself to see if the source code it generates it generates is doing anything different. 他没有其他应用程序的源代码,但我将自己尝试使用App Inventor来查看它生成的源代码是否生成了不同的内容。 To the best of my knowledge, I am complying with most of the standard practices defined in Android's documentation, so perhaps it's something strange about the BT module or the fact that the arduino code isn't necessarily programmatically controlling the BT module. 据我所知,我遵守Android文档中定义的大多数标准实践,所以也许BT模块或者arduino代码不一定以编程方式控制BT模块这一事实。

ANOTHER EDIT: I'm not a Bluetooth expert, but we were able to figure out a work around. 另一个编辑:我不是蓝牙专家,但我们能够找到一个解决方案。 As some are aware, there are a bunch of public BluetoothDevice API's, hidden at compile time, but are legally public at runtime using reflection. 有些人都知道,有许多公共BluetoothDevice API在编译时隐藏,但在运行时使用反射合法公开。 One of them is createRfCommSocket(int). 其中之一是createRfCommSocket(int)。 This API is not in the official documentation since it is hidden, but you can read it here . 此API不在官方文档中,因为它是隐藏的,但您可以在此处阅读。 I haven't tried it yet with the documentation supported API, but the problem appeared to be something of a concurrency issue between the handset and the serial board. 我还没有尝试使用文档支持的API,但问题似乎是手机和串行板之间的并发问题。 The handset sent a message, which is of course a blocking call, and when it returned from there, closed the connection. 手机发送了一条消息,这当然是一个阻塞呼叫,当它从那里返回时,关闭了连接。 The shield on the serial board would then also close the connection and hence the data was not available to the arduino application. 然后,串行板上的屏蔽也将关闭连接,因此arduino应用程序无法获得数据。 We realized this when witnessing successful communication while in debug mode on the android side, but failure in release mode. 我们在android端调试模式下见证成功通信时意识到这一点,但在发布模式下失败了。 Adding a half second delay on the android side, between the transmission and closure of the BluetoothSocket fixed the issue. 在android端添加半秒延迟,在BluetoothSocket的传输和关闭之间修复了这个问题。 I cannot say whether this issue was attributed to by the arduino code or not as I am not very familiar with the architecture, but we as students lack experience so it wouldn't surprise me. 我不能说这个问题是否归因于arduino代码,因为我对这个架构不是很熟悉,但是我们学生们缺乏经验所以不会让我感到惊讶。

Communication Between Android And Arduino With Bluetooth(1) Android和Arduino之间的通信与蓝牙(1)

I think this will be helpful to you. 我想这会对你有所帮助。 Can you provide some detail on this.I have seen one link ,you can see this too. 你能提供一些细节吗。我看过一个链接,你也可以看到这个。 Let me know whether this is helpfull or no? 让我知道这是有帮助还是没有? How to create Insecure RFCOMM Socket in Android? 如何在Android中创建不安全的RFCOMM套接字?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM