Error to send data to tablet through bluetooth device - android

I'm facing the following problem:
I am connecting two devices via Bluetooth socket, one tablet android and a bluetooth device like reader barcode, up to now it's ok, the problem is, when a read the barcode by the bluetooth device and I send it to tablet, the bar code sometimes it's sent in two parts, for example, if I read a barcode with content "212154521212", the tablet receive "2121" and after "54521212", Anyone know tell me what should I do to avoid this?
Thanks in advanced.
My code that read the data from bluetooth device:
[code]
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private BluetoothSocket socket;
public ConnectedThread(BluetoothSocket socket) {
this.socket = socket;
InputStream tmpIn = null;
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
new LogDeErrosRodesTablet(e);
Log.e(TAG, e.getMessage());
Log.e(TAG, "Erro no construtor da classe ConnectedThread.");
}
mmInStream = tmpIn;
}
public void run() {
// continua lendo o inputstream até ocorrer um erro
while (true) {
int read = 0;
byte[] buffer = new byte[128];
do {
try {
read = mmInStream.read(buffer);
Log.e(TAG, "read: " + read);
final String data = new String(buffer, 0, read);
Log.e(TAG, "data: " + data);
//TODO
//send data only (bar code) only after read all
Bundle bundle = new Bundle();
bundle.putString(TelaInserirPedido.CODIGO_BARRAS, data);
Message message = new Message();
message.what = TelaInserirPedido.MSG_COD_BARRAS;
message.setData(bundle);
//Send a message with data
handler.sendMessage(message);
} catch(Exception ex) {
read = -1;
return;
}
Log.e(TAG, "inside while.");
} while (read > 0);
Log.e(TAG, "outside of while.");
}
}
public void cancel () {
try {
socket.close ();
} catch ( IOException e) { }
}
}
[/code]

This isn't a Bluetooth error. The Bluetooth device is sending all of the data to your application, but you are reading the stream before all of the data have been received. You could check for the amount of bytes available() on the stream before reading, if you know the exact length of the data; you could concatenate the results of all of the reads until you reach a known end point. Or you could put in an arbitrary time delay and hope the transmission completed in that time.
You would create the Bundle and Message after the while loop that collects the input string, because you don't know the entire string until that loop finishes. (Unless you are expecting multiple strings in one connection, in which case you need more complex code to handle partial numbers).

Use OutputStream.flush() to force send the all data.

Related

Sending a photo from a device using Python3 and receiving it on an Android Device via TCP gives an OOM on the Android Device

I am trying to send a photo from my Raspberry Pi using Python 3, to my Android Device. I am doing this over TCP with the Pi as the Client, and the Android Device as my Server. My goal is to send a photo file from Pi to my Android Device. My Android Device would then decode that photo data and then set it as the drawable for an ImageView in my App. Kindly note that I'm sending a 200kB image that's 640x480.
I have tried a set up where the Pi sends text to my Android Device via TCP, and I've had success with that.
What I did next was to attempt to send a photo from a Python3 client to a Python3 Server. In this case, I used the Pi still as my client, and I used my MacOS Laptop as the Server. This are the code that I ended up using.
Server - MAC OS
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 11111 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
f = open('torecv.jpg','wb')
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print('Got connection from', addr)
print("Receiving...")
l = c.recv(1024)
while (l):
print("Receiving...")
f.write(l)
l = c.recv(1024)
f.close()
print("Done Receiving")
c.send(b'Thank you for connecting')
c.shutdown(socket.SHUT_RDWR)
c.close() # Close the connection
Client - Pi
import socket # Import socket module
import os
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
host = '192.168.254.194' # Get local machine name
port = 6001 # Reserve a port for your service.
CWD_PATH = os.getcwd()
PATH_TO_IMG_DIR = os.path.join(CWD_PATH, 'img_folder', 'test.jpg')
s.connect((host, port))
#s.send(b'Hello Server!')
f = open(PATH_TO_IMG_DIR,'rb')
print('Sending...')
l = f.read(1024)
while (l):
print('Sending...')
s.send(l)
l = f.read(1024)
f.close()
print("Done Sending")
s.shutdown(socket.SHUT_WR)
print(s.recv(1024))
s.close # Close the socket when done
Using this code, I was able to transfer the photo from my Pi to my MacOS laptop.
Now, I used the code here as reference in order to transfer my photo from my Pi to my Android Device. Now, this is my code:
Server - Android
class ServerThread implements Runnable {
public void run() {
Socket socket;
try {
Log.e(TAG, "starting the serverthread at port 6001");
serverSocket = new ServerSocket(6001);
} catch (IOException e) {
Log.e(TAG, "exception in creating server socket: ", e);
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (IOException e) {
}
}
}
}
class CommunicationThread implements Runnable{
private Socket clientSocket;
private DataInputStream input;//private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
Log.e(TAG, "getting data from the input stream!");
//this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
InputStream in = this.clientSocket.getInputStream();
this.input = new DataInputStream(in);
} catch (IOException e) {
Log.e(TAG, "error in creating data input stream: ", e);
e.printStackTrace();
}
}
public void run() {
Log.e(TAG, "running the code!");
while (!Thread.currentThread().isInterrupted()) {
try {
Log.e(TAG, "parsing the input data stream!");
byte[] data;//String read = input.readLine();
int len= this.input.readInt();
if (len > 0) {
data = new byte[len];
this.input.readFully(data,0,data.length);
}
/*
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] data;
int length = 0;
while ((length = this.input.read(data))!=-1) {
out.write(data,0,length);
}
data=out.toByteArray();
*/
Log.e(TAG, "Updating the UI through a thread!!");
// updateConversationHandler.post(new updateUIThread(data));
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(TAG, "error in reading sent data! ", e);
e.printStackTrace();
}
}
}
}
And in order to use these classes, I had declared the following as global variables:
Thread serverThread = null;
Handler updateConversationHandler;
And in my onCreate(), I have the following:
updateConversationHandler = new Handler();
this.serverThread = new Thread(new ServerThread());
this.serverThread.start();
The app would start, and the socket would be opened. However, when I attempt to send in the photo from my Pi, I hit an error at this block of code:
public void run() {
Log.e(TAG, "running the code!");
while (!Thread.currentThread().isInterrupted()) {
try {
Log.e(TAG, "parsing the input data stream!");
byte[] data;//String read = input.readLine();
int len= this.input.readInt();
if (len > 0) {
data = new byte[len];
this.input.readFully(data,0,data.length);
}
/*
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] data;
int length = 0;
while ((length = this.input.read(data))!=-1) {
out.write(data,0,length);
}
data=out.toByteArray();
*/
Log.e(TAG, "Updating the UI through a thread!!");
// updateConversationHandler.post(new updateUIThread(data));
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(TAG, "error in reading sent data! ", e);
e.printStackTrace();
}
}
}
class updateUIThread implements Runnable {
private byte[] byteArray;//private String msg;
public updateUIThread(byte[] array){ //public updateUIThread(String str) {
this.byteArray=array; //this.msg = str;
}
#Override
public void run() {
Log.e(TAG, "running the photo update!");
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray , 0, byteArray .length);
ivBed.setImageBitmap(bitmap);//text.setText(text.getText().toString()+"Client Says: "+ msg + "\n");
}
}
Originally, the line:
data = new byte[len];
was outside the if(len>0) condition. But what happened was, for some reason, the Pi sent in a negative value, and of course we don't want a negative value for the len variable. Of course, I hit an error when I tried to create the byte array data with a negative length. I then put that line in the if condition.
However, after I did, I hit on OOM Error in the same line data = new byte[len];
Process: agict.work.freelance.patientsensor, PID: 15224
java.lang.OutOfMemoryError: Failed to allocate a 1677608328 byte allocation with 6291456 free bytes and 254MB until OOM, max allowed footprint 7797480, growth limit 268435456
I have a hunch that in the 2nd error, I was trying to initialize the byte array with a value that was actually the image data already, hence, the OOM error.
However, if I just take in the first value and assign it as the len, there's a chance that I'd get a negative number and the code would hit the first error.
Would there be a chance that I have to tweak something in order to transfer a photo data from Python3 to Android? I have a feeling that there's a format mismatch of sorts that's happening.
Again, my goal is to send a photo file from Python3 to my Android Device via TCP. The Python3 will be given a file, and the Android Device will decode the input it gets, and once decoded, use that data as the drawable for an ImageView.
According to me that error is caused by the size of the bitmap that you are trying to set for the ImageView. Checking sizes before use and/or scaling the bitmap may solve the issue. I've encountered such problems in the past before I start using third party libraries to load images.
You can take a look at this article from Android Developers and I think it can help:
https://developer.android.com/topic/performance/graphics/load-bitmap#java
I got it. You're supposed to use a ByteArrayOutputStream Object.
class ServerImageThread implements Runnable{
ServerSocket ss;
Socket s;
DataInputStream dis;
byte[] data;
#Override
public void run(){
try{
ss = new ServerSocket(6001);
while(true){
s = ss.accept();
InputStream in = s.getInputStream();
dis = new DataInputStream(in);
// read from the stream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] content = new byte[1024];
int bytesRead = -1;
while( (bytesRead = in.read(content)) != -1 ) {
baos.write( content, 0, bytesRead );
} // while
Log.e(TAG, "made it through!");
Log.e(TAG, "baos size is = " + baos.size());
File file = new File(
Environment.getExternalStorageDirectory(), "test.jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
baos.writeTo(fos);
Log.e(TAG, "managed to write baos to fos");
} catch(IOException ioe) {
// Handle exception here
Log.e(TAG, "baos IOException = ", ioe);
ioe.printStackTrace();
} finally {
Log.e(TAG, "closing fos");
fos.close();
}
}
}
catch(IOException e) {
Log.e(TAG, "exception in creating server socket: ", e);
e.printStackTrace();
}
}
}
You can call this via:
Thread myThread = new Thread(new ServerImageThread());
myThread.start();

Arduino send data to Android using HC-05

What I have :
HC-05 Bluetooth module
Arduino promini
BPM sensors
Android studio 3.0
What I have done :
Connect the Arduino, sensors, and HC-05 bluetooth using Serial
Send the data from Arduino script
Recieve and get the data using 3rd party apps from playstore
What I wanted to do :
Get the data from arduino's to be showed in the android text view, using native coded apps (not the one from the store) using android studio.
My current code :
Arduino script :
loop(){
Serial.println("*"+String(BPM)+"#"); //BPM from sensor
delay(200)
}
And some code for connecting and pairing using Android Bluetooth Adapter, which I can't showed here full because still hard coded, but the point is :
I made a handler, which recieves incoming inputs from the serial, and at least showing them on Toast component, but still haven't managed to make it work.
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE:
Toast.makeText(getApplicationContext(),"Data in",Toast.LENGTH_SHORT
).show();// if receive massage
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,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length()); // and clear
sensorView0.setText("Data from Arduino: " + sbprint); // update TextView
btnOff.setEnabled(true);
btnOn.setEnabled(true);
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
I also have a class :
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket 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();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[256]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
Toast.makeText(getApplicationContext(),"Masuk ke handler private class",Toast.LENGTH_SHORT
).show();
// Read from the InputStream
bytes = mmInStream.read(buffer); // Get number of bytes and message in "buffer"
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
} catch (IOException e) {
break;
}
}
}
}
Which I think calls for the handler to read the message, but haven't managed to make it work.
I wanted to at least show the message to the Toast, or TextView, but haven't got a clear answer this last 3 weeks.
So anyone who can help will be appreciated.

Bluetooth update UI thread

I am writing an embedded application for Infineon XMC4500 microprocessor.
I read data from different sensors and I send this data by means of bluetooth module in order to visualize them on the screen of Android smarphone. I use GraphView library.
I implemented BluetoothClass according to Android tutorial. If I get data from single sensor then everything is ok. But when I get data from multiple sensors unfortunately my application does not work smoothly.
Of course I am doing Bluetooth connection in seperate thread and I try to update UI in Handler.
Tell me please what am I doing wrong. Of course I send data by means of JSON exchange format:
I send something like this from the microcontroller side:
sprintf(json_data, "{"
"\"m\":"
"["
"{"
"\"id\":a,"
"\"x\":%.2f,"
"\"y\":%.2f,"
"\"z\":%.2f"
"},"
"{"
"\"id\":g,"
"\"x\":%.2f,"
"\"y\":%.2f,"
"\"z\":%.2f"
"},"
"{"
"\"id\":m,"
"\"x\":%.2f,"
"\"y\":%.2f,"
"\"z\":%.2f"
"},"
"{"
"\"id\":t,"
"\"x\":%.2f"
"},"
"{"
"\"id\":h,"
"\"x\":%.2f"
"}"
"]"
"}", getAccelXf(), getAccelYf(), getAccelZf(), getGyroXf(), getGyroYf(), getGyroZf(), getMagnetXf(), getMagnetYf(), getMagnetZf(), readTemperature(), readHumidity());
As an attachment to my request I add pieces of source code:
public class ConnectedThread extends Thread
{
BluetoothSocket connectedSocket;
InputStream inStream;
OutputStream outStream;
public ConnectedThread(BluetoothSocket socket)
{
connectedSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try
{
if (connectedSocket != null)
{
tmpIn = connectedSocket.getInputStream();
tmpOut = connectedSocket.getOutputStream();
mHandler.obtainMessage(Constants.MESSAGE_DEVICE_CONNECTED_SUCCESSFULLY).sendToTarget();
// Toast.makeText(activityContext, "connectedSocket != null", Toast.LENGTH_LONG);
}
}
catch (IOException e) {
mHandler.obtainMessage(Constants.MESSAGE_INPUT_OUTPUT_STREAM_UNAVAILABLE).sendToTarget();
e.printStackTrace();
}
inStream = tmpIn;
outStream = tmpOut;
}
public void run()
{
if(bluetoothAdapter.isDiscovering()){
bluetoothAdapter.cancelDiscovery();
}
byte[] buffer = new byte[4096];
int bytes;
String dupa;
while (true)
{
try {
if (inStream != null)
{
bytes = inStream.available();
if(bytes > 0 && bytes <= 200)
{
byte[] pocketBytes = new byte[bytes];
inStream.read(pocketBytes);
//Log.d(TAG, "setState() " + mState + " -> " + state);
System.out.println(pocketBytes.toString());
dupa = pocketBytes.toString();
System.out.println(dupa);
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, pocketBytes).sendToTarget();
}
}
} catch (IOException e) {
mHandler.obtainMessage(Constants.MESSAGE_REMOTE_DEV_DISCONNECTED).sendToTarget();
break;
}
/*try
{
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
outStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
connectedSocket.close();
} catch (IOException e) { }
}
}
}
And after that I try to update UI in the Handler.
This is link to sample of my application:
https://www.youtube.com/watch?v=_Buv64vADNk&feature=youtu.be
It does not work smoothly, morever sometimes it does not respond.
Could you please tell me what am I doing wrong ? Thx in advance.
Mateusz; Look into operational blocks force your code into the background at a lower priority that the UI code. You can also try GCD. Here a very simple block of code, spun off as a separate process.
How to determine when all images have been downloaded from a set in Swift?
Put the UI code at the highest priority and bluetooth at the lowest; making double sure the only statements you put into UI updates are doing that, don't put anything there that isn't updating the UI.

Understanding bluetooth rfcoom raw data

I'm trying to build an application that reads information sent on a bluetooth service using rfcomm.
The device is an hardness tester (HT-6510A), unfortunalty specs about the device data format can't be found I'm faced with a strange problem, I've to understand how to read these information.
01-11 17:47:28.940 11862-13447/joinstore.it.testhardness V/result: ��S
01-11 17:47:29.581 11862-13447/joinstore.it.testhardness V/result: ��S
01-11 17:47:30.211 11862-13447/joinstore.it.testhardness V/result: ��S
01-11 17:47:30.872 11862-13447/joinstore.it.testhardness V/result: ��S
01-11 17:47:31.513 11862-13447/joinstore.it.testhardness V/result: ��S
01-11 17:47:32.143 11862-13447/joinstore.it.testhardness V/result: ��T
01-11 17:47:32.794 11862-13447/joinstore.it.testhardness V/result: ��T
This is the data I receive from the device, I don't think there's something wrong with the implementation tha simply uses this thread after stabilizing a rfcomm connection.
//After connection, handle data transfer
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
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();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
// readAndPublishRaw();
readAndPublishString();
Log.v("result", "Reading data ended.");
setStatusText(-1);
}
void readAndPublishRaw(){
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
Log.v("result", "Start reading...");
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
Log.v("result", bytes + "");
} catch (IOException e) {
break;
}
}
}
void readAndPublishString(){
//String method, not useful in this case?
try {
BufferedReader r = new BufferedReader(new InputStreamReader(mmInStream));
StringBuilder total = new StringBuilder();
String line;
Log.v("result", "Start reading...");
while ((line = r.readLine()) != null) {
total.append(line);
Log.v("result", line);
}
Log.v("result", total.toString());
//TODO publish read string to the view
} catch (Exception e) {
//
try {
mmSocket.close();
}catch (Exception ex){}
Log.v(TAG, "exception reading data from service");
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
setStatusText(-1);
} catch (IOException e) {
}
}
}
Can you guys give me any information about how to correctly parse this raw data? I think I should have a stream of float values, but instead I've just this random stuff.
Suggestion on how to get some usable log output first:
void readAndPublishRaw(){
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
Log.v("result", "Start reading...");
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
final StringBuilder sb = new StringBuilder();
sb.append("Received ").append(bytes).append(" bytes: ");
for ( int i = 0; i < bytes; i++ ) {
sb.append( Integer.toHexString(((int)buffer[i]) & 0xff) ).append(", ");
}
Log.v("result", sb.toString());
} catch (IOException e) {
break;
}
}
}
The next step should be to calibrate the data, i.e. make note of which input/display value yields what raw data. From there, you may or may not be able to infer the actual encoding.
Your device may or may not include other information besides the actual measurement in the data, e.g. to indicate a low battery. That would have to be factored out to get raw measurement values.
If one data value comprises more than one byte the byte-order (little- or big-endian) needs to be determined.
Often floating point data of small devices is represented in a fixed point representation. Sometimes, esp. if negative numbers are needed too, with an offset added, so that
realValue = rawValue * a + c
If you find out a and c you're good. Hence, once you can relate only two different realValues and corresponding rawValues from the calibration done above, you have enough data to solve the equation for a and c.
Devices with a little more "punch", embedded linux devices for instance, may also use regular IEEE floating point data. - Not that small embedded devices cannot use IEEE, but floating point is often more than is required and comes at the price of higher complexity (memory & CPU) for the floating point emulation code.

Sending String via Bluetooth , I need some information

I'm working on an application which should be quite the same as Bluehood, an application which is on the google market .
So now I'm working on Bluetooth . The fact is, I want to transfer strings (JSON) between two devices . I've seen lots of posts on stackoverflow and some examples on the internet but it's not so clear for me .
I know that I've to use createInsecureRfcommSocketToServiceRecord for sending informations and listenUsingInsecureRfcommWithServiceRecord for receiving them , but I'm searching some simple tutorial to explain how it works and how to transfer data between two devices .
Thank in advance for your explanations...
It's hard to know if I am answering this effectively, as you say you have searched the web and I find one of the most useful tutorials at android com on Bluetooth. I have supplied parts of the code, not the full thread classes, but the bones to give you an idea of how temp sockets are used until sockets are found and made final, for the duration of the connection, and how threads manage each stage of the connection process.
listenUsingRfcommWithServiceRecord(NAME, MY_UUID); is used to create a server socket. It listens for a connection. It acts like a server. This is on the device that is acting as a server or listening for incoming connections.
This is done is a separate thread.
public AcceptThread() {
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) {
}
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (BluetoothConnection.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice());
break;
case STATE_NONE:
case STATE_CONNECTED:
// Either not ready or already connected. Terminate new socket.
try {
socket.close();
} catch (IOException e) {
}
break;
}
}
}
}
}
There is a separate thread to act as a client, seeking a connection. It goes looking for a connection. This is on the device that seeks the connection with the server device. (These can be interchangeable).
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
}
mmSocket = tmp;
}
public void run() {
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
}
connectionFailed();
return;
}
You then need a thread to manage the actual connection. When the client meets the server. Also in a separate thread.
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
connectionLost();
// Start the service over to restart listening mode
BluetoothConnection.this.start();
break;
}
}
}
Within this thread you also have your code to manage writing data through this connection.
There are samples supplied through android.com.
I also found this tutorial good, as a simple background into bluetooth discovery and connection, although it doesn't give you all you need to read and write data.
In terms of reading and writing the data, the following snippet is an example of a way to handle reading data and parsing it to something usable. Calling the handler from within the connection thread. In this case I am appending the data to a textView, but you can do whatever you want with it, it shows how to put it into a String. (which is what you are looking for).
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
textView1.append("\nMessage " + messageCount + ": " + readMessage);
....
Likewise there is some code to write messages - this is in the connected thread class. However, I grab this information using an OnClick event with the button to send. Grab the text from the EditText and send it to a function to parse the String to bytes.
where message is a String and mChatService is calling the write method from the Connected thread.
Converting the string to a byte array, so it can be sent.
// Get the message bytes and tell the BTManager to write
byte[] send = message.getBytes();
mChatService.write(send);
Write method from connected thread:
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
} catch (IOException e) {
}
}
It is worth noting that the states of the devices must be monitored (you can have a look a the tutorial for that).
It is also important to keep the background threads away from the UI. So that is where the skill comes in (and a handler) to transfer data to and from the UI to the socket connection.

Categories

Resources