Android:在SPP蓝牙设备之间切换

时间:2012-07-02 11:08:33

标签: android bluetooth spp

我有两种不同的蓝牙打印机。 Bixolon SPP-R200和Fujitsu FTP-628WSL110。我可以分别连接到每个(使用三星Galaxy SII)打印,断开连接并重新连接就好了。但是,如果我关闭Bixolon并尝试与Fujitsu配对(之前未配对,Bixolon仍然配对),那么在尝试连接到创建的套接字时它会失败。相反的方式。

以下是错误消息:

07-02 13:00:11.040: E/MyApp.BluetoothConnection(9380): Failed to connect to rfcomm socket.
07-02 13:00:11.040: E/MyApp.BluetoothConnection(9380): java.io.IOException: Service discovery failed
07-02 13:00:11.040: E/MyApp.BluetoothConnection(9380):  at android.bluetooth.BluetoothSocket$SdpHelper.doSdp(BluetoothSocket.java:406)
07-02 13:00:11.040: E/MyApp.BluetoothConnection(9380):  at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:217)
07-02 13:00:11.040: E/MyApp.BluetoothConnection(9380):  at MyApp.BluetoothConnection.connect(BluetoothConnection.java:171)
07-02 13:00:11.040: E/MyApp.BluetoothConnection(9380):  at MyApp.AbstractBluetoothPrinter.connect(AbstractBluetoothPrinter.java:34)

这是进行连接尝试的代码,在解释的情况下失败的行是btSocket.connect(); - 例外见上文:

/** Is set in connect() */
private BluetoothSocket btSocket = null;
/** Is set prior to connect() */
private BluetoothSocket btDevice;

public boolean connect(){

        try {
            btSocket = btDevice.createRfcommSocketToServiceRecord("00001101-0000-1000-8000-00805F9B34FB");
            if (btDevice.getName().startsWith("FTP")) {
                //Special treatment for the fujitsu printer
                SystemClock.sleep(1000);
            }
        } catch (Throwable e) {
            LogCat.e(TAG, "Failed to create rfcomm socket.", e);
            return false;
        }

        try {
            // Stop Bluetooth discovery if it's going on
            BluetoothHandler.cancelDiscovery();
            // This fails under the described circumstances
            btSocket.connect();
        } catch (Throwable e) {
            LogCat.e(TAG, "Failed to connect to rfcomm socket.", e);
            return false;
        }

        // Obtain streams etc...
}

我正在使用相同的 UUID连接到两个设备(但是一次只打开一个设备,它们从不同时打开),SDK API中众所周知的SPP UUID:

00001101-0000-1000-8000-00805F9B34FB

这让我想知道:可能是,我需要为每个设备使用不同的UUID吗?如果是的话有什么想法吗?

1 个答案:

答案 0 :(得分:10)

好几天尝试不同的解决方案后,我现在能够在上述打印机之间切换。由于我不完全确定我的哪些措施是成功的原因,我将列出所有这些,所以有人在这篇文章上磕磕碰碰将有一些关于如何解决他的蓝牙问题的线索。但有一点我很确定:你不需要不同的UUID来连接两台不同的打印机 - 你可以使用相同的UUID(但我只打开其中一台)。

我缓存上次打印的设备 - 但不像之前我​​不再缓存实际的BluetoothDevice,而是只缓存它的mac地址,可以通过以下方式获得:

BluetoothDevice bluetoothDevice; 

//Obtain BluetoothDevice by looking through paired devices or starting discovery

bluetoothDevice.getAddress(); 

getAddress()返回一个字符串:设备的硬件地址。我缓存该mac地址,下次用户想要打印时,我将缓存的mac地址与所有配对打印机的mac地址相匹配 - 如果mac地址匹配其中一个,我尝试连接到该打印机。如果失败,我重置我的缓存的mac地址,并尝试通过首先检查我的配对设备,如果其中一个可以连接(如果我可以成功连接,我相应地更新我的缓存的mac地址)找到另一个设备,如果失败我开始寻找其他潜在设备的蓝牙发现。

现在为了不让任何套接字连接打开到我的一台打印机,我的例行程序如下(我将省略每次调用所附带的try-catches以简化读取):

创建套接字

BluetoothSocket btSocket = btDevice.createRfcommSocketToServiceRecord(MY_UUID);

MY_UUID是指用于连接SPP设备的众所周知的UUID:

00001101-0000-1000-8000-00805F9B34FB

如果socket creation失败(这是罕见的,如果它发生,很可能是由于权限不足或蓝牙被禁用/不可用),我们无法继续,因为我们需要一个套接字才能连接。因此,在catch块中,您应该触发disconnect方法(稍后会详细介绍)。

连接到创建的套接字

bSocket.connect();

如果连接失败,我们无法继续进行,因为我们需要有效的套接字连接来获取输入和输出流。因此,在catch块中,您应该触发disconnect方法(稍后会详细介绍)。

获取输入和输出流

下一步是从套接字获取输入和输出流。我在for循环中执行此操作,该循环运行几次(5次应该足够) - 在每次迭代中我检查是否有输出流,如果没有,我尝试获取它,对于输入流也是如此。在循环结束时,我检查我是否有两个流,如果是,我退出循环(和整个连接方法),如果不是,我继续循环再试一次。通常我会在第一次循环迭代中获得两个流,但有时我需要两次或三次迭代才能获得两个流。

如果我在循环声明后到达后面的代码,我显然没有得到我的流或其他错误。此时连接被认为已经失败,我执行我的断开连接代码(清理开放流和插槽,稍后会更多)。

<强>读/写

现在您已连接到目标蓝牙设备,您可以执行读写操作。一旦你完成了,你应该通过关闭所有流和套接字进行清理,在下一段中更多内容:断开连接。切记:如果在读/写操作期间发生异常,请务必触发disconnect方法以清理资源。如果您的打印机需要某种初始化命令,请务必在连接到打印机后以及执行读/写操作之前立即发送。

<强>断开

通常有两种情况你应该断开连接:

  • 完成读/写操作后
  • 如果在此过程中某处发生异常,请清理资源

关闭您的信息流

您要做的第一件事是清理您的流,检查两者,您的输入和输出流,如果它们不为空,关闭它们并将它们设置为null。确保将每个操作(关闭输入流,关闭输出流等)包装到它自己的try-catch中,否则无法进行一次清理(因为引发了异常)将跳过所有其他清理措施。

关闭套接字

既然您已确保清理输入流,请继续关闭套接字连接,然后将其设置为null。

还有一件事:我在disconnect方法的开头和结尾都有一个Thread.sleep。开头的那个长约2.5秒(= 2500毫秒),目的是确保打印机没有其他任何东西(例如挂起的读/写操作或打印机仍在打印等)。第二个Thread.sleep在我的disconnect方法的末尾,大约800毫秒长。最后睡眠的原因与我在关闭后立即尝试立即打开新套接字时遇到的问题有关。有关详细信息,请参阅this answer

<强>问题吗

如果有人对我的OP或我的回答有任何疑问,请在评论中告诉我,我会尽力回答。