In my application two devices are connected via bluetooth. In the background runs an own thread for the bluetooth connection. (Just like the example )
When one device wants to connect to another device i want a request dialog to be displayed on the second device.
So I guess that i have to modify the AcceptThread. The AcceptThread has to inform my mainThread (for example with a Handler).
In the AcceptThread I find this code:
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
Now here is my problem: this "blocking call" runs the whole time. How and when shall I inform my mainThread that another device wants to connect?
Definitely afterwards.
What you want is the result of the blocking call - of the .accept().
That is socket in your code.
Here is a quote from the Android BluetoothServerSocket documentation:
Then call accept() to listen for incoming connection requests. This
call will block until a connection is established, at which point, it
will return a BluetoothSocket to manage the connection. Once the
BluetoothSocket is acquired, it's a good idea to call close() on the
BluetoothServerSocket when it's no longer needed for accepting
connections. Closing the BluetoothServerSocket will not close the
returned BluetoothSocket.
So don't forget to do:
mmServerSocket.close()
After you receive a socket correctly - a BluetoothSocket actually -, you can choose what to do with it following the user's choice:
Should he go ahead, you just create the AsyncTask that reads from the socket until the AsyncTask is cancelled or an Exception occurs(on Bluetooth disconnect probably).
Should he decline, just cancel the socket
If you receive an Exception during the blocking call I would return to the main menu only a toast, saying something failed. But you can do a dialog (like retry?)
Related
Maybe I miss something, but How can I change the timeout of BluetoothSocket.connect() ?
Thanks you
Anthony
You can't change timeout of BluetoothSocket.connect(). As documentation:
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.
A workaround.
Ex: timeout 5s.
Using CountDownTimer to check if connect is complete(success or fail). After 5s, if connection is incomplete then use BluetoothSocket.close() to cancel.
As BluetoothSocket documentation:
close() can be used to abort this call from another thread.
So I've got a socket that is connected to an outside web address and when it gets a certain message it's supposed to disconnect. I tried calling socket.close() but socket.isConnected() is still true. No luck searching for an answer
isConnected() only tells you if you made a successful connection to a socket. isClosed() tells you if you called close().
Check out this guys response https://stackoverflow.com/a/3701249/2453771
" When you use Socket(), which you seem to have overlooked,
Socket.isConnected() tells you whether Socket.connect() has been
called or not. Similarly for isClosed() and close().
Confusion over these methods results from confusing the state of the
socket, which is under the control of the application, with the state
of the overall connection, which is under the control of the protocol.
isConnected() and isClosed() tell what you have done to the socket.
There are no APIs other than read and write for determining the state
of the connection."
Oracle documantion < in here it's well explained that once you call .close() the connection is closed and you can check by isClosed().
.close() :
Closes this socket.
Any thread currently blocked in an I/O operation upon this socket will
throw a SocketException.
Once a socket has been closed, it is not available for further
networking use (i.e. can't be reconnected or rebound). A new socket
needs to be created.
isConnected() and isClosed() tell you the current state of your socket (in your side).
isConnected() tells you whether you have connected this socket and isClosed() tells you whether you have closed this socket. Until you have, it returns false.
Yes, right. It surely seems socket.close() and socket.isConnected() are independent from each other. I wish method naming was not as confusing.
From official Android SDK:
public boolean isConnected()
Returns the connection state of the socket.
Note: Closing a socket doesn't clear its connection state, which means
this method will return true for a closed socket
P.S. more intuitively it should be called wasConnected() 😅
http://developer.android.com/reference/java/net/Socket.html#close()
Do a checksum on the data returned, make sure you get the correct value. If so and you called close and try-catch everything, it should be fine.
You could watch in a debugger and make sure nothing is leaking.
try
socket.isClosed()
Returns a boolian, whether this socket is closed.
Refer
Sockets
I work on application which constantly sends some data acquired from device to server API. And I have a service working all the time in background and collecting data and then a network thread in this service which is responsible for establishing connection with server and sending data.
The problem I have is that although I acquire Wake and WiFi locks on service startup, at some point when device is on 3g network with poor connection it seems that socket write method just hangs: I see this from logs I output after each operation
Network thread is very simple and may be described as
while(true) {
if(!connectedToServer) {
connectToServer();
}
acquireData();
sendData();
}
And sendData is very simple - it writes data to socket output stream. From what I see in logs it seems that OutputStream.write() call just blocks for indefinite time on poor connection.
Did anyone experience similar problems?
Thanks,
I´m writing an android app that connects to a device through bluetooth using RFCOMM. I use the BluetoothChat example as basis for establishing a connection and everything works perfectly most of the time.
However, sometimes I cannot reconnect due to a message that the socket is already open:
RFCOMM_CreateConnection - already opened state:2, RFC state:4, MCB
state:5
This tends to happen if I connect to the device, close the app (call onDestroy()), reopen it and try to connect again, which results in the above.
I use this method for connecting in the ConnectThread(ref.BluetoothChat example):
Method m = device.getClass().getMethod("createRfcommSocket",new Class[] {int.class });
tmp = (BluetoothSocket) m.invoke(device, Integer.valueOf(1));
mmSocket = tmp;
The only thing that resolves this problem is turning off/on the Bluetooth of the Android phone.
This leads me to believe that the socket is not being closed in onDestroy() but still I´m calling on closing all threads as shown in the before mentioned example.
Any ideas would be appreciated.
I stumbled upon this one too, and here is the answer I found:
This error may happen, if you open and close a bluetooth socket connection multiple times.
Solution
Starting from API Level 14 there is a Method in BluetoothSocket called isConected(), which returns true, if this socket is already connected and false otherwise, here the original excerpt from the API:
Get the connection status of this socket, ie, whether there is an
active connection with remote device.
For API levels < 14 you can work around this issue by putting your Bluetooth Handling Thread to sleep after closing the connection - 1000 ms should be enough, here is an example (btDevice is of the type BluetoothDevice and has been initialized prior to the code snippet below):
try {
//Open the socket to an SPP device (UUID taken from Android API for createRfcommSocketToServiceRecord)
BluetoothSocket btSocket = btDevice.createRfcommSocketToServiceRecord("00001101-0000-1000-8000-00805F9B34FB");
//Connect to the socket
btSocket.connect();
//Close the socket
btSocket.close();
//Sleep time of 1000ms after closing the socket
SystemClock.sleep(POST_RESET_DELAY);
} catch (Throwable e) {
// Log error message
}
P.s. Instead of SystemClock.sleep you can also use Thread.sleep - however the SystemCock's sleep can't be interrupted, whereas the Thread.sleep can be interrupted, so it depends on your use-case which option better suits your purpose.
Source: Louis A. Prado
I've a android app which try to connect to server. But there is a problem when I create a socket. the application hang when it try implement the following line:
Socket socket= null;
socket = new Socket("192.168.0.15", 6565);
note that I have added this permission:
<uses-permission android:name="android.permission.INTERNET" />
also I used the debug but it hang when it reach to creating socket line and I've got this detail about the error:
java.net.SocketTimeoutException: Socket is not connected id=829731319824
and I am sure that port is not bound.
I appreciate your time.
Your connection probably cannot be established or is taking some time to be established.
Operations on java.net.Socket are blocking that's why your application appears to be hung. To avoid "hanging" the UI, you should probably try to establish the connection using another thread so your UI thread won't block and will remain responsive.
Obviously your connection cannot be established and the problem lies not within your code but the network setup. To avoid your app to hang, make sure you catch the SocketTimeoutException to be able to show an error message to the user along with some buttons to, for instance, try again or cancel the connection.