How to use Connected Thread in multiple activites - java

I am newbie in Android. First I've written an application which connects to another device via Bluetooth, then sends and receives data, using socket and connected thread. While using one activity everything works great, I receive data using handler.
Then I started to make an application with multiple activities, so I made a special class for socket connection and connected thread. I send data normally from any activity, but I don't know how to receive an answer (how to make a handler in many activities, or what alternative to use). Could you possibly help me and write this lines of code, that I should add.
Thanks.
Here is my thread:
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) {}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[256];
int bytes;
while(true) {
try {
bytes = mmInStream.read(buffer);
byte[] readBuf = (byte[]) buffer;
String strIncom = new String(readBuf, 0, bytes);
// Here I need some method to send data to activity
}
catch (IOException e) {
break;
}
}
}
public void write(String message) {
byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
}
}
}

Well, one thing you can do is the use of an Interface,for example:
public class ConnectedThread extends Thread {
// You declare your interface in the Class body
public static interface CallBackListener
{
public void onReceived(String msg);
}
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private CallBackListener listener = null;
// then, those who want to use this class must implement
// this interface
public ConnectedThread(BluetoothSocket socket, CallBackListener aListener)
{
this.listener = aListener;
...
And in the run method of the thread you do like this:
// Here I need some method to send data to activity
if (listener != null)
{
listener.onReceived(strIncom);
}
And when you create the class, do like this:
BluetoothSocket socket = null;
/*
* Create the BlueToothSocket here
BluetoothSocket socket = new BluetoothSocket(...);
*/
ConnectedThread conThread = new ConnectedThread(socket, new ConnectedThread.CallBackListener()
{
#Override
public void onReceived(String msg)
{
// here you'll receive the string msg
// keep in mind that you receive this call
// in the ConnectedThread's context, not the UI thread
}
});

Related

Android Bluetooth Does not Always Receive Data

I have a frustrating issue, that being my serial Bluetooth receiving code does not always receive the data from it's connection. Most of the time, it works perfectly, but sometimes after connection, it does not receive any data even though I can verify the connection is there, and the other device is sending the data. My receiving code is below:
/**
* Created by tvanderpuy on 12/1/2016.
* Handles communication with BT device
*/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private final BufferedReader bufferedReader;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "create ConnectedThread");
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) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
// Set up buffered reader
bufferedReader = new BufferedReader(new InputStreamReader(mmInStream));
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
String cmd;
// Keep listening to the InputStream until an exception occurs
while (mState == STATE_CONNECTED) {
try {
// Wait for new line for buffered reader
cmd = bufferedReader.readLine();
// Send the obtained bytes to the UI activity
if (!cmd.isEmpty())
mHandler.obtainMessage(MESSAGE_READ, cmd.getBytes().length, -1, cmd.getBytes())
.sendToTarget();
Log.v(TAG, "Command: " + cmd);
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
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) {
}
}
}
}
Please let me know if you have any insight into this.
Thank you,
Tom

How use the class MyBluetoothService in the Android bluetooth documentation

I don't understand the best way to use this class that the official documentation expose.
They say
1)Get the InputStream and OutputStream that handle transmissions through
the socket using getInputStream() and getOutputStream(), respectively.
2)Read and write data to the streams using read(byte[]) and
write(byte[]).
and give this example
public class MyBluetoothService {
private static final String TAG = "MY_APP_DEBUG_TAG";
private Handler mHandler; // handler that gets info from Bluetooth service
// Defines several constants used when transmitting messages between the
// service and the UI.
private interface MessageConstants {
public static final int MESSAGE_READ = 0;
public static final int MESSAGE_WRITE = 1;
public static final int MESSAGE_TOAST = 2;
// ... (Add other message types here as needed.)
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private byte[] mmBuffer; // mmBuffer store for the stream
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();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating input stream", e);
}
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating output stream", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
mmBuffer = new byte[1024];
int numBytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs.
while (true) {
try {
// Read from the InputStream.
numBytes = mmInStream.read(mmBuffer);
// Send the obtained bytes to the UI activity.
Message readMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_READ, numBytes, -1,
mmBuffer);
readMsg.sendToTarget();
} catch (IOException e) {
Log.d(TAG, "Input stream was disconnected", e);
break;
}
}
}
// Call this from the main activity to send data to the remote device.
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
// Share the sent message with the UI activity.
Message writtenMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
writtenMsg.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Error occurred when sending data", e);
// Send a failure message back to the activity.
Message writeErrorMsg =
mHandler.obtainMessage(MessageConstants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString("toast",
"Couldn't send data to the other device");
writeErrorMsg.setData(bundle);
mHandler.sendMessage(writeErrorMsg);
}
}
// Call this method from the main activity to shut down the connection.
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
}
}
I have the rest of the code that following the documentation in the main activity and i need to manage the connection now with this class...
Now i adapt the code in the main activity (copy the private class ConnectedThread extends Threads in the MainActivity) but if someone can explain to me the best usage of this class it's better for me.
Thanks

Android Bluetooth write() method

I'm trying to create bluetooth application, using this tutorial:
https://developer.android.com/guide/topics/connectivity/bluetooth.html
There is class ConnectedThread:
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) { }
}
}
Comment says I need to call write() method from main activity, but there is actually no instance of ConnectedThread class, it is just started from another class. How can I use this method?
EDIT1:
I see why I can't use it that way.
It doesn't work, because ConnectedThread is defined and declared at the point in the program and when program leaves it, it no longer exists, right? So, should I define object of ConnectedThread visible in whole activity and just define it in Connect thread. Instead:
ConnectedThread mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
I could use:
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
Right?

Bluetooth data transfer between two Android devices

I have been following this Android guide for Bluetooth communication
To explain exactly what I want to do, when the two devices are paired, two different activities open up on each device (server and client) where on the server activity I have different buttons, and on the client activity there is just a textview.
I want to be able to press a button on the server device and display it on the client.
I have managed to establish a connection between the two devices, but now I want to send data which I have not been able to do.
They give this code for 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() {
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) { }
}
}
But this line generates an error
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
And is not explained in the guide. I don't know what the mHandler is or does.
Apart from the error, I don't even really understand where to put this code. Should it be in the second activities (server and client) that I open or in the main? If in the Server activity, should it be in the onClick method for all the buttons with a different byte code to send for each button? And in this code, how do we distinguish who is sending and who is receiving?
Check out the BluetoothChat example that Google provides in the SDK. It'll show you how to implement basic sending of text over bluetooth.
You can also try the tutorial example here
Can you please describe the error as seen by you?
As informed by Ankit and Addy, BlueToothChat is the best code for you to refer. Conduct an experiment by loading it on 2 android devices - use one as server other as client to exchange the messages between them. Such experiment will help you to understand it's code and decide your coding logic.
mHandler is used for passing message from your BluetoothHandle.java to your Activity. This will help you to update messages on your screen which are returned by BluetoothHandler.
you have to create mHandler from your activity and call your handler like this -
mBluetoothHandler = new BluetoothHandler(this, mHandler);
and your BluetoothHandler.java has constructor like this -
public class BluetoothHandler {
public BluetoothHandler(Context context, Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
mcontext = context;
}
}
For more details, please refer Android sample project of Bluetooth Chat .
You can also use this link :
http://myandroidappdevelop.blogspot.in/2013/05/bluetooth-chat-example.html
// Enter code here
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
byte[] writeBuf = (byte[]) msg.obj;
int begin = (int)msg.arg1;
int end = (int)msg.arg2;
switch(msg.what) {
case 1:
String writeMessage = new String(writeBuf);
writeMessage = writeMessage.substring(begin, end);
break;
}
}
};

Proper use of context within inner class when using openFileOutput?

I am trying to adapt the Android BluetoothChat example to save the InputStream to file using openFileOutput from within the BluetoothChatService class. When using the Environment.getExternalStorageDirectory and saving to the sdcard using filewriter there is no problem, but using the openFileOutput method with MODE_PRIVATE returns a nullPointerException as mentioned in several other questions/answers. I cant for the life of me figure out the correct way to get the correct context.
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private Context mContext;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "create ConnectedThread");
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) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
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);
// Save to file
String FILENAME = "chat.txt";
FileOutputStream fos = mContext.openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(bytes);
fos.close();
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
Well, right now mContext is null. You're not assigning anything to it anywhere. You could change your constructor signature to pass it in:
public ConnectedThread(Context context, BluetoothSocket socket) {
this.mContext = context;
...
}
If you're actually following the example, you could do the same type of thing in the BluetoothChatService... note that they don't do anything with the context passed in. Store that context off in a field and it would also be accessible to the ConnectedThread.

Categories

Resources