I am currently working on an Android application and has encountered an OutOfMemoryError on a Motorola Defy.
The place where the error occurs, is where I convert a 5MP image to a Base64 encoded string which subsequently is sent to a web service contained in a SOAP document.
I am aware, that both the actual encoding of the image, and using SOAP both are overheads - and would prefer myself to eliminate those - but that is not possible right now.
My question goes more on how to handle the large strings, being not to much into Java and Memory handling I need a little assistance.
The code is approx like this:
String soapMessage = registration.createSoapRequest();
//In this method a StringBuilder is used to build the message, and returns it
//as new String(soap.toString();
//At this point I have to objects in memory using approx 6 and 9 MB each.
//I would expect it to be the StringBuilder and the string soapMessage.
//But I can't figure out how to GC the StringBuilder - which I don't need to use
//any more.
//Declaring the entity to post
StringEntity entity = new StringEntity(soapMessage, HTTP.UTF_8);
//By declaring the entity, I receive my OutOfMemoryException, due to having
//the 6-7 MB string now replicated 3 times - giving 21 MB alone.
entity.setContentType("text/xml");
//Creating client
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://MYSERVER/services/registration.svc");
post.setHeader("Content-Type","text/xml; charset=utf-8");
post.setHeader("SOAPAction", "http://tempuri.org/IRegistration/PostRegistration");
post.setEntity(entity);
BasicHttpResponse response = (BasicHttpResponse)client.execute(post);
The obvious Memory issue here seems to make me able to only hold one instance of the string in memory.
How would I do this?
I hope somebody can help me through this as I feel stuck in Java Memory handling.
Best regards
/Anders
Related
Goal
I am writing a program where a user's input is taken as a parameter and queried against an online API.
Problem
Oddly, I cannot get my parameter into my API successfully. The error I get is
"Could not look up user information; You have an error in your SQL syntax;" Which as it says plainly , is an SQL error. Therefore I was thinking there was a problem in passing my parameter since the application works when I hard code parameter and say "select name from table where id=1".
This is the parameter code and despite many edits and changes I got the same issue which caused me to look to my php even if everything works right in the browser.
HttpParams param = new BasicHttpParams();
ArrayList<NameValuePair> inputArguments = new ArrayList<NameValuePair>();
inputArguments.add(new BasicNameValuePair("id", idnum));
HttpClient client = new DefaultHttpClient(param);
HttpPost request = new HttpPost("http://myurl.com/DAIIS/getName.php");
request.setHeader("Content-Type", "application/x-www-form-urlencoded");
request.setEntity(new UrlEncodedFormEntity(inputArguments, "UTF-8"));
HttpResponse httpResponse = (HttpResponse) client.execute(request);
Where I think the problem lie
I belives the problem lies in my select statement
<?php
header("Content-Type:application/json");
//Connect to DB
include ("dbcon.php");
//Run query
$para=$_GET['id'];
$sql=("SELECT name FROM class where stu_id=$para");
I say this because after stripping my API to the bare minimum the program's error was Could not look up user information; You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
but if i hard code the parameter (it works) or put something random like stu_id=$_GET['id']; it returns blank.
So is the way that I used this parameter incorrect for android? even if it works in the browser?
Thank you
As you asked for :
Just change '$_GET' to '$_POST',
As a side note
You can also check 'POST' request in browser, in order to do that add 'Rest client plugin' to your browser and you are done and have fun with api calls :)
Hi I am parsing data from JSON. While parsing data I am getting OUT OF MEMORY error and dalvik-heap. How to over come from this problem. and I search in net i didn't found any solution please help me.
Thanks in advance
03-06 08:19:00.618: E/dalvikvm-heap(1415): Out of memory on a 2506782-byte allocation.
JSONObject jsonObj1 = new JSONObject(jsonStr1);
ArrayList<String> matter1= new ArrayList<String>();
String stat = jsonObj1.getString(TAG_stat);
String suc=jsonObj1.getString(TAG_success);
// Getting JSON Array node
matter = jsonObj1.getJSONArray(TAG_mdata);
// looping through All Contacts
dbdata =new ArrayList<String>();
for (int i = 0; i < matter.length(); i++) {
JSONObject j = matter.getJSONObject(i);
String ddesc= j.getString(TAG_ddesc);
String spd= j.getString(TAG_sped);
String gzid=j.getString(TAG_geozid);
String dev = j.getString(TAG_devid);
matter1.add(stat);
matter1.add(suc);
Log.v("contact", ""+matter1);
dbdata.add(ddesc);
dbdata.add(spd);
dbdata.add(gzid);
dbdata.add(dev);
dbdata1.add(dbdata);
One strange thing about this is that the crash only occurs every 2nd or 3rd time the app is run, leaving me to believe that the memory consumed by the app is not being garbage collected each time the app closes.
That is certainly possible, and if it is the case then it probably due to a memory leak that can be traced back to something that your application is doing. I think you should focus your initial efforts into investigating this aspect ... rather than loading the file in chunks. (I am not familiar with the Android tool-chain, but I am sure it includes memory usage profilers or memory dump analysers.)
EDIT
In response to your followup comment, the fact that it works 2 times in 3 suggests that your app ought to work roughly as-is. Admittedly, you don't have much leeway if the input file gets bigger.
A couple of ideas though:
Rather than reading the file into a String and running the JSON parser on the String, use a parser that can read directly from a stream. Your current solution needs space for two complete copies of the data in memory while you are doing the parsing.
If the file gets much bigger, you may need to think of a design that doesn't create a complete in-memory representation of the data.
I'm not sure that it is a good idea to read a JSON file in "chunks". This could present problems for parsing the JSON ... depending on exactly what you mean by reading in chunks.
Use Gson library. Will optimize all your process.
I have a Tornado web service that returns a list to an android application as below
output = []
output.append(img_URL)
output.append(temp_folder_name)
self.finish(output)
First it assigns values to a list called "output" and then return it.
My question is how can I split this data within the Android application, I have the following two lines of code within the Android application
HttpEntity responseEntity = httpResponse.getEntity();
String transformedImageURL = EntityUtils.toString(responseEntity);
but when I try to output it (using Toast) the android application force closes. Could you please suggest me a better solution for this.
Thank you for your time.
The data between python and android will not full translate well unless you use a message passing convention. I would suggest rolling this data into lets say into JSON. Like this
output = []
output.append(img_URL)
output.append(temp_folder_name)
self.set_header("Content-Type", "application/json")
from json import dumps
self.finish(dumps(output))
On android side of things, you can use JSON library to parse data.
Seemingly simple question, but no obvious answer found online.
At this link, there is a tutorial on posting simple name value pairs to a file from within an android app. http://www.androidsnippets.com/executing-a-http-post-request-with-httpclient
What I want to do is post 'something' which on the receiving end (a php script) can be accessed as an array.
In PHP I want to receive:
$_POST['array']=array("key"=>"value","key2"=>"value2");
Being relatively new to android development, perhaps someone could elaborate on creating a similar thing in Java, and then how one cant send it - setEntity seems to only take namevaluepairs...
Many Thanks
You should use a JSON Wrapper both in Android App and your PHP server.
In PHP you should use json_decode(), like: $thingFromPost = json_decode($data).
In Java, there are many ways to create a JSONArray. A basic example would be:
List<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
JSONArray jsonArray = new JSONArray(list);
And after that, you just send your array with a HttpPost to your server.
StringEntity stringEntity = new StringEntity(jsonArray.toString());
stringEntity.setContentEncoding(new BasicHeader(HTTP.CONTENT_ENCODING, "UTF-8"));
stringEntity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
HttpPost post = new HttpPost(url);
post.setEntity(stringEntity);
post.setHeader(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
If you need a detailed tutorial how to make requests using JSON in Android, follow this link.
Hope it helps!
If you want the entire, raw body of your POST to be the stringified array (and nothing else), I believe you should use a StringEntity instead of a UrlEncodedFormEntity.
So this:
String s = "asdf"; // replace this with your JSON string
StringEntity stringEntity = new StringEntity(s);
httpPost.setEntity(stringEntity);
I am not familiar with PHP, but conceptually on the receiving end you'll then do something like json.parse(request.full_body). Note that this (request.full_body or the equivalent) is very different from the common pattern of fetching a single value of the POST form like request['input_field1'].
However, reading your question I'm not entirely sure that this full_body approach is what you want. It looks to me like you want to access the data via the form variable 'array', as you indicate here:
$_POST['array']=array("key"=>"value","key2"=>"value2");
Note that you are not working with the entire POST body here, rather instead you are fetching the value of a single form variable called 'array' (I think, I don't really know PHP). If this is the case, then you should use NameValuePairs like something below:
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("array", yourJSONArrayAsString));
This will post the array as a value associated with the form variable 'array' I believe.
I'm using JSON Framework to update the data of client side from server. I have 30 Pojo Classes and i received the Http Response from server. I create the Object of Reader by using the method
InputStream instream = entity.getContent();
reader = new InputStreamReader(instream, "UNICODE");
And i pass it in the Json Object like this
synchronizationResponse = gson.fromJson(reader, SynchronizationResponse.class);
But this line is giving outOfMemory Exception.
I write the response in a file and found the size of file is around 12MB.
So is their any way to split the response in multiple response.So that i can read and write simultaneously to avoid OOM exception.
Looking for Help
Difficult to say, as long as we do not know, what your SynchronisationResponse Class looks like.
Whatever your content, if you can split it into sub-sections, do so and serialize those.
You can use a JsonReader to parse a large stream of JSON without running out of memory. The details are in the documentation, but basically you create a JsonReader:
JsonReader reader = new JsonReader(new InputStreamReader(instream, "UNICODE"));
and write a recursive descent parser using reader.nextName() to get keys, reader.nextString(), reader.nextInt(), etc. to get values, and reader.beginObject(), reader.endObject(), reader.beginArray(), reader.endArray() to mark object boundaries.
This allows you to read and process one piece at a time, at any granularity, without ever holding the entire structure in memory. If the data is long-lived, you can store it in a database or a file.