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.
Related
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().
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()?
My app displays data from a steady stream of Bluetooth text input.
In Android 2.3.4, if I close the socket the read immediately throws an IO exception. In 2.2 is does only most of the time.
I am trying to stop the reading when onStop() is called. Then in onStart() I reconnect.
Is there a better way to kill the thread that is suspended on an inputStream read that is likely to work over all versions?
Thanks
TomZ
I tried interrupting the task and got bogged down in multiple types of exceptions depending on what it was doing at the time of the interrupt and getting compile errors that I was catching exceptions that it said could not be thrown. Even when I did get some working code, it still had reliability problems on Froyo (Galaxy S - Vibrant).
So I backed up and tried using InputStream.available in a loop with a short sleep and a check of a flag that is set to end the read task (so the task was never suspended except on the sleep). This worked great on various android versions.
It seems the trick is to not externally stop the thread but to let it detect the need to quit and return on it's own.
Seems a bit of a kludge, sort of polling the reads. But the code is now stable and the phone performance does not seem to suffer.
I have developed an app to communicate with my own server and published it. However, sometimes the app force closes. I know there is no bug in the code because the app works properly most of the time, but sometimes it is waiting for an answer from the server forever. I think this is due to the fact that so many people are using the app, and the app refreshes every 1 second or so, so this heavy traffic causes the server to take a large amount of time to respond. So how do you take care of such a use case? should I have a use case where if the server does not respond after some time you just stop the app and throw a message saying that the server is not responding or something like that?
Right now, your main application is timing out due to server load. If you put your connection details in a thread, you will be able to avoid having that main thread time out. You can check for updated data from the connection thread (through some shared object) and then present a message to the user if the data has stopped.
It sounds like you have your server communication code within your main Activity. Any code running in this Activity will be run in the main UI thread. If your code sends a request to your server, and is then waiting for a response, the main UI thread is blocked until your server responds. The Android OS recognises that the UI thread has effectively hung, and kills your app.
What you need to do is to separate out the UI code in your Activity from the server communication code. You should move this into an AsyncTask or a new Thread/Handler combination. This will allow the UI to remain responsive even when your server is under load.
Documentation for AsyncTask
Designing for Responsiveness
Android Thread Messaging
Thread example
All,
I'm developing an Android application that connects to other hardware on start up via TCP (over WiFi) . I'm pretty happy with the software that handles the connection -- it does a good job of establishing the socket connection as well as handling things when the connection is unexpectedly lost.
Unfortunately, my application currently just displays a blank, empty screen until the connection is established, and I expect that this sort of thing may produce unwarranted worry on the part of my users.
I can't figure out how to put up a start-up message informing the user that I have a towel and that there's no need to panic. Can anybody point me to a method for accomplishing this? I'll be happy with just about anything that's legible, whether graphical or textual.
Thanks,
R.
Whatever you choose, you need to get the startup screen displayed and more importantly start responding to UI events before the TCP connection is made - ie, you shouldn't do the TCP connection attempt on the UI thread, as if it takes longer than expected you may get an application not responding error.
Do the networking in AsyncTask (another thread, so it won't block the UI). Then you can display all kinds of progress indicators in the UI.
You could use a ProgressDialog. http://developer.android.com/reference/android/app/ProgressDialog.html