I am new to Object Input Streams and Object Output Streams but I have to use them to send a string over Bluetooth. Whenever I try to make the connection both phones freeze and then crash. I used the debugger and the last line it stopped at before the program froze is: tmpIn = new ObjectInputStream(socket.getInputStream());
Here is my connection thread:
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final ObjectInputStream mmInStream;
private final ObjectOutputStream mmOutStream;
private FileOutputStream mmFileOut = null;
public ConnectedThread(BluetoothSocket socket, String socketType) {
Log.d(TAG, "create ConnectedThread: " + socketType);
mmSocket = socket;
ObjectInputStream tmpIn = null;
ObjectOutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
//input stream
//mmFileIn = new FileInputStream("t.tmp");
tmpIn = new ObjectInputStream(socket.getInputStream());
//output stream
mmFileOut = new FileOutputStream("t.tmp");
tmpOut.flush();
tmpOut = new ObjectOutputStream(mmFileOut);
tmpOut.writeObject(socket.getOutputStream());
}catch (FileNotFoundException fnfe){
System.out.println("FileOutPutStream: "+ fnfe);
}catch (IOException ie){
System.out.print("ObjectOutputStream: " + ie);
}catch (Exception e){
System.out.print(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);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
break;
}
}
}
/**
* Write to the connected OutStream.
*
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
I read somewhere it may have to do with using .flush() on my Object Output Stream am I using that correctly?
The code in the constructor runs on the UI thread. Move it to run().
Related
I've been following a BluetoothChat app tutorial similar to the sample provided by Google. Link to reference here GoogleSource . I can successfully connect to other phone's Bluetooth when I have not implemented the class that handles the input and output streams. But when I implemented the class (ConnectedThread), it crashes the app with the null pointer exception at the run() method on "bytes = inputSream.read(buffer)" inside that class. Any idea on how to approach a fix? Been plaguing me for days. Help would be appreciated. Thanks!
ConnectedThread class
private class ConnectedThread extends Thread {
private final BluetoothSocket bluetoothsocket;
private final InputStream inputStream;
private final OutputStream outputStream;
public ConnectedThread(BluetoothSocket socket) {
bluetoothsocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = bluetoothsocket.getInputStream();
tmpOut = bluetoothsocket.getOutputStream();
} catch (IOException e) {
Log.e("ConnectedThrd->Cons", "Socket not created.");
}
inputStream = tmpIn;
outputStream = 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
//App crashes here(?)
bytes = inputStream.read(buffer);
// Send the obtained bytes to the UI Activity
handler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e("ConnectedThrd->Run", "Connection Lost.", e);
e.printStackTrace();
connectionLost();
break;
}
}
}
public void write(byte[] buffer) {
try {
outputStream.write(buffer);
handler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e("ConnectedThread->Write", "Empty write stream.");
}
}
public void cancel() {
try {
bluetoothsocket.close();
} catch (IOException e) {
Log.e("ConnectedThread->Cancel", "Failed to close socket.");
}
}
}
The problem was that the BluetoothSocket was null when I try to send a data to the other device causing this error. Adding a condition to check whether a connection is established helped me handle the error.
I am sending String "A:22.656565,76.545454#" through bluetooth.BUT At recieving time it only takes "" at first time then takes remaining String i.e "A:22.656565,76.545454#".I dont know why this occur? Any Help would be appreciated. Here is my code::
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType) {
//Log.d(TAG, "create ConnectedThread: " + socketType);
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
//Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
mState = STATE_CONNECTED;
}
String received="" ;
public void run() {
//Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
while (mState == STATE_CONNECTED) {
try {
bytes = mmInStream.read(buffer);
received += new String(buffer, "UTF8");
received = received.replaceAll("\\p{C}", "");
if (received.contains("*")) {
received = received.substring(0, received.indexOf("*"));
Log.e("FOUND", ": " + received);
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, received).sendToTarget();
received = "";
buffer = new byte[1024];
}
} catch (IOException e) {
//Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
public void write(byte[] buffer) {
try {
//Log.d("Filter","Sending Data inside write3");
mmOutStream.write(buffer);
Log.e("FOUND456", ": " + buffer);
mHandler.obtainMessage(MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
} catch (IOException e) {
//Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
//Log.e(TAG, "close() of connect socket failed", e);
}
}
}
Sounds like there is a small delay in receiving the data, this is not unusual. You should read data from the inputstream in a loop breaking out of the loop when the complete data is received or timeout
is there a way to send multiple messages with OutputStream.write(bytes[]), for example when i call twice my function to write func.write("hi"); func.write(" how are you");, I receive the message "concateneted" like this: "hi how are you", but i want two different messages, is there a way to do it without using separators in my message, i mean know when the other device receives the message, here is my code (its the android bluetooth sample):
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType) {
Log.d(TAG, "create ConnectedThread: " + socketType);
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);
// 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();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
break;
}
}
}
/**
* Write to the connected OutStream.
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
Call:
mmOutStream.flush()
after each message part.
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
//send what is already in buffer
mmOutStream.flush();
// Share the sent message back to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
From the docs:
flush()
(Flushes this output stream and forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written have been buffered by the implementation of the output stream, such bytes should immediately be written to their intended destination.
I need to show data to a TextView from a serial Bluetooth.
But when i connect my application with the serial device, it did connected but suddenly went forced closed. The logcat shows nothing so I don't know what's wrong.
This is the code when application listens the inputstream while connected:
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
//mEmulatorView.write(buffer, bytes);
mTextView.append(new String(buffer));
// Send the obtained bytes to the UI Activity
//mHandler.obtainMessage(BlueTerm.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
String a = buffer.toString();
mTextView.setText(a);
a = "";
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
and TextView mTextView = (TextView) findViewById(R.id.dataTerm);
and on the layout:
<TextView
android:id="#+id/dataTerm"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
So does anyone know what went wrong?
Any answers are so helpful, thanks..
The code that finally work
On the main file, in my case named FinalSetting:
On the Activity method, declare:
//Layout View
private static TextView mTextView;
On the onCreate(Bundle savedInstanceState) method declare the textview:
mTextView = (TextView) findViewById(R.id.dataTerm);
On the Handler method:
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
//mEmulatorView.write(readBuf, msg.arg1);
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
//mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
mTextView.setText(readMessage);
break;
On the BluetoothService.java file:
Let's just straight to the method
//This thread runs during a connection with a remote device.
//It handles all incoming and outgoing transmissions.
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
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];
//final 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(FinalSetting.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
/**
* Write to the connected OutStream.
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(FinalSetting.MESSAGE_WRITE, buffer.length, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
After you connect to the serial Bluetooth device, the data will show up on the TextView.
Hope this help :D
Seems like you are trying to modify mTextView in a non-UI thread which is illegal and might be the reason for FC (if not any other issue). However you can achieve this as below:
Change this:
mTextView.append(new String(buffer));
To this:
mTextView.post(new Runnable() {
#Override
public void run() {
mTextView.append(new String(buffer));
}
});
I saw in Android 2.1 highlight it said new platform support: "Bluetooth 2.1, New BT profiles: Object Push Profile (OPP) and Phone Book Access Profile (PBAP)". Now I have bluetooth adpater with OPP support. I can search and pair with it. But how can I get the txt file it send to me. There is no API for this function. I'm using the BluetoothChat sample code like structure as below. But the code is block in
"bytes = mmInStream.read(buffer);".
And nothing happens. Why? Nothing received?
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
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);
// 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;
}
}
}
/**
* Write to the connected OutStream.
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
As far as I know, OPP and PBAP features are provided for developers by Android API.
What they did was implement these profiles as applications, and ship it with the platform. You can see in your device that there are OPP and PBAP services running, so they will accept and handle the external connections, not your app.
The source code for these apps I mentioned are available here:
https://android.googlesource.com/platform/packages/apps/Bluetooth