Slow Internet connection leads to force close - android

I am developing an android application where in each activity i need to pass some data onto the server and get back the responses before going to the next activity. The application works fine if the internet is fast enough. But as the speed goes down the application force closes. How to deal with slow internet connection so that it might not lead to force close of application?????
Here is some part of code
public void onClick(View v) {
// TODO Auto-generated method stub
UserFunctions userFunction = new UserFunctions();
if(userFunction.isNetworkAvailable(getApplicationContext()))
{
answer="";
for(int check1=0;check1<counter2;check1++){
int check2=0;
answer=answer+option4[check1]+"|";
while(check2<counter1){
if(edTxt[check1][check2].getText().toString().equals("")){
answer="";
break;
}
else{
answer=answer+edTxt[check1][check2].getText().toString()+"|";
}
check2++;
}
if(answer.equals("")){
break;
}
else{
answer=answer+"||";
}
}
if(answer.equals("")){
Toast.makeText(this, "Please fill all fields", 600).show();
}
else{
userFunction.form1(surveyId,userId , quesNo, answer);
if(total>0){
draw(temp);
}
else{
ques_no++;
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("quesNo", Integer.toString(ques_no)));
params.add(new BasicNameValuePair("surveyId", surveyId));
count = getJsonFromURL22(surveyCond, params);
j=Integer.parseInt(result);
if(j==22)
{
Toast.makeText(this, "Survey Completed", 600).show();
Intent home=new Intent(Format16.this, SurveyCompleted.class);
UserFunctions userFunctions = new UserFunctions();
userFunctions.full(surveyId);
Bundle d=new Bundle();
d.putString("userId", userId);
home.putExtras(d);
startActivity(home);
}
public String getJsonFromURL22(String url, List<NameValuePair> params){
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
httppost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection"+e.toString());
}
//convert response to string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
sb = new StringBuilder();
sb.append(reader.readLine());
String line="0";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
is.close();
result=sb.toString();
}catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
return result;
}

Since you have not shown any code, I am guessing you are targeting Android API level 10 or lower, and you are doing all the networking in the UI thread, resulting in the dreaded App Not Responding(ANR) error. One way to fix the problem would be to use AsyncTask and move all your networking code in there. When done right, AsyncTask's doInBackground() will process all your networking in a separate thread, allowing the UI to remain responsive.
It usually works something like this:
private class NetworkTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
// Do all networking here, this will work away in a background thread.
// In your case:
// HttpResponse response = httpclient.execute(httppost);
// Must happen here
}
#Override
protected void onPostExecute(String result) {
// dismiss progress dialog if any (not required, runs in UI thread)
}
#Override
protected void onPreExecute() {
// show progress dialog if any, and other initialization (not required, runs in UI thread)
}
#Override
protected void onProgressUpdate(Void... values) {
// update progress, and other initialization (not required, runs in UI thread)
}
}
If you enable StrictMode, or target api versions 11 and higher, Android will throw a NetworkOnMainThreadException when you try to do this.

The application works fine if the internet is fast enough. But as the
speed goes down the application force closes.
It clearly indicates that you are doing network operation on UI Thread.As per Google Docs if the Asynchronous operation is performed on Main thread and if it is taking more than 5 seconds then your application will show force close dialog which is very unpleasent for end user.
In-fact if you try to run such application on latest android version (i.e 4.0 or later) It will not allow you to run application it will crash at start as soon as it detects that the asynchronous operation is performed on main thread.
You must use AsyncTask or Handlers to perform long running application.
Go through following blog to know more.
http://android-developers.blogspot.in/2010/07/multithreading-for-performance.html

That must be ANR issue not the Force Close issue.
You can use StrictMode to help find potentially long running operations such as network that you might accidentally be doing your main thread.
Or else try to put progress bar.

use setConnectionTimeout or setSoTimeout for handling connection timeout.
HttpGet httpGet = new HttpGet(url);
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used.
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
and use AsyncTask or Handler or HandlerThread or runOnUiThread anyone for getting data from Server(to perform long running task in background).

You should take a look at this tool that allows you to see what is causing the slow down in your application. The ARO tool is designed to diagnose these sorts of network problems http://developer.att.com/developer/forward.jsp?passedItemId=9700312

Related

Android make a http request and ignore response

I'm developing a program that sends some Logs to a database.
As logs, the main idea is to save as much information as it can, I want to avoid the part if the server where I store logs is down. What I'm trying to do is to make an http request and totally ignore server response, it doesn't matter if is online or offline. What I'm done so far is to set a timeout to my request but that doesn't resolve my problem. Here is my code:
public synchronized void LOG_sendERROR(String token, String channelnumber, String type)
{
HttpResponse response = null;
HttpParams httpParameters = new BasicHttpParams();
int timeout = 3000;
HttpConnectionParams.setConnectionTimeout(httpParameters,timeout);
int timeoutsocket = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutsocket);
DefaultHttpClient httpclient = new DefaultHttpClient(httpParameters);
try
{
if (ep.getString("username", "").length() == 0)
return ;
String url = Server.Log_Server + "/LOG_CHANNEL_LOGS.aspx?params=1";
log.i("LOGS", url);
HttpGet c = new HttpGet(url);
response = httpclient.execute(c);
return ;
}
catch (Exception e)
{
e.printStackTrace();
try
{
if (response != null)
response.getEntity().consumeContent();
}
catch (Exception f)
{
}
return ;
}
}
If server is down my application stuck for 3 seconds. I want to send the logs, it doesn't matter for the client application to know whether the server saved the logs the client just send. How can I make a http request and ignore response?
After i tried many methods, the best way is to execute as a parallel task. In this way client wont ignore the response of the server but at least the application will be running normaly.
private Runnable LOG_CHANNEL_LOGS = new Runnable()
{
public void run()
{
new LOG_CHANNEL_LOGS().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
};

Launch multiple tasks consecutively

I want to save certain information via http. This information is continuously stored in a local database (sqlite) and just keep it in the server (HttpPost) every so often.
How I can save that information releasing tasks individually by each data from my table? If possible an orderly manner.
Thus I launch a task and works perfectly (the code is generic, of course)
(I hope my english is right)
void SaveDataOnServer()
{
String data = db.getFirstData();
task = new SaveItemTask();
task.execute(data);
//if I have, say, 5 data, it would be nice to launch 5 row consecutive (for, while...)?
}
public class SaveItemTask extends AsyncTask<String, Void, Boolean>
{
protected Boolean doInBackground(String... param)
{
...
HttpClient client = new DefaultHttpClient();
HttpPost consult = new HttpPost(url + "?x=" + param[0]);
//making an HTTP POST request
try
{
HttpResponse response = client.execute(consult);
HttpEntity entity = response.getEntity();
...
}
catch...
}
....
#Override
protected void onPostExecute(final Boolean success)
{
...
if (success)
{
//Update row (set saved onserver=true)
}
...
}
http://developer.android.com/reference/android/os/AsyncTask.html
The task can be executed only once (an exception will be thrown if a
second execution is attempted.)
So either you re-create your SaveItemTask object every time, either you modify SaveItemTask in order to perform the HttpPost a target number of times.

Creating an HTTP connection via Android

I am creating an HTTP client to execute a PHP file in my server and this is the code:
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://yasinahmed.cpa10.com/sendnoti.php");
HttpResponse response = httpclient.execute(httppost);
Toast.makeText(GCMMainActivity.this, "Done", Toast.LENGTH_LONG).show();
}
catch(Exception e)
{
Toast.makeText(GCMMainActivity.this, "error", Toast.LENGTH_LONG).show();
}
Many times I used this code and it's working without a problem, but this time when I execute the code it always go to the exception and prints the error. This time, I used AVD with Google API level 17, so is this the problem or is there another problem in the code?
This exception is thrown when an application attempts to perform a networking operation on its main thread. Run your code in AsyncTask:
class Preprocessing extends AsyncTask<String, Void, Boolean> {
protected Boolean doInBackground(String... urls) {
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://yasinahmed.cpa10.com/sendnoti.php");
HttpResponse response = httpclient.execute(httppost);
return true;
}
catch(Exception e)
{
return false;
}
}
protected void onPostExecute(Boolean result) {
if(result)
Toast.makeText(GCMMainActivity.this, "Done", Toast.LENGTH_LONG).show();
else
Toast.makeText(GCMMainActivity.this, "error", Toast.LENGTH_LONG).show();
}
}
Call this class in your Activity:
new Preprocessing ().execute();
Don't forget to add this to AndroidManifest.xml file:
<uses-permission android:name="android.permission.INTERNET"/>
It would help to know the error. But since I have to guess, my bet is that you are trying to execute this code on the main event thread (a.k.a. the UI thread). That was always wrong and as of API level 11, it will cause a NetworkOnMainThreadException to be thrown. See the document Designing for Responsiveness for the proper way to handle networking in Android.

Android: Http request doesn't work on 4.0

I tested this code and it works fine on 2.2 and 2.3.3, but it crashes on 4.0.
The problem seems to be with the http request. Any ideas why?
public class Rezultat extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
//http post
InputStream is=null;
try{
String url="http://google.com";
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection "+e.toString());
}
//convert response to string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
}catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
e.printstacktrace() will tell you:
http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
The exception that is thrown when an application attempts to perform a
networking operation on its main thread.
This is only thrown for applications targeting the Honeycomb SDK or
higher. Applications targeting earlier SDK versions are allowed to do
networking on their main event loop threads, but it's heavily
discouraged. See the document Designing for Responsiveness.
private class DownloadFromUrlTask extends AsyncTask<String, Void, Bitmap> {
protected void onPreExecute() {
mDialog = ProgressDialog.show(ChartActivity.this,"Please wait...", "Retrieving data ...", true);
}
protected String doInBackground(String... urls) {
//All your network stuff here.
return result
}
}
You're performing a (potentially slow) network operation on the main thread. If your target SDK is 11 or higher this will throw a NetworkOnMainThreadException , because this behaviour can block the UI and lead to an unresponsive app.
You could use an AsyncTask to get around this, loading the data in its doInBackground(..).
You should normally post your stack trace when asking about a crash but in this case you're doing network operations on the main UI thread. This is not recommended and now throws an exception. Instead do it in another thread, perhaps via an AsyncTask.

Do POST request with Android DefaultHTTPClient cause freeze on execute()

I need post data to server.
I use this code:
HttpClient client = new DefaultHttpClient();
try {
HttpPost httppost = new HttpPost(serverUrl);
StringEntity se = new StringEntity(data);
httppost.setEntity(se);
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Content-type", "application/json");
// Execute HTTP Post Request
HttpResponse response = client.execute(httppost);
int statusCode = response.getStatusLine().getStatusCode();
Log.i(TVProgram.TAG, "ErrorHandler post status code: " + statusCode);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (client != null) {
client.getConnectionManager().shutdown();
}
}
But problem is that Android freeze on execute() method, application is blocked out and after some time Android tell me that application doesn't respond.
I tried to debug into SDK classes and it freeze in AbstractSessionInputBuffer class on the line 103 which is
l = this.instream.read(this.buffer, off, len);
I also tried it run the request in separated thread, but the same problem.
I tested it on Android 2.1 (emulator) and Android 2.2 real mobile device.
I also tried to set HTTP proxy and use Fiddler to check HTTP communication data are received by server and server also send correct answer and HTTP code 200. All seems to be ok.
What is wrong please?
UPDATE: When I use AndroidHttpClient which is part of Android 2.2 SDK it works great. But it is not in earlier version of Android. So I include it's source code in my app for now. But AndroidHttpClient use DefaultHTTPClient internally, so problem will be in configuration of DefaultHttpClient.
I am using a POST HTTP request successfully. Here is my code. I removed pieces using handler to display messages etc. and the handler itself.
The POST string is like "&NAME=value#NAME2=value2"...
protected class ConnectingThread implements Runnable
{
Message msg;
private Handler mExtHandler;
private String mData;
private String mUrl;
/**
* #param h (Handler) - a handler for messages from this thread
* #param data (String) - data to be send in HTTP request's POST
* #param url (String) - URL to which to connect
*/
ConnectingThread(Handler h, String data, String url) {
mExtHandler = h;
mData = data;
mUrl = url;
}
public void run() {
try {
// TODO use the handler to display txt info about connection
URL url = new URL(mUrl);
URLConnection conn = url.openConnection();
conn.setConnectTimeout(CONN_TIMEOUT_MILLIS);
conn.setDoOutput(true);
BufferedOutputStream wr = new BufferedOutputStream(conn.getOutputStream());
wr.write(mData.getBytes());
wr.flush();
wr.close();
String sReturn = null;
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
int length = conn.getContentLength();
char[] buffer = new char[length];
int read = rd.read(buffer);
if(read == length)
sReturn = new String(buffer);
rd.close();
buffer = null;
// TODO use the handler to use the response
} catch (Exception e) {
//....
}
// TODO use the handler to display txt info about connection ERROR
}
}
Isn't client.execute(httppost); synchronous ?
You probably need to put this in a thread, else it will freeze the UI.
Yes it is being freezed just becoz you haven't implemented this as Asynchronous process. Because while it makes web request, your UI will wait for the response and then it will be updated once the response is received.
So this should be implemented as Asynchronous process, and user should be notified (with progress bar or progress dialog) that there is something happening.
Now, Instead of implementing Runnable class, in android its preferrable and recommended to use AsyncTask, its also known as Painless Threading.
Do you background tasks inside the doInBackground() method.
Do your display type of operations inside onPostExecute() method, like updating listview with fetched data, display values inside TextViews....etc.
Display ProgressBar or ProgressDialog inside the onPreExecute() method.
Use AndroidHttpClient helped me in this situation.
But now complete AndroidHttpClient and DefaultHttpClient are obsolete in current version of Android so it is not important now.

Categories

Resources