Android: Http request doesn't work on 4.0 - android

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.

Related

OutOfMemory JSON Android

I'm trying to obtain an JSON answer type but is to big and at 50 MB Android Studio throw new Exception OutOfMemory
class MyClass extends AsyncTask<Void, Void, Void>
{
String result="";
#Override
protected Void doInBackground(Void... params){
HttpClient httpClient=new DefaultHttpClient();
String URL="http://82.79.121.114:1001/api/search/category/3,1,1";
try{
HttpGet httpGet = new HttpGet(URL);
httpGet.setHeader("Authorization", "Bearer " + AccesToken);
HttpResponse httpResponse=httpClient.execute(httpGet);
//Log.e("EROARE!!!!!!","EROARE!!!!!");
HttpEntity httpEntity=httpResponse.getEntity();
InputStream is=httpEntity.getContent();
result=convert(is);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid){
Toast.makeText(MainActivity.this,result,Toast.LENGTH_SHORT).show();
if(result.length() == 0 || result == null)
{
Toast.makeText(MainActivity.this,result.Toast.LENGTH_SHORT).show();
if(result.length() == 0 || result == null)
{
Toast.makeText(MainActivity.this,"Nu merge!!!",Toast.LENGTH_SHORT).show();
}
}
public String convert(InputStream is) throws IOException {
BufferedReader reader = null;
StringBuffer buffer = new StringBuffer();
try {
reader = new BufferedReader(new InputStreamReader(is,"UTF-8"),8192);
int read;
char[] chars = new char[1024];
while ((read=reader.read(chars)) != -1)
buffer.append(chars, 0, read);
}
finally {
if (reader != null)
reader.close();
}
return buffer.toString();
}
Your JSON object is simply too large, as most of the devices do not have such big heap. If you own the server-side, you should change the response you send to the clients and make it few separate responses, handled in a sequence.
In addition, I recommend you to rethink why you send so much data at once. It will take a very long time to load even on an average internet connection.
If indeed the OutOfMemory problem is related with the size of the data returned by your REST service then you are doing it wrong both on server and client side. A mobile application should care about users data traffic and also about their battery so instead of loading the entire JSON in one shot maybe you can split it in pages and load only the first page first. Once the user is interested in more (maybe you are using a ListView there to show those categories) then you load the next page and so on. Please see the Endless List Patter for Android Here:
https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews

Android HttpDefaultClient times out only after another device makes a similar but not identical request

Some quick background. We have multiple devices running a scanner app which checks against a database to see whether an id has been scanned in or not. I can scan in with Device A as many times as I like without issue. I then pick up Device B and scan in, also as many or few times as I like. If I pick Device A back up and scan, the HttpClient will hang for approximately 60 seconds refusing to send any further requests. The code below has commented the point of failure.
// Asynchronous get request
private class aGETRequest extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
client.setKeepAliveStrategy(null);
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse httpResponse = client.execute(httpGet); //Hangs Here
HttpEntity httpEntity = httpResponse.getEntity();
InputStreamReader isr = new InputStreamReader(httpEntity.getContent());
BufferedReader buffer = new BufferedReader(isr);
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
httpEntity.consumeContent();
isr.close();
} catch (Exception e) {
e.printStackTrace();
}
httpGet.abort();
client.getConnectionManager().shutdown();
}
return response;
}
#Override
protected void onPostExecute(String result) {
results(result);
}
}
The client hangs and even snooping traffic shows no requests sent at all from Device A after the failure. You ready for the best part? If the devices are going through a Proxy server, it works. W.T.F?
Android is java 6 compat . right.
BufferedReader on java 7 makes me nervous and the while read loop appears to be whats hanging.....
I would try a different different read loop class thats solid on java 6 or i would find someone else's pattern for httpclient that's solid.
My wild guess is that your code is never getting out of the following...
while ((s = buffer.readLine()) != null)
Maybe the server is returing chunked encoding or something like that with a diff protocol ( pattern of length=0 followed by \r\n or something.

Android application force Close on lowsy Internet connection

I have the following code for to perform xml download via asynctask for android application targeting for android version>3. The code work pretty good if the network/internet connection is good. However, if internet connection is not good, the application will force close. I have tried throw in different kind of error catching but still unable to solve the force close on lowsy internet connection.
Anyone has any suggestion that I can try
private class DownloadWebPageXML extends AsyncTask<String, Void, InputStream> {
#Override
protected InputStream doInBackground(String... urls) {
Log.d("mylogitem", "AsyncTask started!");
InputStream content = null;
String myurl = urls[0];
AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
HttpGet httpGet = new HttpGet(myurl);
try {
HttpResponse execute = client.execute(httpGet);
content = execute.getEntity().getContent();
} catch (Exception e) {
xmldownloaderror = e.getMessage();
Log.d("mylogitem", e.getMessage());
} finally {
Log.d("mylogitem", "Closing AndroidHttpClient");
client.close();
}
return content;
}
#Override
protected void onPostExecute(InputStream result) {
//do xml reader on inputstream
}
}
add a null check on variable execute, in between these two lines
HttpResponse execute = client.execute(httpGet);
if(execute == null){ return null;} // null check to see if execute is null
content = execute.getEntity().getContent();
another thing in onPostExecute, first line should check if InputStream result is null!
#Override
protected void onPostExecute(InputStream result) {
if(result == null){
Log.d("TEMP_LOG",Content is null);
return;
}
//do xml reader on inputstream
}
check and post your findings
hmm... I recommend to set connection times.
HttpClient client = new DefaultHttpClient();
HttpResponse response;
BufferedReader bufferedReader = null;
HttpParams params = client.getParams();
HttpConnectionParams.setConnectionTimeout(params, 20000);
HttpConnectionParams.setSoTimeout(params, 20000);
I have found the root cause. It is not in the dobackground.
In my case, lousy connection will sometime return not xml data type but rather loading error,
and this is passed as the inputstream to my xmlparser in postexecute.
I did not put in much error catcher in my xmlparser. xmlparser is expecting xml document but received non-xml content, thus throwing null in which i did not cover with error catcher.
Thank you for the suggestion. I have place it in my code as well.

getting JSON feed working inside AsyncTask but not in oncreate

Hello I have to fetch a JSON feed and that's why I am using this code:
try {
DefaultHttpClient httpclient = new DefaultHttpClient(
new BasicHttpParams());
HttpGet httpget = new HttpGet(CommonUtils.URL);
httpget.setHeader("Authorization", "Bearer " + CommonUtils.BEARER_TOKEN);
httpget.setHeader("Content-type", "application/json");
InputStream inputStream = null;
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
inputStream = entity.getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream, "iso-8859-1"), 8);
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
inputStream.close();
} catch (Exception e) {
Log.e("GetFeedTask", "Error:" + e.getMessage());
}
This is working when I used this code inside AsyncTask and call it in onCreate() but is not working and throw Exception GetFeedTask when I call it directly in onCreate(). What's the problem?
Logcat:
GetFeedTask Error: null
By running the code directly in onCreate() you are attempting to do network communications on the UI thread. Android does not allow networking on the main thread and will throw a android.os.NetworkOnMainThreadException. You are catching a type Exception which is for all run time errors - otherwise your program would crash with the above as the reason. It is not the best practice to catch all Exception as you may have a failure mode other than the one you are protecting against that will cause problems if the program continues.
You should remain using the AsyncTask and it will work

Slow Internet connection leads to force close

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

Categories

Resources