0

stuck in One Issue ,

I am using BluetoothSocket class, I am sending and receiving data with the help of input and output streams.

when App receives large amount of data from input stream, I am killing my app forcefully and after it I am again restarting my app, but InputStream returns me previous data, which is not needed anymore.how to discard that old data?

has Anyone Some Solution for this Issue?

Following is my source code:

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);
            }
        }
    }
}
Vishal Chhodwani
  • 2,567
  • 5
  • 27
  • 40

2 Answers2

1
// Keep listening to the InputStream until an exception occurs

The problem is here. You should keep reading from the stream until end of stream or an exception occurs. You need to break out of the read loop if read() returns -1.

At present you are reading beyond end of stream, and ignoring the condition altogether, so of course the data that was in the buffer on the last successful read is still there.

For your application to keep seeing that data, you must also be ignoring the read count and assuming the buffer was filled, which also is invalid.

user207421
  • 305,947
  • 44
  • 307
  • 483
-1

I think you should close the socket to manage the bug.

I recommend you to do this in finalizer like the code below.

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();
   }
 }
...

Also as I mentioned in comment, it is safer to close every streams before closing the socket.

So, try this cancel() method.

// 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);
     }
 }

And more information about finalize method.

EDIT: bold ones are important than other suggestions.

Reading comments of EJP I understood why your app stops when you get large data : you maybe have to clear buffers before calling read(). And he says that finalizer can happen not to be called by system (I don't know why). How about breaking the loop when the read() returned -1?

And just now I found a helpful link about proper method to read a stream. I hope it helped.

Code cited from the 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");
  }

Also Though the finalizer may be able not to be called by system closing streams before closing sockets is safer (I read some SO threads before).

KYHSGeekCode
  • 1,068
  • 2
  • 12
  • 30