i have already get result from thread that running in same activity, but after change activity i cant get that result. is there any way to get that result ?
here my Thread, i get the result from runOnUiThread
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() {
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);
final String s = new String(buffer);
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), s.toString(),
Toast.LENGTH_SHORT).show();
txtcomand.setText(s);
intent.putExtra("ct", s);
}
});
// Send the obtained bytes to the UI activity
// .obtainMessage(MESSAGE_READ, bytes, -1, buffer)
// .sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* 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();
} catch (IOException e) { }
}
}
You could define an interface to communicate between different activitys or classes.
Just create the interface with methods that allow you to pass the data you need.
Then implement it on the receiver activity, when you create your second activity you need to pass the instance of the receiver activity and store it.
Then you can call that method and pass any parameter when you need.
Hope this helps.
I would recommend implementing a Service class instead of using a thread for your socket communication. A Service can run independently of your activities and different activities can communicate with your service in a number of ways.
For example i would implement a service and an event bus such as Otto (http://square.github.io/otto/) - its a few lines of code implementation. And then you can send your result without worrying about activities, and you activities/fragments can subscribe to those events. Its the easiest/safest way to communicate in your case, IMO, and you will have a nicely modular system.
Btw if you still want to use your thread, you can just add the event bus and use it for communication.
There are also other ways to pass that data. Interfaces for example, Broadcast receivers...
Related
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.
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.
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.
I am going through a scenario in which I need to receive data from a NON-Android device (say, a PC with Bluetooth Dongle). I need to display my own UI and want to handle the incoming data by my application itself. So is there any good way to achieve this goal.
--Edit
As #Trevor mentioned in his answer, the following para have no meaning, I only understood the fact after a little long study about the topic. Anyway, Thanks for all for there suggestions.
So far I tried with listenUsingRfcommWithServiceRecord(...) and createRfcommSocketToServiceRecord(...) but in this way, we need to run our application in both the devices. Currently its not my case.
--Edit
So, is there any good way to receive data from a NON-Android device?
Thanks in advance...
Your question is a little vague because you haven't explained exactly what problems have occurred when you've tried to connect to whatever Bluetooth device it is you're trying to use. Your second paragraph ("So far I tried with listenUsingRfcommWithServiceRecord(...) and createRfcommSocketToServiceRecord(...) but in this way, we need to run our application in both the devices. Currently its not my case.") doesn't make sense to me.
However, I'm assuming it's a SPP device you're trying to connect to (that is, a Bluetooth to Serial interface, or a USB PC Bluetooth dongle set up with a virual COM port). In this case, you can use the Bluetooth Chat example code pretty much as it is, except for one important change which is to use the SPP UUID:
/** UUID for Serial Port Profile */
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
By the way, if you use the Bluetooth Chat example as the basis of your project, beware of a bug I found in the Bluetooth Chat code which causes received characters to be lost if they're received at anything faster that typing speed. For information on this, refer to my answer given here: Android InputStream dropping first two bytes (modified BluetoothChat)
in android sdk sample take a Look at the BluetoothChat,
you need two thread to communicate the data
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
this.mmDevice = device;
BluetoothSocket tmp = null;
try {
tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(SPP_UUID));
} catch (IOException e) {
e.printStackTrace();
}
mmSocket = tmp;
}
#Override
public void run() {
setName("ConnectThread");
mBluetoothAdapter.cancelDiscovery();
try {
mmSocket.connect();
} catch (IOException e) {
try {
mmSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
connectionFailed();
return;
}
synchronized (PrinterService.this) {
mConnectThread = null;
}
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e("PrinterService", "close() of connect socket failed", e);
}
}
}
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;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e("Printer Service", "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
#Override
public void run() {
while (true) {
try {
if (!encodeData(mmInStream)) {
mState = STATE_NONE;
connectionLost();
break;
} else {
}
// mHandler.obtainMessage(AbstractActivity.MESSAGE_READ,
// bytes, -1, buffer).sendToTarget();
} catch (Exception e) {
e.printStackTrace();
connectionLost();
PrinterService.this.stop();
break;
}
}
}
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.