陷入一期,
我正在使用BluetoothSocket
类,我在输入和输出流的帮助下发送和接收数据。
当应用程序从输入流接收大量数据时,我强行终止我的应用程序,之后我又重新启动了我的应用程序,但是InputStream
返回了我以前的数据,这是不再需要的了。如何丢弃旧数据?
对于这个问题有任何解决方案吗?
以下是我的源代码:
public class MyBluetoothService {
private static final String TAG = "MY_APP_DEBUG_TAG";
private Handler mHandler; // handler that gets info from Bluetooth service
// Defines several constants used when transmitting messages between the
// service and the UI.
private interface MessageConstants {
public static final int MESSAGE_READ = 0;
public static final int MESSAGE_WRITE = 1;
public static final int MESSAGE_TOAST = 2;
// ... (Add other message types here as needed.)
}
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
public 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;
}
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.
Message readMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_READ, numBytes, -1,
mmBuffer);
readMsg.sendToTarget();
} 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.
Message writtenMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
writtenMsg.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Error occurred when sending data", e);
// Send a failure message back to the activity.
Message writeErrorMsg =
mHandler.obtainMessage(MessageConstants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString("toast",
"Couldn't send data to the other device");
writeErrorMsg.setData(bundle);
mHandler.sendMessage(writeErrorMsg);
}
}
// 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);
}
}
}
}
答案 0 :(得分:1)
// Keep listening to the InputStream until an exception occurs
问题出在这里。您应该继续从流中读取,直到流结束或发生异常。如果read()
返回-1,则需要中断读取循环。
目前,您正在读取超出流的结尾,并完全忽略该条件,因此当然上次成功读取时缓冲区中的数据仍然存在。
为了让您的应用程序看到该数据,您还必须忽略读取计数并假设缓冲区已填满,这也是无效的。
答案 1 :(得分:-1)
我认为您应该关闭套接字以管理错误。
我建议你在终结器中执行此操作,如下面的代码。
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
@override
protected void finalize() throws Throwable
{
try
{
cancel();
}
finally
{
super.finalize();
}
}
...
正如我在评论中提到的那样,在关闭套接字之前关闭每个stream
更安全。
所以,试试这个cancel()
方法。
// Call this method from the main activity to shut down the connection.
public void cancel()
{
try {
mmInStream.close();
} catch( NullPointerException | IOException e) {}
try {
mmOutStream.close();
} catch( NullPointerException | IOException e) {}
try
{
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
more information关于finalize
方法。
编辑:大胆的内容比其他建议重要。
阅读EJP的评论我理解为什么你的应用程序在你获得大数据时会停止:你可能必须在调用read()
之前清除缓冲区。他说终结者可能不会被系统调用(我不知道为什么)。
break
返回 read()
>> <{strong> -1
循环?
刚才我找到了一个有用的link关于正确读取流的方法。我希望它有所帮助。
链接引用的代码
private String extract(InputStream inputStream) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int read = 0; while ((read = inputStream.read(buffer, 0, buffer.length)) != -1) { baos.write(buffer, 0, read); } baos.flush(); return new String(baos.toByteArray(), "UTF-8"); }
另外
虽然在关闭finalizer
之前系统关闭streams
可能无法调用sockets
更安全(我之前读过一些SO线程)。