Search code examples
androidbluetoothbufferblockingqueue

Implementing BlockingQueue Buffer used in Bluetooth Communication for Android


I'm really stumped with this and I've trying to debug for the passed three days. Hopefully someone will be able to tell me what I am doing wrong.

I am implementing a BlockingQueue (FIFO) buffer to receive information being streamed from my PC over bluetooth. I am sending prerecorded electrocardiogram signal over a Hyperterminal link using RealTerm.

I have tested the buffer as I start up the app by adding values and then removing them, and it seems to work as it should.

The problem comes in when I try to store in the buffer while I'm receiving data from the bluetooth connection. I don't know if I am adding faster than the BlockingQueue can cope, but when I stop the data transmission and check my buffer, the whole buffer contains the last value that was added. The size of the buffer is correct, but the content isn't.

Here is my buffer:

public class IncomingBuffer {

private static final String TAG = "IncomingBuffer";

private BlockingQueue<byte[]> inBuffer;

public IncomingBuffer() {
    inBuffer = new LinkedBlockingQueue<byte[]>();
    Log.i(TAG, "Initialized");
}

public int getSize() {
    int size;
    size = inBuffer.size();
    return size;
}

// Inserts the specified element into this queue, if possible. Returns True
// if successful.
public boolean insert(byte[] element) {
    Log.i(TAG, "Inserting " + element[0]);

    boolean success = inBuffer.offer(element);
    return success;

}

// Retrieves and removes the head of this queue, or null if this queue is
// empty.
public byte[] retrieve() {
    Log.i(TAG, "Retrieving");
    return inBuffer.remove();

}

// Retrieves, but does not remove, the head of this queue, returning null if
// this queue is empty.
public byte[] peek() {

    Log.i(TAG, "Peeking");
    return inBuffer.peek();
}
}

The portion of my BluetoothCommunication class which receives the information and sends it to the buffer is the following:

   public void run() {
        Log.i(TAG, "BEGIN mConnectedThread");
        ringBuffer = new IncomingBuffer();

        byte[] buffer = new byte[1024];
        Log.i(TAG, "Declared buffer byte");

        int bytes;

        byte[] retrieve;
        int size;

        Log.i(TAG, "Declared int bytes");
        //Setting up desired data format 8
        write(helloworld);
        Log.i(TAG, "Call write(initialize)");

        // Keep listening to the InputStream while connected
        while (true) {
            try {
                Log.i(TAG, "Trying to get message");
                // Read from the InputStream
                bytes = mmInStream.read(buffer);

                //THIS IS WHERE THE BYTE ARRAY IS ADDED TO  THE IncomingBuffer
                RingBuffer.insert(buffer);

                // Send the obtained bytes to the UI Activity
                mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer)
                        .sendToTarget();

                Log.i(TAG, "Sent to target" +ringBuffer.getSize());
            } catch (IOException e) {
                Log.e(TAG, "disconnected", e);
                connectionLost();
                // Start the service over to restart listening mode
                BluetoothCommService.this.start();
                break;
            }
        }
    }

So an example of my problem would be:

Send values over bluetooth connection (8 bit values from 1 to 20). In the insert method of the IncomingBuffer class, the log message confirms the proper value is sent. When values are retrieved from buffer, it contains twenty byte arrays which all contain the last number inserted (20).

Any clue as to why the buffer would work in other circumstances but not during the bluetooth communication?


Solution

  • I figured out what my problem was.

    When I was using the variable buffer to read from mmInStream and then pass that to the ringBuffer, I pass the same byte array variable every time i go through the while loop. From what I can understand that simply assigns a specific memory location where the byte array is calculated and that is why at the end all of the elements in my ringBuffer are the last value that was assigned to 'buffer' from the mmInStream.

    What i did to change that is make a separate variable that i clone the 'buffer' byte array to. Before I pass 'buffer' to 'RingBuffer', i do the following:

    byte[] newBuf;
    newBuf = buffer.clone();
    ringBuffer.store(newBuf);
    

    This takes care of my problem.