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(){}
Related
I'm trying to send a hashmap from one device to another via bluetooth. I'm creating the hashmap like this, and then calling the connection threads writeObject method:
Map<String,String> subInfo = new HashMap<>();
subInfo.put("type", "subInfo");
subInfo.put("num", "1");
BTService.connectedThread.writeObject(subInfo);
My bluetooth service has the following class thats used to handle data transfer between devices in a background thread:
public static class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private final ObjectInputStream mmObjInStream;
private final ObjectOutputStream mmObjOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
ObjectInputStream tmpObjIn = null;
ObjectOutputStream tmpObjOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
tmpObjIn = new ObjectInputStream(socket.getInputStream());
tmpObjOut = new ObjectOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
mmObjInStream = tmpObjIn;
mmObjOutStream = tmpObjOut;
}
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 (!this.isInterrupted()) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
e.printStackTrace();
break;
}
try {
//Read objects from ObjectInputStream
Object object = mmObjInStream.readObject();
// Send the obtained object to the UI activity
mHandler.obtainMessage(Constants.MESSAGE_READ_OBJECT, -1, 0, object)
.sendToTarget();
} catch (ClassNotFoundException | IOException e) {
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) {
e.printStackTrace();
}
}
public void writeObject(Object object) {
try {
mmObjOutStream.writeObject(object);
}catch(Exception e){
Log.e(TAG, "Error ObjectOutputStream: " + e.getLocalizedMessage());
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
this.interrupt();
} catch (IOException e) {
e.printStackTrace();
}
}
}
So when I call the writeObject method it should send the object down the Object output stream of the thread above.
On the other device, the code is similar. It just listens on the Object input stream for an object, once it has been found it sends a MESSAGE_READ_OBJECT message to my message handler in the main activity:
static class MessageHandler extends Handler {
private final WeakReference<MainActivity> mActivity;
MessageHandler(MainActivity activity) {
mActivity = new WeakReference<>(activity);
}
#Override
public void handleMessage(Message msg)
{
final MainActivity mainActivity = mActivity.get();
if (mainActivity == null) {
return;
}
switch(msg.what){
case Constants.MESSAGE_READ_OBJECT:
Object receivedObject = msg.obj;
//How should I pull out the hashmap here?
switch(type){
case "subInfo":
//do some things
break;
}
break;
}
}
}
What is the correct way to reassemble the hashmap in my message handler? I need to check the "type" key of the map and switch based on that, but as of right now I'm not sure how to get the map object back. The receivedObject object in my message handler doesn't seem to behave like a hashmap, and doesn't have the typical methods used for pulling out keys and values
Furthermore, instead of sending a generic Object over bluetooth, would it make more sense to directly send a Map type object?
Just direct convert
HashMap mHashmap = (HashMap) obj;
this is what I do ,
https://github.com/zhenbeiju/AndroidCommonUtil/blob/master/app/src/main/java/commanutil/utl/file/ObjUtil.java
useage: https://coding.net/u/zhenbeiju/p/javanlp_/git/blob/master/src/com/voice/common/util/nlp/Main.java
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.
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
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.
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);
}