Vinay Pandravada Vinay Pandravada - 2 months ago 24
Java Question

HttpURLConnection Throwing OutOfMemoryError

I am making a network call as instructed in developer.android.com (by using

HttpURLConnection
). Now I am getting a out of memory exception and app is getting crashed.

The following is the stack trace:

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.app, PID: 19869
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:318)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 4294967306 byte allocation with 4056144 free bytes and 370MB until OOM
at com.example.app.webservices.HttpConnectionClass.readIt(HttpConnectionClass.java:158)
at com.example.app.webservices.HttpConnectionClass.downloadUrl(HttpConnectionClass.java:123)
at com.example.app.webservices.HttpConnectionClass.access$100(HttpConnectionClass.java:28)
at com.example.app.webservices.HttpConnectionClass$DownloadWebpageTask.doInBackground(HttpConnectionClass.java:52)
at com.example.app.webservices.HttpConnectionClass$DownloadWebpageTask.doInBackground(HttpConnectionClass.java:46)
at android.os.AsyncTask$2.call(AsyncTask.java:304)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
at java.lang.Thread.run(Thread.java:761) 


I've already included this in my manifest :

android:largeHeap="true"


This is my Networkclass:

public class HttpConnectionClass {

public static Activity context;

List json;
static boolean dialogIsShowing = true;
public String url;
List<NameValuePair> params = new ArrayList<NameValuePair>();
public void getPostResponse_WithAsyn(Activity context, String url, List json, String message) {
this.params = json;
this.url= url;
this.json = json;
Log.v("TAG","PARAMS::"+json.toString());
//add all the default parameters here
new DownloadWebpageTask().execute(url);
}

private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
// params comes from the execute() call: params[0] is the url.
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
e.printStackTrace();
return "Unable to retrieve web page. URL may be invalid.";
}
}
// onPostExecute displays the results of the AsyncTask.
@Override
protected void onPostExecute(String result) {

GetHttpPostResponse.myJsonResponse = result;

/*int maxLogSize = 1000;
for(int i = 0; i <= result.length() / maxLogSize; i++) {
int start = i * maxLogSize;
int end = (i+1) * maxLogSize;
end = end > result.length() ? result.length() : end;
Log.v("TAG_result", result.substring(start, end));
}
*/
Log.v("Connection class","Response::"+result);
}
}

private String downloadUrl(String myurl) throws IOException {
InputStream is = null;
// Only display the first 500 characters of the retrieved
// web page content.
int len =Integer.MAX_VALUE;

try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
Log.v("TAG","CONNECTING URL::"+myurl);
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);

List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("key1", ""));
params.add(new BasicNameValuePair("key2", ""));

Log.v("TAG","PARAMETERS::"+params.toString());
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(getQuery(params));
writer.flush();
writer.close();
os.close();

// Starts the query
conn.connect();

int response = conn.getResponseCode();
String res_data = conn.getResponseMessage();
Log.d("TAG", "The response is: " + res_data);
is = conn.getInputStream();

// Convert the InputStream into a string
String contentAsString = readIt(is, len);
return contentAsString;

// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
is.close();
}
}
}

private String getQuery(List<NameValuePair> params) throws IOException,UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;

for (NameValuePair pair : params) {
if (first)
first = false;
else
result.append("&");

result.append(URLEncoder.encode(pair.getName(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(pair.getValue(), "UTF-8"));
}

return result.toString();
}
public String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
Reader reader = null;
reader = new InputStreamReader(stream, "UTF-8");
char[] buffer = new char[len];
reader.read(buffer);
return new String(buffer);
}
}


And,I've Identified that "len" is the problem and tried to hardcode it but doesn't seem to work in all scenarios.

{"ResponseCode":"-1000","ResponseDesc":"Invalid user type."}�


Please help me out.

Answer

Try this readIt method,

public String readIt(InputStream stream) throws IOException, UnsupportedEncodingException {
    StringBuffer sb = new StringBuffer();
    BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
    String line;
    while ((line = br.readLine()) != null){
      sb.append(line);
    }
    br.close();
    return sb.toString();
}
Comments