Bluetooth insecure connection act like a loopback? - android

I'm developing an Android Bluetooth app that aim to speak using Bluetooth with a device we created, I successfully made everything work on most device on Android 3+ but it seems that android 2.3.x (which is our minimal requirement) doesn't act like the others. I also reproduced the same behavior on a Huawei Ascend P1.
What happens is that on Android side everything acts normal, I connect to the device and a pairing request is made if I'm not paired, I retrieve both in and outstream but when I use them they act like I'm speaking to myself on a loopback. Everything written on the outputstream is read on the inputstream. And of course the device does not see anything (It seems that it doesn't even know that an android phone is connected).
Here are some code sample from my sources (most of it is exactly as described in the android documentation):
Connection thread:
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
btSpeaking = true;
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
tmp = device.createInsecureRfcommSocketToServiceRecord(BluetoothUuid.declareUuid.getUuid());
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
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)
mConnected = new ConnectedThread(mmSocket);
mConnected.start();
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
Read 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;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
WSLog.e(tag, e.getMessage(), e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
try {
writeSocket(RESET, empty);
} catch (IOException e1) {
return;
}
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
for (int size = 0; size < framesize;) {
int read = mmInStream.read(frame, size, frame.length - size);
if (read < 0) {
return;
}
size = size + read;
}
} catch (IOException e) {
return;
}
}
}
Write socket:
private void writeSocket(byte comm, byte[] data) throws IOException {
ByteBuffer bf = ByteBuffer.allocate(1 + data.length);
bf.put(PROTO);
bf.put(comm);
bf.put(data);
mmOutStream.write(bf.array());
}
I really hope I'm not doing something obviously wrong but as I can't get why it doesn't work I had no choice but to ask for help.
Thanks,
Martin

Related

Bluetooth connection doesn't close

hello everybody i have been working on this app for so long now, and i think i almost finished but there is a problem and i tried a lot of different ways to solve it but i couldn't so any help i would appreciate .
the app is simple Bluetooth data sender to an Bluetooth module and it works just fine the problem occur if i wanted to close the connection from the app i couldn't close it and i have tried interrupt and the cancel method and putting a condition in a while loop but without any luck so can anyone help me please thank you.
this is my client thread (the same as android developer)
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private boolean x;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Log.i(tag, "construct");
// 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) {
// Log.i(tag, "get socket failed");
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
while (true) {
bluetoothAdapter.cancelDiscovery();
Log.i(tag, "connect - run");
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
Log.i(tag, "connect - succeeded");
} catch (IOException connectException) {
Log.i(tag, "connect failed");
// 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)
xHandler.obtainMessage(0, mmSocket).sendToTarget();
if(x==false){
break;
}
}
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
Log.i(tag,"cancel 1");
mmSocket.close();
x=false;
// mmDevice.close();
} catch (IOException e) { }
}
}
and this is my connected class
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private boolean x;
//private FileInputStream fis;
private int s;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
//s=x;
// 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() {
// if (s == 1) {
byte[] buffer;
// buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs}
//}
while (x) {
try {
// Read from the InputStream
buffer=new byte[1024];
// buffer = new byte[1024];
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
xHandler.obtainMessage(1, 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) {
Log.i(tag,"write");
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
mmInStream.close();
mmOutStream.close();
x=false;
Log.i(tag,"cancel 2");
}
catch (IOException e) { }
}
}
and finally the handler:
public Handler xHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
Log.i(tag, "in handleeer");
super.handleMessage(msg);
switch(msg.what){
case 0:
// DO something
// if(omar==1){
//(BluetoothSocket)msg.obj
// bluetoothSocket=(BluetoothSocket).msg.obj;
connectedThread = new ConnectedThread((BluetoothSocket)msg.obj);
Toast.makeText(getApplicationContext(), "CONNECT", Toast.LENGTH_LONG).show();
//omar++;}
//String s = "79";
String s="h";
connectedThread.write(s.getBytes());
Log.i(tag, "connected");
break;
case 1:
byte[] readBuf = (byte[])msg.obj;
String string = new String(readBuf);
Toast.makeText(getApplicationContext(), string, Toast.LENGTH_LONG).show();
break;
}
}
};

Receiving data from raspberry pi in android via bluetooth

I am creating an android app using which I am going to connect to Raspberry pi over Bluetooth.
The issue that I am able to send data to Raspberry pi and it is visible on the terminal (I am using OutputStream in android to send data), but whatever Raspberry pi is sending I am not able to get that in my InputStream.
I have read about using listenrfcomm to get the data sent by another device, but while using createrfcomm also, I have input as well output streams. I am confused as what to use and how to use.
NOTE: Using createrfcomm I am able to send data to Raspberry pi successfully. Only data reception from Rasperry pi is the part that's remaining.
Please advise accordingly.
It would be easier to answer specifically with your code, but I found the API guide example helpful although slightly disjointed at first:
Have a thread to connect:
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 a thread to listen and do the work:
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 assume if you can sent that you have BluetoothDevice, and BluetoothAdapter already, and can create and run the connect thread
mConnectThread = new ConnectThread(bluetoothAdapter.getRemoteDevice(deviceAddress));
mConnectThread.start();
In the example bytes is the data read, which is sent to the UI thread with mHandler.obtainMessage. This line can be edited to suit whatever you want to do with the received data.
Example comes from http://developer.android.com/guide/topics/connectivity/bluetooth.html

Bluetooth - Receive data from multiple device in same time on android

I'm trying to receive data from multiple device in same time, i'm using createInsecureRfcommSocketToServiceRecord() and the SPP UUID 00001101-0000-1000-8000-00805F9B34FB to connect to non-android devices.
So i'm running 3 instance of ConnectedThread, i'm able to write to all device, but i can't receive from 2 device at same time.
Example : i'm connecting to 2 Pc using HyperTerminal, if i send a txt file on both at the same time, i will receive only one on my android device, the other one is ignored.
I'm looking this library : http://arissa34.github.io/Android-Multi-Bluetooth-Library/ seems i have to run a server on my android phone.
How can I achieve this?
Best regards.
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) { }
}
}

connect function gets blocked while connection to bluetooth device

i am trying to connect with a bluetooth device from my HTC Wildfire , few months back it was working fine and able to make a connection with bluetooth device , but after updating software on HTC , things are not working well
when phone wasn't updated following code working like a charm
bluetoothSocket = bluetoothDevice.createRfcommSocketToServiceRecord(UUID_STRING);
after updating my phone i explored and i found following code
Method m = bluetoothDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
bluetoothSocket = (BluetoothSocket) m.invoke(bluetoothDevice, Integer.valueOf(1));
bluetoothSocket.connect();
but my bluetooth connection gets blocked bluetoothSocket.connect(). Moreover the code doesnt reach to
bluetoothSocket.getInputStream() and bluetoothSocket.getOutputStream() .
Does anyone has any fix for this problem ,
my current status of HTC wildfire is
android os 2.2.1
build number 2.25.720.4CL299259 release-keys
As Bluetooth connecting process is time-consuming and can't be predict to some time bound.
It's better to put connect in
Background Thread.
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) { }
}
}
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) { }
}
}

Bluetooth On Android: my Socket.connect() Blocks forever, and Socket.close does not unblock

I have been working on a bluetooth app for android for awhile now and I just discovered this problem. When I preform mySocket.connect(); in my bluetooth service class it occasionally blocks indefinitely. I read the documentation for BluetoothSocket.close() and it says the following:
Immediately close this socket, and release all associated resources.
Causes blocked calls on this socket in other threads to immediately
throw an IOException.
However, this does not seem to work for me. Here is my code for setting a timer and then trying to connect.
//code for starting timer and connecting
MyRunnable runner = new MyRunnable(mySocket);
Thread countThread = new Thread(runner);
countThread.start();
mySocket.connect();
runner.setSocketConnected();
//code for MyRunnable
private class MyRunnable implements Runnable{
private boolean didSocketConnect = false;
private boolean socketConnectFailed = false;
private BluetoothSocket socket;
public MyRunnable(BluetoothSocket socket){
this.socket = socket;
}
public void run() {
long start = System.currentTimeMillis();
while(ESTABLISH_TIMEOUT + start >= System.currentTimeMillis() && !didSocketConnect && !socketConnectFailed){
}
if(!didSocketConnect && !socketConnectFailed){
Log.v(TAG,"Reached Timeout and socket not open. Look for #");
try {
socket.close();
Log.v(TAG,"#THIS CALL SHOULD BE MADE AFTER REACHED TIMEOUT AND SOCKET NOT OPEN");
} catch (IOException e) {
Log.v(TAG,"Closing the socket connection fail--", e);
}
}else{
Log.v(TAG, "Connected or Failed Before Timeout Thread Hit");
}
}
public void setSocketConnected(){
didSocketConnect = true;
}
public void setSocketFailed(){
socketConnectFailed= true;
}
}
When I call close(), it also blocks indefinitely and the connect() call never throws an IOException, despite BluetoothSocket.close() documentation. What is the best way to make it work so that the connect() and close() do not block indefinitely?
NOTE: I am using Android 2.2 for this project.
BluetoothSocket.connect() - From the documentation:
Attempt to connect to a remote device. This method will block until a
connection is made or the connection fails. If this method returns
without an exception then this socket is now connected.
In order for your call to BluetoothSocket.connect() to quit blocking, it needs to make the connection. This is by design and it makes sense if you think about it, get the address of the Bluetooth device we want to connect to, call .connect(), and block until its connected. This is why you want separate threads.
As far as you calling .close(), if you work out the issues with .connect(), .close() should fall into place.
Please read this. It basically says you want a separate thread called "connecting" (.connect()) and "connected" (InputStream.read()). This way your UI will not be blocked.
Example (from the above link). ConnectThread initiates the connection. ConnectedThread manages the connection (reads/writes data, etc...).
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) { }
}
}
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) { }
}
}

Categories

Resources