所以我在运行pybluez rfcomm-server的配对的raspberry pi设备之间建立了一个串行连接。我已经将我的Android设备与Pi配对,然后整合了一个利用线程处理双向异步通信的蓝牙服务。大多数代码都是直接来自Android开发人员指南上的蓝牙套接字通信here和读取/写入套接字here
当我通过关闭套接字并关闭处理通信的线程手动断开Pi时,会出现问题。我可以重新连接,启动另一个线程,然后再次成功开始与Pi进行通信但这就是它变得奇怪的地方,IOExcpetions开始被抛出,而Logcat正在骚扰和呻吟,并且"发生了错误发送数据"。这个例外很明显,就像我之前说过的那样,Pi仍然乐于接收消息。我可以通过一次又一次地断开连接和重新连接来重复这一点。
通常我会耸耸肩继续前进,因为它的工作正常吗?但我不觉得应该抛出任何IOExceptions。
以下是一些代码:
(BtBus是我制作的基于RxJava的消息总线,所有消息都在后台线程上发送并在主线程上接收)
BluetoothService - connect()和disconnect()方法
public void connect(){
if(btAdapter == null) {
Log.e(TAG, "No bluetooth adapter available");
}
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
// There are paired devices. Get the name and address of each paired device.
for (BluetoothDevice device : pairedDevices) {
if(device.getName().contains("raspberry")){
pi = device;
Log.d(TAG, "using paired device: " + pi.getName());
break;
}
}
}else {
Log.d(TAG, "No BT devices paired");
}
if(pi != null) {
if(btAdapter.isDiscovering())
btAdapter.cancelDiscovery();
Observable.fromCallable(this::connectSocket)
.observeOn(Schedulers.io())
.subscribeOn(Schedulers.io())
.subscribe(socket -> {
if(socket != null){
try {
socket.connect();
Log.d(TAG, "Socked with device created, creating thread");
connectedThread = new ConnectedThread(socket);
Log.d(TAG, "Thread created, starting...");
connectedThread.start();
Log.d(TAG, "Thread Started");
isConnected = true;
BtBus.publish(new BtAction("CONNECTION_ESTABLISHED"));
}catch (IOException e) {
Log.d(TAG, "Unable to connect socket");
e.printStackTrace();
}
}
});
}
//disconnect
public void disconnect() {
if(socket != null) {
connectedThread.cancel();
}
}
private BluetoothSocket connectSocket(){
try {
socket = pi.createInsecureRfcommSocketToServiceRecord(DEFAULT_UUID);
return socket;
}catch (IOException e){
Log.d(TAG, "Failed to get service with Pi UUID");
return null;
}
}
ConnectedThread
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private byte[] mmBuffer; // mmBuffer store for the stream
private ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams; using temp objects because
// member streams are final.
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating input stream", e);
}
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating output stream", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
BtBus.subscribe(action -> {
if(action instanceof BtAction){
write(((BtAction) action).getAction().getBytes());
}
});
}
public void run() {
mmBuffer = new byte[1024];
int numBytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs.
while (true) {
try {
// Read from the InputStream.
numBytes = mmInStream.read(mmBuffer);
// Send the obtained bytes to the UI activity.
BtAction action = BtCommFilter.getActionType(mmBuffer);
BtBus.publish(action);
} catch (IOException e) {
Log.d(TAG, "Input stream was disconnected", e);
break;
}
}
}
// Call this from the main activity to send data to the remote device.
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
// Share the sent message with the UI activity.
} catch (IOException e) {
Log.e(TAG, "Error occurred when sending data", e);
// Send a failure message back to the activity.
}
}
// Call this method from the main activity to shut down the connection.
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
}
这是来自异常
的堆栈相关堆栈跟踪E/BluetoothService: Error occurred when sending data
java.io.IOException: socket closed
at android.net.LocalSocketImpl$SocketOutputStream.write(LocalSocketImpl.java:130)
at android.bluetooth.BluetoothSocket.write(BluetoothSocket.java:659)
at android.bluetooth.BluetoothOutputStream.write(BluetoothOutputStream.java:85)
at java.io.OutputStream.write(OutputStream.java:82)
at com.medspark.tenscontroller.service.BluetoothService$ConnectedThread.write(BluetoothService.java:183)
at com.medspark.tenscontroller.service.BluetoothService$ConnectedThread.lambda$new$0$BluetoothService$ConnectedThread(BluetoothService.java:157)
at com.medspark.tenscontroller.service.BluetoothService$ConnectedThread$$Lambda$0.accept(Unknown Source)
at io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:60)
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:200)
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6872)
正如您所看到的,当我关闭连接时,插座正确关闭并且线程被丢弃。当我重新连接时,创建了一个新的套接字并且新的线程被启动,所以我不知道抛出IOException的位置。提前谢谢。