How to read and write data through Java Nio client in Android - android

I am doing Client server communication in java successfully but now i need to write client in Android rather the java.
client: public class ExampleClient2 {
public static void main(String[] args) throws IOException,
InterruptedException {
int port = 1114;
SocketChannel channel = SocketChannel.open();
// we open this channel in non blocking mode
channel.configureBlocking(false);
channel.connect(new InetSocketAddress("192.168.1.88", port));
if(!channel.isConnected())
{
while (!channel.finishConnect()) {
System.out.println("still connecting");
}
}
System.out.println("connected...");
while (true) {
// see if any message has been received
ByteBuffer bufferA = ByteBuffer.allocate(60);
int count = 0;
String message = "";
while ((count = channel.read(bufferA)) > 0) {
// flip the buffer to start reading
bufferA.flip();
message += Charset.defaultCharset().decode(bufferA);
}
if (message.length() > 0) {
System.out.println("message " + message);
if(message.contains("stop"))
{
System.out.println("Has stop messages");
// break;
}
else
{
// write some data into the channel
CharBuffer buffer = CharBuffer.wrap("Hello Server stop from client2 from 88");
while (buffer.hasRemaining()) {
channel.write(Charset.defaultCharset().encode(buffer));
}
}
message = "";
}
}
}
}
this code is running successfully in java but in android it consuming lots of memory and not running reliably, due to its while (true) loop its like polling , plz let me know some solution that without polling i can read and write the data.
Thanks.

You need to compact() the buffer after calling decode() (or get(), or write(), anything that takes data out of the buffer).
Youu shouldn't allocate a new buffer every time around that while loop, and you should break out of it if read() returned -1. I don't actually see a need for the while loop at all.

Related

Packet Sent but cannot Received Packets

I've been editing androids toyvpn sample project for vpn and i got this one for my sample app
I know there is something wrong/missing with my code because when i manually set up the vpn via android settings, there are packets Receive that's why
i've been searching how to receive packets and i dont know how to get this working.
here is my source code that VCL that extends VpnService
import android.app.PendingIntent;
import android.net.VpnService;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
/**
* Created by Jameshwart Lopez on 8/18/15.
*/
public class VCL extends VpnService {
private static final String TAG = "VpnClientLibrary";
private Thread mThread;
private ParcelFileDescriptor mInterface;
private String mServerAddress;
private String mServerPort;
private PendingIntent mConfigureIntent;
private String mParameters;
//a. Configure a builder for the interface.
Builder builder = new Builder();
public void vclRun(){
try {
//a. Configure the TUN and get the interface.
mInterface = builder.setSession("thesessionname")
.addAddress("192.168.0.1",24)
.addDnsServer("8.8.8.8")
.addRoute("0.0.0.0", 0).establish();
//b. Packets to be sent are queued in this input stream.
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
//b. Packets received need to be written to this output stream.
FileOutputStream out = new FileOutputStream(mInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
//c. The UDP channel can be used to pass/get ip package to/from server
DatagramChannel tunnel = DatagramChannel.open();
// Connect to the server, localhost is used for demonstration only.
mServerAddress="";//some of the vpn ip address here
mServerPort="1723";
InetSocketAddress server = new InetSocketAddress(mServerAddress, Integer.parseInt(mServerPort) );
tunnel.connect(server);
// For simplicity, we use the same thread for both reading and
// writing. Here we put the tunnel into non-blocking mode.
tunnel.configureBlocking(false);
// Authenticate and configure the virtual network interface.
handshake(tunnel);
//d. Protect this socket, so package send by it will not be feedback to the vpn service.
protect(tunnel.socket());
int timer = 0;
//e. Use a loop to pass packets.
while (true) {
//get packet with in
//put packet to tunnel
//get packet form tunnel
//return packet with out
//sleep is a must
// Assume that we did not make any progress in this iteration.
boolean idle = true;
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
// Write the outgoing packet to the tunnel.
packet.limit(length);
tunnel.write(packet);
packet.clear();
// There might be more outgoing packets.
idle = false;
// If we were receiving, switch to sending.
if (timer < 1) {
timer = 1;
}
}
// Read the incoming packet from the tunnel.
length = tunnel.read(packet);
if (length > 0) {
// Ignore control messages, which start with zero.
if (packet.get(0) != 0) {
// Write the incoming packet to the output stream.
out.write(packet.array(), 0, length);
}
packet.clear();
// There might be more incoming packets.
idle = false;
// If we were sending, switch to receiving.
if (timer > 0) {
timer = 0;
}
}
// If we are idle or waiting for the network, sleep for a
// fraction of time to avoid busy looping.
if (idle) {
Thread.sleep(100);
// Increase the timer. This is inaccurate but good enough,
// since everything is operated in non-blocking mode.
timer += (timer > 0) ? 100 : -100;
// We are receiving for a long time but not sending.
if (timer < -15000) {
// Send empty control messages.
packet.put((byte) 0).limit(1);
for (int i = 0; i < 3; ++i) {
packet.position(0);
tunnel.write(packet);
}
packet.clear();
// Switch to sending.
timer = 1;
}
// We are sending for a long time but not receiving.
//if (timer > 20000) {
// throw new IllegalStateException("Timed out");
//}
}
}
} catch (Exception e) {
// Catch any exception
e.printStackTrace();
} finally {
try {
if (mInterface != null) {
mInterface.close();
mInterface = null;
}
} catch (Exception e) {
}
}
}
private void handshake(DatagramChannel tunnel) throws Exception {
// To build a secured tunnel, we should perform mutual authentication
// and exchange session keys for encryption. To keep things simple in
// this demo, we just send the shared secret in plaintext and wait
// for the server to send the parameters.
// Allocate the buffer for handshaking.
ByteBuffer packet = ByteBuffer.allocate(1024);
// Control messages always start with zero.
String password = "";//vpn password here
packet.put((byte) 0).put(password.getBytes()).flip();
// Send the secret several times in case of packet loss.
for (int i = 0; i < 3; ++i) {
Log.e("packetsdata", packet.toString());
packet.position(0);
tunnel.write(packet);
}
packet.clear();
// Wait for the parameters within a limited time.
for (int i = 0; i < 50; ++i) {
Thread.sleep(100);
// Normally we should not receive random packets.
int length = tunnel.read(packet);
if (length > 0 && packet.get(0) == 0) {
configure(new String(packet.array(), 1, length - 1).trim());
return;
}
}
//throw new IllegalStateException("Timed out");
}
private void configure(String parameters) throws Exception {
// If the old interface has exactly the same parameters, use it!
if (mInterface != null) {
Log.i(TAG, "Using the previous interface");
return;
}
// Configure a builder while parsing the parameters.
Builder builder = new Builder();
for (String parameter : parameters.split(" ")) {
String[] fields = parameter.split(",");
try {
switch (fields[0].charAt(0)) {
case 'm':
builder.setMtu(Short.parseShort(fields[1]));
break;
case 'a':
builder.addAddress(fields[1], Integer.parseInt(fields[2]));
break;
case 'r':
builder.addRoute(fields[1], Integer.parseInt(fields[2]));
break;
case 'd':
builder.addDnsServer(fields[1]);
break;
case 's':
builder.addSearchDomain(fields[1]);
break;
}
} catch (Exception e) {
throw new IllegalArgumentException("Bad parameter: " + parameter);
}
}
// Close the old interface since the parameters have been changed.
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
// Create a new interface using the builder and save the parameters.
mInterface = builder.setSession(mServerAddress)
.setConfigureIntent(mConfigureIntent)
.establish();
mParameters = parameters;
Log.i(TAG, "New interface: " + parameters);
}
}
this is how i use the class above
private Thread mThread;
/*
* Services interface
* */
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Start a new session by creating a new thread.
mThread = new Thread(this, "VpnRunnable");
//start the service
mThread.start();
/*
*service is left "started" and will later be restarted by the system
* http://android-developers.blogspot.com.au/2010/02/service-api-changes-starting-with.html
*/
return START_STICKY;
}
#Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
super.onDestroy();
}
#Override
public synchronized void run() {
/*
* to run the vpn interface call the vclRun method inside VCL class
* */
this.vclRun();
}
Firstly, check that there are bytes being sent to your android device. As it won't be reading anything if there is nothing to receive.
Then have a look at this, as it may be messing up your connection.
You need to include this in the onStartCommand:
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
// Stop the previous session by interrupting the thread.
if (mThread != null) {
mThread.interrupt();
}
// Extract information from the intent.
String prefix = getPackageName();
mServerAddress = intent.getStringExtra(prefix + ".ADDRESS");
mServerPort = intent.getStringExtra(prefix + ".PORT");
mSharedSecret = intent.getStringExtra(prefix + ".SECRET").getBytes();
// Start a new session by creating a new thread.
mThread = new Thread(this, "ToyVpnThread");
mThread.start();
return START_STICKY;
And also the details (some shown below) of the sychronized void.
#Override
public synchronized void run() {
try {
Log.i(TAG, "Starting");
// If anything needs to be obtained using the network, get it now.
// This greatly reduces the complexity of seamless handover, which
// tries to recreate the tunnel without shutting down everything.
// In this demo, all we need to know is the server address.
InetSocketAddress server = new InetSocketAddress(
mServerAddress, Integer.parseInt(mServerPort));
// We try to create the tunnel for several times. The better way
// is to work with ConnectivityManager, such as trying only when
// the network is avaiable. Here we just use a counter to keep
// things simple.
for (int attempt = 0; attempt < 10; ++attempt) {
mHandler.sendEmptyMessage(R.string.connecting);
// Reset the counter if we were connected.
// See BELOW
if (run(server)) {
attempt = 0;
}
// Sleep for a while. This also checks if we got interrupted.
Thread.sleep(3000);
} /..../
You are not managing your thread actions well. It is advised to receive any bytes that need to be received before attempting your run. That not doing so can cause problems.
I would go back through your code and put in the things you took out.
I also suggest you change your code here:
packet.put((byte) 0).put(password.getBytes()).flip();
Try to use explicit encoding:
packet.put((byte) 0).put(password.getBytes("UTF-8")).flip();
As data can be lost without it. See this answer:
https://stackoverflow.com/a/7947911/3956566
I have checked and your project is using "UTF-8".
Let me know if this doesn't help.

QTcpServer with android client unable to print or use data received from client

I am developing Client-Server application in C++ using Qt framework, but the clients can be android phones and computers(Qt client app)
Now i'm having troubles to handle Reception of data on the server side; the server is not receiving data properly.
First, I got things working nicely between the server(Qt app) and the client(Qt app) using these methods for sending and receiving:
The size of the message is kept at the beginning of the packet to help check whether the whole message is received or not.
This is the method to send message to the clients
void Server::send(const QString &message)
{
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
out << (quint16) 0; // just put 0 at the head of the paquet to reserve place to put the size of the message
out << message; // adding the message
out.device()->seek(0); // coming back to the head of the paquet
out << (quint16) (paquet.size() - sizeof(quint16)); // replace the 0 value by the real size
clientSocket->write(paquet); //sending...
}
This slot is called every time a single paquet is received.
void Server::dataReceived()
{
forever
{
// 1 : a packet has arrived from any client
// getting the socket of that client (recherche du QTcpSocket du client)
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
if (socket == 0)
return;
QDataStream in(socket);
if (dataSize == 0) // if we don't know the size of data we are suppose to receive...
{
if (socket->bytesAvailable() < (int)sizeof(quint16)) // we haven't yet receive the size of the data completly then return...
return;
in >> dataSize; // now we know the amount of data we should get
}
if (socket->bytesAvailable() < dataSize)
return;
// Here we are sure we got the whole data then we can startreadind
QString message;
in >> message;
//Processing....
dataSize = 0; // re-initialize for the coming data
}
}
This is working well when the server is talking with the Qt app Client, because the same methods are used there, and the size of quint16 will remain the same hover it doesn't work with android client, then i tried another way in which i wanted to ignore the size of the message sent, but format the message in a way such that i can know where it starts and where it ends, then with some controls i can get it however i'm stuck here, cause the data read doesn't contain anything when printed, but his size has a value(which even vary according to the amount of text the client send)!
void Server::dataReceived() // a packet is received!
{
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
if (socket == 0)
return;
QByteArray data= socket->readAll(); //reading all data available
QString message(data)
qDebug() << data; // this prints nothing!
qDebug() << data.size();// But this prints a non null number, wich means we got something, and that number varies according to the amount of text sent!
qDebug() << message; // this also prints notghing!
}
PS: it's not working even for the Qt app Client.
Can you help me find out what's wrong, i'm a bit confused how the tcp protocol is handling the data, and if you could and also advise me a good way for doing this.
here is the android class I made for the purpose
class QTcpSocket implements Runnable {
private String ip="";
private int port;
private Socket socket;
private PrintWriter printWriter;
private DataOutputStream dataOutputStream;
private DataInputStream dataInputStream;
public QTcpSocket(String ip, int port) {
this.ip = ip;
this.port = port;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getIp() {
return this.ip;
}
public void setPort(int port) {
this.port = port;
}
public void run() {
try {
socket = new Socket(this.ip, this.port);
dataOutputStream = new DataOutputStream( socket.getOutputStream() );
dataInputStream = new DataInputStream(socket.getInputStream());
String response = dataInputStream.readUTF();
dataOutputStream.writeUTF("Hello server!");
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String message) {
try {
dataOutputStream.writeUTF(message);
}catch (IOException e) {
e.printStackTrace();
}
}
public void disconnect() {
try {
printWriter.flush();
printWriter.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean isClosed() {
return socket.isClosed();
}
}
Replace in 'data' all bytes with value 0 by value 20 and print again. I think you see nothing printed because the first byte is 0. You could also replace with 'X'. Did you already replace writeUTF() by write() ?
20 is the space character. But then you also see nothing printed so better use a X char. Strings get printed until a \0 char (which indicates the end of a string) is met. Because nothing was printed i supposed one right at the beginning. So writeUTF causes that leading 0. I could only explain that if all chars had doubled. What was the first char you sent?
But now: send size-of-message first so it equals your qt client.

Android VpnService: Reading from Tun device hangs

My app is using VpnService for traffic interception.
What it does:
1.Reads from Tun device in a loop:
while (started && tunDevice.valid()) {
final byte[] bytes = tunDevice.read();
IpPacket packet = PacketFactory.createPacket(bytes);
if (packet == null) {
Thread.yield();
} else {
proxyService.handlePacket(packet);
}
}
TunDevice.read:
#Override
public byte[] read() throws IOException {
if (!valid()) {
LOG.warn("TUN: file descriptor is not valid any more");
return null;
}
int length = tunInputStream.read(readBuffer);
LOG.debug("TUN: Received packet length={}", length);
if (length < 0) {
throw new IOException("Tun device is closed");
}
if (length == 0) {
return null;
}
return Arrays.copyOfRange(readBuffer, 0, length);
}
2.Proxifies data to the protected socket.
The problem is that after some time it stops reading from TUN device.
Read method just hangs and waits for some time (like 3-5 minutes).
Using netstat I see that all new connections are in SYN_SENT state and I can understand why - they cannot receive ACK from my code because I cannot receive these SYN packets.
The question is: what could it be? When TUN device could behave like this?
In our case the problem was in our TCP implementation.
We have written more data than TCP could receive (advertised window).

Do we need to consume HttpURLConnection's error stream when IOException thrown

According to technical guide from Oracle Java, we should consume HttpURLConnection's error stream when IOException thrown
http://docs.oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html
What can you do to help with Keep-Alive? Do not abandon a connection
by ignoring the response body. Doing so may results in idle TCP
connections. That needs to be garbage collected when they are no
longer referenced.
If getInputStream() successfully returns, read the entire response
body.
When calling getInputStream() from HttpURLConnection, if an
IOException occurs, catch the exception and call getErrorStream() to
get the response body (if there is any).
Reading the response body cleans up the connection even if you are not
interested in the response content itself. But if the response body is
long and you are not interested in the rest of it after seeing the
beginning, you can close the InputStream. But you need to be aware
that more data could be on its way. Thus the connection may not be
cleared for reuse.
Here's a code example that complies to the above recommendation:
Here's the code example
try {
URL a = new URL(args[0]);
URLConnection urlc = a.openConnection();
is = conn.getInputStream();
int ret = 0;
while ((ret = is.read(buf)) > 0) {
processBuf(buf);
}
// close the inputstream
is.close();
} catch (IOException e) {
try {
respCode = ((HttpURLConnection)conn).getResponseCode();
es = ((HttpURLConnection)conn).getErrorStream();
int ret = 0;
// read the response body
while ((ret = es.read(buf)) > 0) {
processBuf(buf);
}
// close the errorstream
es.close();
} catch(IOException ex) {
// deal with the exception
}
}
Does this applicable to Android platform? As I don't see such technique in most of the Android code example.
If you are not interested in displaying the error message to the user, close the InputStream or invoke disconnect on HttpURLConnection in finally block without reading the error message. This is what you see in most of the examples.
I came across following comment in one of the source code, while browsing the implementation of HttpURLConnection. That could be the reason why connections are closed without reading all data.
This should be invoked when the connection is closed unexpectedly to
invalidate the cache entry and to prevent the HTTP connection from
being reused. HTTP messages are sent in serial so whenever a message
cannot be read to completion, subsequent messages cannot be read
either and the connection must be discarded.
According to Android's implementation of HttpURLConnection, in case of exception:
If error is not read and the InputStream is closed, the connection will be considered as not reusable and closed down.
If you read the error and then close the InputStream, connection is considered as reusable and is added to the connection pool.
You can see in the below image, variable connection & connectionReleased are set to null and true respectively, as soon as all data is read. Note that getErrorStream returns the InputStream, so it is valid in exception scenario also.
Code analysis : Let's look at the FixedLengthInputStream one of the specialized InputStream implementation. Here is the close method implementation:
#Override public void close() throws IOException {
if (closed) {
return;
}
closed = true;
if (bytesRemaining != 0) {
unexpectedEndOfInput();
}
}
Instance variable bytesRemaining contains byte count still available on the InputStream to be read. Here is the unexpectedEndOfInput method implementation:
protected final void unexpectedEndOfInput() {
if (cacheRequest != null) {
cacheRequest.abort();
}
httpEngine.release(false);
}
Here is the release method implementation. Calling disconnect on HttpURLConnection instance leads the call to this release method with false as parameter.
The last if check ensures whether connection need to be closed down or added to the connection pool for reuse.
public final void release(boolean reusable) {
// If the response body comes from the cache, close it.
if (responseBodyIn == cachedResponseBody) {
IoUtils.closeQuietly(responseBodyIn);
}
if (!connectionReleased && connection != null) {
connectionReleased = true;
// We cannot reuse sockets that have incomplete output.
if (requestBodyOut != null && !requestBodyOut.closed) {
reusable = false;
}
// If the headers specify that the connection shouldn't be reused, don't reuse it.
if (hasConnectionCloseHeader()) {
reusable = false;
}
if (responseBodyIn instanceof UnknownLengthHttpInputStream) {
reusable = false;
}
if (reusable && responseBodyIn != null) {
// We must discard the response body before the connection can be reused.
try {
Streams.skipAll(responseBodyIn);
} catch (IOException e) {
reusable = false;
}
}
if (!reusable) {
connection.closeSocketAndStreams();
connection = null;
} else if (automaticallyReleaseConnectionToPool) {
HttpConnectionPool.INSTANCE.recycle(connection);
connection = null;
}
}
}
The code shared by you, in which the IOException is handled, error stream is read and then closed, ensures the Connection is reusable and is added to the connection pool. The moment all data is read from InputStream the Connection is added to the connection pool. Here is the read method implementation of FixedLengthInputStream :
#Override public int read(byte[] buffer, int offset, int count) throws IOException {
Arrays.checkOffsetAndCount(buffer.length, offset, count);
checkNotClosed();
if (bytesRemaining == 0) {
return -1;
}
int read = in.read(buffer, offset, Math.min(count, bytesRemaining));
if (read == -1) {
unexpectedEndOfInput(); // the server didn't supply the promised content length
throw new IOException("unexpected end of stream");
}
bytesRemaining -= read;
cacheWrite(buffer, offset, read);
if (bytesRemaining == 0) {
endOfInput(true);
}
return read;
}
When bytesRemaining variable becomes 0, endOfInput is called which will futher call release method with true parameter, which will ensures the connection is pooled.
protected final void endOfInput(boolean reuseSocket) throws IOException {
if (cacheRequest != null) {
cacheBody.close();
}
httpEngine.release(reuseSocket);
}
If it's documented for Java it's binding for the Android platform.

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?
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.

Categories

Resources