Closing additional threads during ServerSocket.accept() in Android - android

in my current project I'm using my smartphone as a server. The server is started when a special Card or Tag was detected via NFC. This is the part that works.
In order to achieve this I'm using an AsyncTask that gets started once the tag is scanned. The problem is now, that I am not able to stop the server when he is currently calling ServerSocket.accept(). Calling AsyncTask.cancel(true) does not stop the server while he is waiting for a connection request.
How would I go about this if I want to stop the server at some point?
Right now I'm quite clueless. My only idea was to set the timeout time for the serversocket resulting in a thrown exception. But that would mean polling ServerSocket.accept() which can't be the only way going about this? If it is, that would be a rather poor solution in my eyes...

One way is that you can call close() on the ServerSocket from another thread, which will throw a SocketException in accept().
Another is to use the timeout that you were thinking about.
See the following posts for ideas on how to implement this :
How can I interrupt a ServerSocket accept() method?
Java Stop Server Thread
Close listening ServerSocket
Stop a socket from listening on accept
How to unblock a thread blocked on ServerSocket.accept()?

Related

Best solution for waiting on response in Android?

I want to create a Android background service, which creates a notification, if a server has restarted, but I need some ideas how to implement it.
I thought about a http connection, where the background service waits until a message comes in, but I think the connection can not be keep up while a restart. After this there came up a new idea, where the background service pushes a notification, when the connection breaks.
Would this be possible (if yes, what would be the easiest way) or is there a better way to solve this?
Create an asynchronous task that tries to connect to the server in an endless loop. Use an time limit to cancel the process after a given time or return an ok value if the server responds an 200.

What is a good way to interrupt an AsyncTask if it clearly isn't finishing execution?

I have an AsyncTask which I am using to create a Socket connection. Within my doInBackground() method, I have:
Socket socket = new Socket(HOST_NAME, PORT_NUMBER);
For my case, this line of code hangs when I try to connect via a cellular network. It never finishes executing and eventually the app crashes. Because the information from the Server was necessary to me, I did something like this:
AttemptConnection attemptConnection = new AttemptConnection(); // this is the AsyncTask
attemptConnection.execute().get();
Now I realize this is bad because the purpose of AsyncTask is to run parallel to the main thread and this is halting processing on the main thread. However, my app can't really go anywhere until the information from the Server is acquired so I kind of NEED this AsyncTask to finish.
Because the Socket connection fails and hangs some times though, there are cases where this causes freezes on my device and an eventual crash of my app. So I want something better. The solution I came up with is:
attemptConnection.execute();
try {
Thread.sleep(3000);
} catch (Exception e) {
}
attemptConnection.cancel();
But I wonder if this is any better? I can't cancel the process internally because the try / catch that should catch errors with the Socket connection is never reached. The code hangs there and no errors are ever caught. But the above idea also seems like a really hacky way to do it; I'm wondering if this approach is as bad as my gut tells me it is, and if so, what are some better ways to handle this?
In general, you must code your ASyncTask so that it cannot hang indefinitely.
In your specific case, you can achieve this by specifying a timeout (of a few seconds, perhaps) when you create the Socket. This will force an exception to be thrown if the Socket connection cannot be established in a reasonable time. See Setting a timeout for socket operations for guidance on how to do this.
Of course, regardless of whether the connection succeeds or fails, you should never block your main thread waiting for the result. You should send the result from the ASyncTask through the usual way, by returning a result from doInBackground().

Background server approach

I have built an Android chat application. It has a TCP server which is connected to via using a Socket.
I want the server connection to work in the background always - even if the app is not in foreground - and listen to data sent from the server.
For now I am using a while loop to checking if there is something new, but the OS close my thread when Android needs resources.
I have thought about using the readline() method in my thread instead of using the while loop because readline() is a blocking method.
Is this the right approach to take, which will lead to, prevention of the OS from killing my application?
Is there any way, like a custom broadcast receiver that will launch only when the incoming socket is available?
Thanks!
In short, Android can and will kill any applications that hog up resources in order to keep running. The onus is on you on how to handle the scenarios which can threaten your app to be killed.
I suggest looking at the service's life-cycle as found on the developer's site.
For a start, any application, be it service/activity, that hogs up too much, in this manner is considered... "rude" in the eyes of Android, and therefore, is prepared to be killed in this manner regardless!
For example, listen in the onLowMemory override method and act accordingly, such as saving data and what-nots.
What really, should be happening, is this, the service, spawns a thread to periodically listen for incoming connections in this manner,
while (!terminating){
Socket incomingClientSocket = ourServerSocket.accept();
// How you handle this part is up to you?
Thread.sleep(500); // Sleep for 500 ms
}
The terminating variable is a boolean and is the deciding variable that controls when to terminate the loop. Notice how the Thread.sleep method is used, to "calm down" the execution, if omitted, Android will put a cross-hair on the app and terminate it, in other words, be polite to system resources.
Hint: Extend the Thread class, to hold the functionality of handling incoming connections via the accept() method.
When the incomingClientSocket becomes non-null, then another thread is created in which it opens the input/output stream of the incomingClientSocket and read/write to it using binary fashion.
Do not use the readline method as that is an indication of poor design and assuming the data is text-ual, because one incoming packet to the client could be for example, 720bytes, the next packet coming in after that, could well be 564 bytes, that is the nature of TCP/IP.
You need to come up with a more reliable way of establishing boundaries for the data transmission, for example, a begin and end marker, and let the server read the incoming data and distinguish the byte stream that composes of a begin and end markers, once both are present, then extract the real data in-between the markers and act on it accordingly.
You could for instance, say, upon incomingClientSocket that actually becomes non-null, send a broadcast to your activity to act on it, and let the activity, take that socket, and open the connection and read/write to/from the input/output streams associated with the socket.

UDP chat on android

I have a school assignment about building a UDP based chat client on android. Now, my first idea was to make an activity that starts a service and the service handle all the networking and the activity all the input an output. But a have found a problem.
If i try to start the service so that the startCommand function starts and calls the socket.receive to start receiving network message, I can not bind the service so that i can pass input from the activity to the service (input = messages that the user want to send). It just hangs and a ANR exception is thrown. If i only bind it (so that receive is never called), it works like a Charm.
Maybe I'm not approaching this problem right. Or should it work to bind the service wen it's on a blocking receive call?
I did something like this once. I took the necessary data needed to track down the other device and fed it into an asyncTask where I kicked off a Runnable that basically kept a connection going on in the background.(This way you don't have to worry about binding) I found that instead of making your own socket connections its easier just to use Apache Mina or Netty. (No need to reinvent the wheel). If you just pass the data transmissions from the session running in the background to a List or a Queue and have an asyncTask check it and update the UI accordingly you should be all set for chatting. Maybe this isn't the best way, but it worked for me. Hope some of this helps.

Android app ANR when wi-fi connectivity is lost

I'm in the middle of debugging an issue where ANR message gets displayed when wi-fi connectivity is lost. So when the application starts it has WI-Fi connectivity. The connectivity drops and during the switching from wi-fi to 3G.. no data can be fetched from the sever. In my code i catch the exception and then after a brief sleep period i try again. But the application displays ANR message and crashes. My question is where should i even begin with. what's the lead . I looked in the LOGCAT.. but it has no indication which states the application is hanging at a particular place. Any inputs from expert on this.
BTW my devise is Moto Droid Adroid 2.2
Off the top of my head two things could be the problem:
1) You could be getting an ANR because you are doing blocking IO in the UI thread. This is a bad thing as you have discovered. Your solution is to do all blocking IO in separate background threads. Even if this is not directly the case it is still best practice to do IO on a thread separate from the UI thread.
2) The socket is bound to the wifi interface. When that interface is disabled (i.e., connection is lost) that socket is useless. If you are catching exceptions and then just naively attempting to preform another operation on that socket it's going to throw another exception. This will send your application into an infinite loop of exception catching. You should check the exceptions and throw away the socket appropriately when the network interface is lost.

Categories

Resources