Android Threads and Asynchronus tasks - java

So I have a thread, lets call it connectedThread it receives data from a input stream (could be anything Bluetooth, wifi, usb serial etc), what I wanted to know is how do I send a interrupt to the thread which causes it hold on until a certain method in the same thread (connectedThread) is finished generating results. See the below pseudo code to help illustrate my point.
Connected Thread:
private class ConnectedThread extends Thread {
//Bluetooth socket just a example could be any input stream.
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; // 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
// Arbitrary size for input stream data buffer.
buffer = new byte[3];
//Send a arbitrary command for device to respond
mmOutStream.write(255);
bytes = mmInStream.read(buffer,0,buffer.length);
/* This is where I want to not hard code a time out but in fact,
* wait for mmInStream.read(buffer,0,buffer.length);
* to finish then immediately proceed
*/
Thread.sleep(87);
// Send the obtained bytes to the message handler
mHandler.obtainMessage(MESSAGE_READ,buffer).sendToTarget();
}
catch (IOException e) {
break;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/* 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) { }
}
}
}
Summary
So as I suggested in the code comments above. I want the current executing thread to wait for the input stream data to finish filling up the buffer then immediately send the results to the message handler. In particular I do not want to use the Thread.sleep() command as this slows down the process. I have already read the following page intensely but haven't found a solution to my problem.

Related

Android Bluetooth Program Stops Receiving Characters After About a Minute. java.io.exception: BT Socket Closed Read Return: -1

I am trying to send bytes from my circuit board to my android app. My hardware is a Microchip BM78 SPP chip and I know for certain the hardware transmits bytes because when I connect an RFCOMM monitor on my computer to the hardware the bytes are received forever. However, on my Android application, the bytes are received from thirty seconds to two minutes, and then the program just stops. The app doesn't crash, it just appears to stop running. The run window and the logcat window show the following when the program stops:
Run and Logcat window when program stops
Why is the last buffer full of diamond question marks? Every time the program stops the last buffer is full of diamond question marks and is longer than 60 bytes. Also, when I debug the program, when it stops I don't get any error messages. The program just silently stops. One time I got the message java.io.exception: BT socket closed read return: -1. Why is my Bluetooth socket closing? Thanks in advance.
Here is my code for the ConnectedThread.java:
public class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private final Handler mHandler;
public ConnectedThread(BluetoothSocket socket, Handler handler) {
mmSocket = socket;
mHandler = handler;
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;
}
#Override
public void run() {
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.available();
byte[] buffer = new byte[60];
if(bytes != 0) {
SystemClock.sleep(100); //pause and wait for rest of data. Adjust this depending on your sending speed. Originally 100
bytes = mmInStream.read(buffer, 0, 50); // record how many bytes we actually read
mHandler.obtainMessage(AndroidGame.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget(); // Send the obtained bytes to the UI activity
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
/* Call this from the main activity to send data to the remote device
public void write(String input) {
byte[] bytes = input.getBytes(); //converts entered String into 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) { }
}
}

How to call write() function of ConnectedThread class of android bluetooth from main activity

i just want to know how to call the write function of the ConnectedThread class from main activity java file
public static class ConnectedThread extends Thread {
public 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);
// Send the obtained bytes to the UI activity
// mHandler.obtainMessage(2, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
break;
}
}
}
// Call this from the main activity to send data to the remote device
public void write(String m) {
try {
String msg = m;
mmOutStream.write(msg.getBytes());
} catch (Exception e)
{
e.printStackTrace();
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
The short answer is you cannot (and shouldn't) call it directly from an Activity callback or Handler tied to the main thread. This will cause the main thread of your app to block since you are making socket calls. Defer this to a background thread. There are many options you can use for this, such as HandlerThread, IntentService, AsyncTask or even the RxJava framework.

Calling a method form a different thread in Android

How do you use a method which is defined in another thread(not main) and in in a different class?Direct example is there is a ConnectedThread class in a bluetooth tutorial onAndroidDev
and in that class there is a write() method which is used to put something on a output stream of bluetooth.How can i use that method in the main activiy because i want to send an information by pressing a button?
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);
// Send the obtained bytes to the UI activity
mHandler.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) { //how do i use this method in the ui(main) activity?
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) { }
}
}
Make sure the method you are trying to access from another class is a public method.
In this example the main activity calls a fragmentActivity and shows the fragment in the layout main activity. What you have to do is create a new button in the layout fragmentActivity and instantiate within the onViewCreated. After the button initializes the event within setupChat () method sending the sendMessage ("yourMessage") your information through parameter. Everything inside the fragment activity.
I would recommend using an eventbus such as EventBus or Otto. If you are changing the UI, you will need to register for the event and then run your code on the main thread with something like Activity.runOnUIThread(){}

How to Use Classes - Bluetooth Thread

I'm trying to connect android and arduino and send data between them. I am following the guide http://developer.android.com/guide/topics/connectivity/bluetooth.html#ManagingAConnection
I think I vaguely understand how this works but I don't have a complete mastery of the basics so I am a bit stuck.
I am looking at the code for "connecting as a client":
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
and for "managing connection"
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);
// Send the obtained bytes to the UI activity
mHandler.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) { }
}
}
I basically copied the exact code and made new java files containing them.
I want to actually use these classes to send data so I paired the devices and then found the IDs like:
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0)
{
// Loop through paired devices
for (BluetoothDevice device : pairedDevices)
{
if (device.getName().equals("HC-06"))
{
//NEED TO INSERT CODE HERE (I think...)
}
else
{
Intent intentneedsetting = new Intent(this, NeedSettingsActivity.class);
startActivity(intentneedsetting);
}
}
}
else
{
Intent intentneedsetting = new Intent(this, NeedSettingsActivity.class);
startActivity(intentneedsetting);
}
Any help regarding how to use these classes (ConnectThread/ConnectedThread) will be very appreciated!
I'm not sure what did you vaguley understood and what not but i'll try to explain the purpose of these classes in general..
ConnectThread - receives a bluetooth device that was discovered in the discovery stage (which is prior to connection obviously) gets the BT socket from the device and when run() is called it tries to connect to it.
if the connection succeeded - in the code it just says manageConnectedSocket(mmSocket); but that means that u should open a ConnectedThread for receiving and sending data through the socket.
ConnectedThread - as mentioned, is the thread for managing sending and receiving data. as you can see in the run() it constantly listens using a while(true) it calls read which is blocking - meaning "the thread is stuck there" until it receives incoming data.
When data is received it handles it with the mHandler which is also not implemented here, again you should just implement whatever you want to do with the data received.
The write method simply receives an array of bytes and writes it to the socket, note that this is also a blocking call therefore u should use it from another thread.
Hope this helps u understand

how to call thread method

So I am quite new to java so be gentle.
I am trying to connect two phones by bluetooth. I created a socket but how should I use it? I mean, bluetooth tutorial says that I should call public void write(byte[] bytes) to send data, but how? I created button, assigned "onClick" method but what then? how should I call method that is in ConnectedThread form UI thread? Here is example from tutorial.
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;
Message msg = mainHandler.obtainMessage();
Bundle bundle = new Bundle();
String btnTxt = "Socket aquizaired";
bundle.putString("myKey", btnTxt);
msg.setData(bundle);
mainHandler.sendMessage(msg);
// 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);
// Send the obtained bytes to the UI activity
// mHandler.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) { }
}
}
and in the UI thread I have something like
private void sendSms (){ // method assigned to button "onClick"
// i want to send some text here, like "hello" or something...
//???????????????????????????
}
The examples in the android sdk have a very good bluetooth chat example, you should have a look at it.
public void write(byte[] out) {
ConnectedThread r;
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
r.write(out);
}

Categories