I am having an issue where when I call sock.connect() it just hangs indefinitely. There is no exception and no timeout.
try
{
Method m = dev.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
sock = (BluetoothSocket) m.invoke(dev, 1);
sock.connect();
Thread.sleep(100);
in = sock.getInputStream();
out = sock.getOutputStream();
}
catch(ConnectTimeoutException ex)
{
return false;
}
catch(IOException ex)
{
return false;
}
catch(Exception ex)
{
return false;
}
The reason is that another app is using the bluetooth device already. I am trying to make my connection fail and at least throw an exception or something to let me know the device is already in use by another app.
Any other suggestions to approaching this?
Thanks.
Why are you calling Thread.Sleep? BluetoothSocket.connect is a blocking call. This means that your Thread.Sleep will not be called until connect returns with either a successful connection or throws an exception.
Are you calling this in an activity? As this will hang your activity. You should have 3 threads to handle bluetooth, an accept thread, connect thread and a connected thread. Like in the BluetoothChat example here:
http://developer.android.com/resources/samples/BluetoothChat/index.html
Related
I am doing socket programming. I took reference from below link:
http://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/
Below is detail about my issue. I have created Android lib for this ServerThread (my project requirement), and this is used in test app.
Now test app connect to this through lib and do the process. First time it works perfectly fine, but if I closed and reopen it crashed with exception:
"EADDRINUSE (Address already in use)"
Also tried serverSocket.setReuseAddress(true) this but no luck.
My code:
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVER_PORT);
serverSocket.setReuseAddress(true);
} catch (IOException e) {
Log.e(TAG, "exception1= " + e.getMessage());
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
Log.d(TAG, "server Connected.......!!!!");
communicationThread = new CommunicationThread(
socket);
commThread = new Thread(communicationThread);
commThread.start();
} catch (IOException e) {
Log.e(TAG, "exception 2=" + e.getMessage());
}
}
}
If I call serverSocket.close() I am getting exception 2 as server socket close. Communication thread is same as given in previous link.
You have to call setReuseAddress(true) before the socket is bound to the port. You are calling it after, because you are passing the port to the constructor, which will bind the socket immediately.
Try this instead:
serverSocket = new ServerSocket(); // <-- create an unbound socket first
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(SERVER_PORT)); // <-- now bind it
TCP (and probably some other) sockets can't reuse the same port for a period after closing. This is to prevent confusion if there's data on the network from an existing connection. You can override this behavior, but the default is to wait for a period of time before allowing reuse of the port.
The call to fix this is setReuseAddress(true) on the server socket. But I'm not sure if it needs to be called on the first socket or the second, or both.
Edit:
Here's a blog post describing the TCP socket TIME_WAIT state and why it exists: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html
While other answers pointed out the importance of setReuseAddress(true), another problem that could arise is to construct the ServerSocket twice and call bind with the same parameters. For example if you call twice the code run() of the question, serverSocket will be assigned to a new instance of the ServerSocket class, but the old one is still living until garbage collected. Now constructing with the port value as parameter equals to bind the ServerSocket object, and you are going to end up with two ServerSocket bound to the same address, which is forbidden hence the exception. So build your serverSocket with your chosen port only once!
Try to create the instance of SocketServer outside of the run() method.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
try {
// create a new instance of an unbound socket first
serverSocket = new ServerSocket();
} catch (IOException e) {
e.printStackTrace();
}
}
I'm trying to establish a bluetooth communication between an android phone/tablet (4.0.3), and a bluetooth device, which is an earring reader (Destron Fearring DTR3E, in case you want to know, which I don't suppose you do).
I paired the phone with the reader (the reader has the pairing passcode on a tag) from the bluetooth settings, bluetooth is on of course, and now I'm trying to listen to reads from the device, by means of BluetoothServerSocket. The problem is that the accept call never returns, so obviously I am doing something wrong. The communication is done using RFCOMM.
Code:
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
String uuid = "00001101-0000-1000-8000-00805F9B34FB";
tmp = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("pdfParserServer", UUID.fromString(uuid));
} catch (Exception e) {
e.printStackTrace();
}
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
try {
mmServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
Is there something I am missing?
Thank you!
The only reason that could cause the code never to come back from accept is that, the device "Destron Fearring DTR3E" you are trying to connect to, has actually a bluetoothserver socket and not a bluetooth client, hence, the device might be waiting for you to actually connect to it, in stead of you creating a bluetoothserver socket and waiting for it to connect to your android device, you should read the specs on the device and make sure that actually is you the one that has to open a connection on "Destron Fearring DTR3E" socket...
Hope this helps...
Regards!
So I have TCP server in Windows that is programmed in C++ and a client in JAVA, Android 4.0.4.
In Android, I connect like this:
public boolean sendConnectRequest()
{
while (isSocketConnected == false)
{
try {
if(comSocket == null)
comSocket = new Socket("192.168.0.1",1531);
isSocketConnected = comSocket.isConnected();
if (isSocketConnected) {
out = comSocket.getOutputStream();
in = comSocket.getInputStream();
}
else
comSocket.close();
}
catch (IOException ex)
{
Log.e("TCP Error", ex.getLocalizedMessage());
}
}
return true;
}
I typically have no problems with this code on the first connection to the server.
When i disconnect from the server, I call this:
public void closeConnection() {
if (comSocket != null)
{
try {
comSocket.close();
isSocketConnected = false;
if (out != null)
out.close();
if (in != null)
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
So here is the problem... I hit the home button on the smartphone, which places the program in pause. I start the program again and it calls the resume function in activity, which in turn starts the process toward reconnection. The connection is attempted and i get no errors. However, my Windows server records no connection. In Windows, I know that I am still blocked at:
SOCKET connectionSocket = accept(tcpNetworkData->socket, (struct sockaddr*)&from, &fromlen);
I believe this is normal. When I am in debug mode on the Android side, I notice that it returns immediately from the line: comSocket = new Socket("192.168.0.1",1531); This should indicate to me that a connection is made.
If you follow me so far... I should also say that if I shut the server down, the client resets by closing the connection and opening a new one. This time the comSocket = new Socket("192.168.0.1",1531) does not block as it should and the execution keeps going. This is obviously wrong. I think it is a resource release problem but why? With Winsock you can solve this problem with this line of code:
int so_reuseaddr = TRUE;
setsockopt(networkData->socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&so_reuseaddr,sizeof(so_reuseaddr));
Can you do something similar with Android or do you have to? Thank you for your help!
According to the javadoc the connection is established once you call the constructor.
Socket(InetAddress address, int port)
Creates a stream socket and connects it to the specified port number at the specified IP address.
When you press the home button, your app goes in background but it does not get killed immediately, so your comSocket might be not null when you get back to your application. In that case you are not calling the constructor again, thus you are not reconnecting to the server. What you should do is
if(comSocket == null){
comSocket = new Socket("192.168.0.1",1531);
}else{
comSocket.connect(new InetSocketAddress("192.168.0.1",1531));
}
(and please please place the curly brackets :-) )
Something to keep in mind is that the isConnected() method isn't very reliable for detecting when the remote side has closed the connection, (here is an example).
You have to figure this out by reading or writing on the associated Input/Output Streams.
Try using PrintWriter.checkError(), which will return true as soon as the client can no longer connect to the server.
I was trying to use SocketServer to setup a server
int i =1, PORT = 6666;
ServerSocket server;
Socket client;
try {
server = new ServerSocket(6666);
for(;;){
client = server.accept();//fail in here
textView.setText("server accept..." + i);
//new MyHttpServer(client, i, PORT).start();
i++;
}
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
textView.setText("Fail...");
}
However, the app always stops in server.accept(). I have already add internet permission for this app. I don't know why?
Update:
I have found the reason. It is because thread cannot start from an Active instance. I was putted server.accept() in onStart without a thread. Now I open a new Runnable for it, then fixed
There could be multiple reasons why your application can not start the server. My initial guess would be that you are trying to run the code on an emulator or a device and you already have some other application listening on that port.
You must check/provide the logcat trace in order to get to the cause of the error.
I think so your app will wait for client with port 6666.
server.accept();// return socket
Above code will return socket if client is available.For more details and clearity you can refer these links::
http://www.happygeek.in/socket-programming-in-android
http://www.edumobile.org/android/android-development/socket-programming/
I have an Android Bluetooth application which manages a couple of remote devices(Capsules).
Writing data to the socket output stream of a Capsule worked yesterday, and after medium scale refactoring to the Android application only, I get the following error:
java.lang.IllegalMonitorStateException: attempt to unlock read lock, not locked by current thread.
Here is the socket creation code:
public final void connectWithCapsule(Capsule capsule)
throws Exception {
BluetoothSocket socket = capsulesSockets.get(capsule);
if (socket == null) {
try {
// Method m = capsule.getBT_Device().getClass().getMethod("createRfcommSocket", new Class[]{int.class});
// socket = (BluetoothSocket) m.invoke(capsule.getBT_Device(), Integer.valueOf(17));
socket = capsule.getBT_Device().createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
} catch (Exception e) {
logError("Error creating RFcomm socket", e);
throw e;
}
capsulesSockets.put(capsule, socket);
}
try {
socket.connect();
} catch (IOException e) {
logError("Error connecting socket", e);
try {
socket.close();
} catch (IOException e1) {
logError("Error closing socket", e1);
}
capsulesSockets.remove(capsule);
throw e;
}
}
and the model which manages the in/out streams:
public final class KitBT_ConnectionModel {
private final OutputStream[] outputStreams;
private final InputStream[] inputStreams;
public KitBT_ConnectionModel(OutputStream[] outputStreams, InputStream[] inputStreams) {
super();
this.outputStreams = outputStreams;
this.inputStreams = inputStreams;
}
public void transmitData(byte[] bs)
throws IOException {
for (OutputStream outputStream : outputStreams) {
outputStream.write(bs); // THIS LINE THROWS THE EXCEPTION
outputStream.flush();
}
}
public InputStream[] getInputStreams() {
return inputStreams;
}
}
Note: I do not perform any action with both of the streams, and the first write causes the exception.
First thing that pops to mind is which thread puts the read lock and when?
I've tried to play around with the threads which call the socket creation, and the streams transactions, I've made sure, 100% sure they have both been accessed by the same thread (and also tried accessing with different threads), but this exception persists.
Please enlighten me...
HAAAAAAAAAAAAAAAAAAa.........
Darn this LG phones!!!!
I gave the phone a hard reboot, removed the battery and started it over, and it works again...
turning the Bluetooth off and on didn't do the trick! I've been doing it for the past day or so.
God damn it nearly 24 hours of waste for nothing....
How messed up can these products be!
at least it works now!