Bluetooth socket, write and read strings - android

How can I output and read strings over a bluetooth socket. Right now it prints the value of the bytes being sent which is the number of character 0-255. So 'hi' would be 2, 'bye' would be 3. Here is my read and write functions:
public void read() {
byte buffer[] = new byte[1024];
final int bytes;
try {
bytes = iStream.read(buffer);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
updateTView(bytes);
}
});
Log.i("WTF",String.valueOf(bytes));
} catch(IOException e) {
//TODO: something
}
}
public void writeText(byte bytes[]) {
try {
oStream.write(bytes);
} catch(IOException e) {
//TODO: something
}
}

private InputStream input;
Perform this in background thread.
byte[] buffer = new byte[1024];
bytes = input.read(buffer);
String readMessage = new String(buffer, 0, bytes);
// Send the obtained bytes to the UI Activity
System.out.println(readMessage);

Related

How to receive a complete arduino string in android

I am doing an app for my arduino sensor I wanted to know how to actually obtain the data from arduino to android studio via bluetooth because in my arduino I put Serial.println("occupied") but when receive in android it somehow mixed with some numbers/bytes like "o2cuppied" or else it will receive seperately in logcat. I don't know what is wrong with it.
Arduino Code:
void setup() {
serial1.begin(9600); //for the bluetooth module
}
void loop() {
//send data to Bluetooth module//
if (dist[0] < dist_threshold) {
serial1.print("Occupied\n");
}
if (dist[1] < dist_threshold) {
serial1.print("Occupied2\n");
}
Android
#Override
protected void onCreate(Bundle savedInstanceState) {
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECEIVE_MESSAGE: // if receive massage
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
// and clear
txtArduino.setText("Data from Arduino: " + strIncom);
break;
}
}
};
}
private class ConnectedThread extends Thread {
private final BluetoothSocket bluetoothSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
bluetoothSocket = socket;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer); // Get number of bytes and message in "buffer"
String incomingMessage = new String(buffer, 0, bytes);
Log.d(TAG, "InputStream: " + incomingMessage);
h.obtainMessage(RECEIVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
} catch (IOException e) {
Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
break;
}
}
}
}
Logcat
2019-11-27 12:28:13.505 12733-12893/com.example.fyp D/MainActivity: InputStream: O
2019-11-27 12:28:13.508 12733-12893/com.example.fyp D/MainActivity: InputStream: ccupied
private StringBuilder sb = new StringBuilder();
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length());
final String finalSbprint = sbprint;
TCP: You have to concatenate the incoming bytes.
But if the Arduino is only going to send text you can make your life easier by letting it send "Occupied\n" instead of "Occupied".
On the receiving side you add a BufferedStreamReader and use its readLine() member to read that line.

Socket recieves Images with delay of 1

I have a socket that recieves images via one InputStream that doesnt get closed. I want to send images continiously that way. But now the images get recieved with a delay of 1 image (the first one after I sent the second one, the second one after I sent the third one, ....). What am I doing wrong?
Server
public static void readImages(InputStream stream) throws IOException {
stream = new BufferedInputStream(stream);
BufferedImage image = null;
int j = 0;
while (true) {
stream.mark(MAX_IMAGE_SIZE);
ImageInputStream imgStream = ImageIO.createImageInputStream(stream);
Iterator<ImageReader> i = ImageIO.getImageReaders(imgStream);
if (!i.hasNext()) {
System.out.println("No more image readers");
break;
}
ImageReader reader = i.next();
reader.setInput(imgStream);
image = reader.read(0);
ImageIO.write(image,"jpg",new File("current" + j + ".jpg"));
System.out.println("Save an image " + j);
if (image == null) {
System.out.println("Image is null");
break;
}
long bytesRead = imgStream.getStreamPosition();
stream.reset();
stream.skip(bytesRead);
j++;
}
}
Client
new Thread(new Runnable() {
#Override
public void run() {
try {
OutputStream outputStream = server.getOutputStream();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmapToSend = Bitmap.createScaledBitmap(bitmapToSend, 900, 800, true);
bitmapToSend.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
outputStream.write(byteArray);
outputStream.flush();
} catch (IOException e) {
System.out.println("Socket not created");
e.printStackTrace();
}
}
}).start();
Note I dont close the output stream of the client, so I can send pictures all the time.
Using ImageIO.getImageReaders(imgStream) doesn't seem logical for socket streams, since it probably expects all images to be available at once. That may be the reason of your delay.
Secondly, for decompressing images there is a simple method BitmapFactory.decodeStream().
Thirdly, since client already creates a "JPG" format, the server just needs to store it. You only need to send at start the number of bytes and zero after all files have been sent.
Client:
new Thread(new Runnable() {
#Override
public void run() {
try {
ByteArrayOutputStream memoryStream = new ByteArrayOutputStream();
Bitmap bitmapToSend =
Bitmap.createScaledBitmap(bitmapToSend, 900, 800, true);
bitmapToSend.compress(
Bitmap.CompressFormat.JPEG,100, memoryStream);
byte[] byteArray = memoryStream.toByteArray();
memoryStream = null;
DataOutputStream outputStream =
new DataOutputStream(server.getOutputStream());
outputStream.writeInt(byteArray.length);
outputStream.write(byteArray);
outputStream.flush();
} catch (IOException e) {
System.out.println("Socket not created");
e.printStackTrace();
}
}
}).start();
Server:
public static void readImages(InputStream stream) {
DataInputStream imgInput = new DataInputStream(stream);
int index = 0;
int byteLength;
try {
while ((byteLength = imgInput.readInt())>0) {
byte[] buffer = new byte[byteLength];
imgInput.readFully(buffer);
OutputStream imgOutput = new FileOutputStream("current" + (index++) + ".jpg");
imgOutput.write(buffer);
imgOutput.close();
}
} catch (IOException ex) {
// .............
} finally {
try {
imgInput.close();
} catch (IOException ex1) {
//...........
}
}
}

Xamarin Bluetooth InputStream not reading all the bytes (sometime)

I used this code to read the reply of a Bluetooth not LE device.
The solution is a Xamarin Forms project and the code is in the DependencyService.
using Android.Bluetooth;
....
public byte[] GetCommand()
{
byte[] rbuffer = new byte[200];
try
{
// Read data from the device
while (!_socket.InputStream.CanRead || !_socket.InputStream.IsDataAvailable())
{
}
int readByte = _socket.InputStream.Read(rbuffer, 0, rbuffer.Length);
}
catch (Java.IO.IOException e)
{
}
return rbuffer;
}
How is it possible to solve it?
I would use the following code instead:
//create new class for connect thread
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
//creation of the connect thread
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
//Create I/O streams for connection
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[256];
int bytes;
// Keep looping to listen for received messages
while (true) {
try {
bytes = mmInStream.read(buffer); //read bytes from input buffer
String readMessage = new String(buffer, 0, bytes);
// Send the obtained bytes to the UI Activity via handler
bluetoothIn.obtainMessage(handlerState, bytes, -1, readMessage).sendToTarget();
} catch (IOException e) {
break;
}
}
}
//write method
public void write(String input) {
byte[] msgBuffer = input.getBytes(); //converts entered String into bytes
try {
mmOutStream.write(msgBuffer); //write bytes over BT connection via outstream
} catch (IOException e) {
//if you cannot write, close the application
Toast.makeText(getBaseContext(), "Connection Failure", Toast.LENGTH_LONG).show();
finish();
}
}
}
This is working for me to get bluetooth information from an Arduino! :)

I cannot cancel my thread in Android

I am developing an app that communicated with Arduino via bluetooth, however, I dont know why I cannot cancel the thread which responsible for the bluetooth inputstream.
public class mainclass extends Activity{
BluetoothSocket scSocket = AnotherClass.btSocket;
SendReceiveBytes sendReceiveBT;
Thread th;
protected void onCreate(Bundle savedInstanceState) {
.
.
sendReceiveBT = new SendReceiveBytes(scSocket);
th = new Thread(sendReceiveBT);
th.start();
.
.
sendReceiveBT.stop=true;
Log.e(TAG, "Request sent");
.
.
}
}
public class SendReceiveBytes implements Runnable {
public static final int MESSAGE_WRITE = 1;
public static final int MESSAGE_READ = 2;
String readMessage="";
private BluetoothSocket btSocket;
private InputStream btInputStream = null;
private OutputStream btOutputStream = null;
public boolean stop=false;
public boolean stopped=false;
String TAG = "SendReceiveBytes";
public SendReceiveBytes(BluetoothSocket socket) {
btSocket = socket;
try {
btInputStream = btSocket.getInputStream();
btOutputStream = btSocket.getOutputStream();
}
catch (IOException streamError) {
Log.e(TAG, "Error when getting input or output Stream");
}
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (!stop) {
try {
// Read from the InputStream
bytes = btInputStream.read(buffer);
// Send the obtained bytes to the UI activity
byte[] readBuf = (byte[]) buffer;
// construct a string from the valid bytes in the buffer
readMessage = new String(readBuf, 0, bytes);
}
catch (IOException e) {
Log.e(TAG, "Error reading from btInputStream");
break;
}
}
Log.e(TAG, "Quit");
stopped=true;
}
}
In the LogCat, the tag with "Request sent" is shown which means I already set the "stop" to true, however, the tag with "Quit" never show up.
You could try to override the stop()-method, which set stop-flag to true. Also make sure to close your streams.

why android only receive 2896 bytes on c# tcp socket?

c# Use tcp socket Send message to Android:
string data = "my message....";
byte[] msg = Encoding.UTF8.GetBytes(data);
//for example msg Length is 5210 bytes
client.socket.SendBufferSize = 500000;
socket.Send(msg, msg.Length, SocketFlags.None);
Android receive message from c# server-side:
socket = new Socket(ServerIP, ServerPort);
socket.setReceiveBufferSize(500000);
isReceive = true;
receiveThread = new ReceiveThread(socket);
receiveThread.start();
private class ReceiveThread extends Thread{
private InputStream inStream = null;
ReceiveThread(Socket socket){
inStream = socket.getInputStream();
}
#Override
public void run(){
while(isReceive){
byte[] buffer = new byte[99999];
try {
//only receive 2896 bytes?
int size = inStream.read(buffer);
} catch (IOException e) {
unConnSocket();
}
}
}
}
why the size only receive 2896 bytes?
Your Android code has no way of knowing how many bytes the C# code is sending. inStream.read() is reading only the bytes that are currently available on the socket at that moment. You should have the C# code send the string length before sending the string data, so that the Android code knows how many bytes to expect, eg:
string data = "my message....";
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
int dataLen = IPAddress.HostToNetworkOrder(dataBytes.Length);
byte[] dataLenBytes = BitConverter.GetBytes(dataLen);
socket.Send(dataLenBytes);
socket.Send(dataBytes);
private class ReceiveThread extends Thread
{
private DataInputStream inStream = null;
ReceiveThread(Socket socket)
{
inStream = new DataInputStream(socket.getInputStream());
}
#Override
public void run()
{
while (isReceive)
{
try
{
String s;
int size = inStream.readInt();
if (size > 0)
{
byte[] buffer = new byte[size];
inStream.readFully(buffer);
s = new String(buffer, "UTF-8");
}
else
s = "";
// use s as needed ...
}
catch (IOException e)
{
unConnSocket();
}
}
}
}
Because TCP is a byte stream protocol and isn't obliged to deliver you more than one byte at a time.
You have to loop.
I quote from Linux man recv(2):
The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested.

Categories

Resources