Memory leak with Android app? - android

I have a simple Android app that reads some JSON data from a php file on my local server. It's very simple and up until about an hour ago it was working fine. However, after a little break (I didn't even turn my PC off), it's suddenly struggling with what seems like a memory leak, although I'm no expert on the subject.
I'm not sure why all of a sudden this is happening, as I didn't change any code. But when I run the app my logcat slowly starts to fill with messages like this:
"GC_CONCURRENT freed, 910K, 53% free 3167K/6727K....."
The app eventually runs, but only after about 1-2 minutes of waiting. Anyway, I was wondering if someone could check my code or advise me what maybe causing this to happen.
public static JSONArray getJSONfromURL(String url) {
// initialize
InputStream is = null;
JSONArray jArray = null;
String result = "";
// http post
try {
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, "utf-8"), 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());
}
// try parse the string to a JSON object
try {
jArray = new JSONArray(result);
} catch (JSONException e) {
Log.e("log_tag", "Error parsing data " + e.toString());
}
return jArray;
}
The JSON data isn't very large at all.
Thanks for any advice.

BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "utf-8"), 8);
You've allocated a buffer size of 8 bytes. That is very small. Unless you really know what you're doing, just use the default size with the alternative single-argument constructor:
public BufferedReader(Reader in)

Well I changed the 'While' loop to this and performance increased dramatically:
int len;
char[] chars = new char[4*1024];
while((len = reader.read(chars))>=0) {
sb.append(chars, 0, len);
}
It's still slower than I'd like, but at least I'm heading in the right direction. I'm going to work on it some more. Thanks everyone.

Related

How to handle 500 Internal Server Error when using JSON

I am relatively new to Android and I am using JSON to get data from a server. On the first loop at line 22, the StringBuilder contains, 500 Internal Server Error and then the jArray ends up coming back null. How can I handle this error?
public static JSONObject getJSON() {
String jsonString = "";
InputStream inStream = null;
//http post
JSONObject jArray = null;
try {
HttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());
HttpPost httpPost = new HttpPost(WS_URL);
httpPost.setHeader("Content-type", "application/json");
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
inStream = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
inStream.close();
jsonString = sb.toString();
jArray = new JSONObject(jsonString);
//outputTransactions(jArray);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return jArray;
}
Though its a late reply but it might help others. You need to check the response status from the server before parsing it as JSON.
For ex.
int status_code=response.getStatusLine().getStatusCode();
if(status_code!=200){
Log.d("MYLOG","ERROR! Response status is"+status_code);
}
else{
inStream = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
inStream.close();
// Rest of your code......
}
or Optionally you can check the status code and display the error to the user
Like:
else if(status_code==404){
Log.d("MYLOG","Sorry! Page not found! Check the URL ");
}else if(status_code==500){
Log.d("MYLOG","Server is not responding! Sorry try again later..");
}
Hope it helps for newbies like you :-)
A "500 Internal Server" error means the server had a problem responding to your request. You are not getting a JSON string response.
Then when you try to create your jArray, the string is not valid JSON and the JSONObject cannot parse it - it returns "null" as you say.
You can parse the server response to see if it contains this string, and then create whatever jArray object you want, but you can't get a JSON object from a non-JSON string.
Take a look at this answer: https://stackoverflow.com/a/8148785/1974614
You should check the statusCode against 500
You should consider use a library to handle the REST requests like: http://square.github.io/retrofit/
If you use a library like that you can get an object from json when a success response is available and other when an error occur.
MyApi mylogin = restAdapter.create(MyApi.class); //this is how retrofit create your api
mylogin.login(username,password,new Callback<String>() {
#Override
public void success(String s, Response response) {
//process your response if login successfull you can call Intent and launch your main activity
}
#Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace(); //to see if you have errors
}
});
}
I got the same problem like you and I solved it because I missed a part while adding GSON .jar files to adding my serverside project. I think you should carrefully add external libraries to your project too like me.With these links I could aware of problem .
LINK 1
LINK 2

Require Help while Reading huge data (7MB or more) from Httpclient in Android

Require your Help for fetching the json response from the httpclient in Android since the following code mentioned is making the Application to crash on android Devices particularly on the GingerBread device , since the JSON Response is very huge in size (may be 7 MB) .
So I wanted to know any alternative way for reading the JSONresponse from the Httpclient, since the present implementation is consuming too much of memory and making my application to crash on lower end devices.
It would be very greatful for any suggestions or help for solving this problem .
HttpClient httpClient = new DefaultHttpClient(ccm, params);
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Cache-Control", "no-cache; no-store");
HttpResponse httpResponse = httpClient.execute(httpGet);
response = Utils.convertStreamToString(httpResponse.getEntity().getContent());
public static String convertStreamToString(InputStream is)
{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
//System.gc();
sb.append(line).append("\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
You can use Google Volley for you networking. Among a lot of other things, it has a built in method to retrieve JSON objects, regardless of size.
Give it a try.
You could try this:
public static String convertStreamToString(InputStream is)
{
try
{
final char[] buffer = new char[0x10000];
StringBuilder out = new StringBuilder();
Reader in = new InputStreamReader(is, "UTF-8");
int read;
do
{
read = in.read(buffer, 0, buffer.length);
if (read > 0)
{
out.append(buffer, 0, read);
}
} while (read >= 0);
in.close();
return out.toString();
} catch (IOException ioe)
{
throw new IllegalStateException("Error while reading response body", ioe);
}
}
Google Android ships with an extremely outdated fork of Apache HttpClient. However, the base principles still apply. The most efficient way of processing HTTP responses with Apache HttpClient is by using a ResponseHandler. See my answer to a similar question for details

android - error while parsing JSON response from server

I'll try be to brief, please ask if something is unclear. I'm getting a user's audio list from vk.com (a large social network in case someone doesn't know). The response looks like:
{"response":[{
"aid":"60830458","owner_id":"6492","artist":"Noname","title":"Bosco",
"duration":"195","url":"http:\/\/cs40.vkontakte.ru\/u06492\/audio\/2ce49d2b88.mp3"},
{"aid":"59317035","owner_id":"6492","artist":"Mestre Barrao","title":"Sinhazinha",
"duration":"234","url":"http:\/\/cs510.vkontakte.ru\/u2082836\/audio\/
d100f76cb84e.mp3"}]}
Usually it is much longer since a user can have hundreds or even thousands of tracks on his profile. Artist and title can also contain cyrillic letters, that's why I used UTF-8 in the Parser. I'm not really familiar with JSON, I'm trying to parse the response using the following:
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
public JSONParser() {
}
public static JSONObject getJSONFromUrl(String url) {
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
return jObj;
}
}
But the app crashes with an IllegalArgumentException exception (Illegal character in scheme at index 0):
02-27 10:37:35.870: E/AndroidRuntime(21038): FATAL EXCEPTION: main
02-27 10:37:35.870: E/AndroidRuntime(21038): java.lang.RuntimeException: Unable to resume activity {com.vadim.android.vk_player/com.vadim.android.vk_player.MainActivity}: java.lang.IllegalArgumentException: Illegal character in scheme at index 0: {"response":[{"aid":191819427,"owner_id":13590837,"artist":"Buena Vista Social Club","title":"El Cuarto de Tula","duration":445,"url":"http:\/\/cs548.userapi.com\/u361189\/audios\/b8c6a3bdb0bb.mp3","lyrics_id":"1133390"},{"aid":191477921,"owner_id":13590837,"artist":"Buena Vista Social Club","title":"Hasta Siempre Comandante Che Guevara","duration":193,"url":"http:\/\/cs4515.userapi.com\/u7198823\/audios\/5fafa2136e16.mp3","lyrics_id":"2876258"},{"aid":190900891,"owner_id":13590837,"artist":"Slade","title":"Oh la la in L.A.","duration":229,"url":"http:\/\/cs4962.userapi.com\/u9811745\/audios\/ed7445d38bef.mp3"},{"aid":188976833,"owner_id":13590837,"artist":"PR-MEX","title":"У Билли Гейтса","duration":126,"url":"http:\/\/cs5002.userapi.com\/u4693819\/audios\/a1899ebb7716.mp3","lyrics_id":"5201762"},{"aid":186998450,"owner_id":13590837,"artist":"The Best Latino Dance","title":"2Sweet-Bomba Latina","duration":213,"url":"http:\/\/cs4341.userapi.com\/u49441496\/audios\/788cd8243842.mp3"},{"aid":186486990,"owner_id":13590837,"artist":"001 Track No05 Latin music 9","title":"001 Track No05 Latin music 9","duration":226,"url":"http:\/\/cs4341.userapi.com\/u25293142\/audios\/277e46d451d4.mp3"},{"aid":185813300,"owner_id":13590837,"artist":"Латино ?? ","title":" Самбо","duration":190,"url":"http:\/\/cs4206.userapi.com\/u2183525\/audios\/678fe97a8700.mp3","lyrics_id":"4944025"},{"aid":185805191,"owner_id":13590837,"artist":"Дженифер Лопес","title":"Латино","duration":212,"url":"http:\/\/cs4220.userapi.com\/u33799853\/audios\/685f4bc7024d.mp3","lyrics_id":"3985793"},{"aid":185355131,"owner_id":13590837,"artist":"Latino","title":"Afa-Na-Na","duration":174,"url":"http:\/\/cs548.userapi.com\/u406078\/audios\/5e771c6958c4.mp3","lyrics_id":"8840070"},{"aid":185167860,"owner_id":13590837,"artist":"Batuka-Latino_StepMIX(137bpm)","title":"demo","duration":232,"url":"http:\/\/cs4863.userapi.com\/u43189860\/audios\/b6a08490146a.mp3","lyrics_id":"10200160"},{"aid":185143167,"owner_id":13590837,"artist":"Pr, Mex","title":"Ставил Windows программист","duration":130,"url":"http:\/\/cs4246.userapi.com\/u3476823\/audios\/75161ed38448.mp3","lyrics_id":"2012814"},{"aid":185141056,"owner_id":13590837,"artist":"Antony Melnyk, Sergiy Tykhanskyy ","title":"Debugging Song","duration":234,"url":"http:\/\/cs6126.userapi.com\/u42350435\/audios\/f83f20d8d754.mp3","lyrics_id":"36053942"},{"aid":185141033,"owner_id":13590837,"artist":"админ","title":"чистый дос","duration":173,"url":"http:\/\/cs4429.userapi.com\/u9853602\/audios\/2b77464f9193.mp3"},{"aid":184547392,"owner_id":13590837,"artist":"Geri Halliwell","title":"Mi chico latino (samba)","duration":194,"url":"http:\/\/cs5057.userapi.com\/u8186180\/audios\/67119f2af914.mp3"},{"aid":184022338,"owner_id":13590837,"artist":"Elena Paparizou","title":"My number one","duration":176,"url":"http:\/\/cs1092.userapi.com\/u830723\/audios\/25552d1f7e40.mp3","lyrics_id":"6640643"},{"aid":183519519,"owner_id":13590837,"artist":"Latino - Samba - Elena Paparizou","title":"Gigolo","duration":203,"url":"http:\/\/cs4405.userapi.com\/u3609345\/audios\/5255ecdda950.mp3","lyrics_id":"7216473"},{"aid":183219402,"owner_id":13590837,"artist":"David Bisbal ","title":" Llorare las penas (самба)","duration":260,"url":"http:\/\/cs5003.userapi.com\/u32245826\/audios\/fe718c40aed1.mp3"},{"aid":183110662,"owner_id":13590837,"artist":"Juanes","title":"La soledad","duration":193,"url":"http:\/\/cs4615.userapi.com\/u400878\/audios\/40abd9dcb4f5.mp3","lyrics_id":"7753114"},{"aid":180455728,"owner_id":13590837,"artist":"Guns N' Roses","title":"Sweet Child O' Mine","duration":356,"url":"http:\/\/cs5125.userapi.com\/u1412326\/audios\/1fc190388445.mp3","lyrics_id":"5582681"},{"aid":180317426,"owner_id":1359083
Any ideas what I'm doing wrong and what would be the correct way to parse the response of given format? There are a lot of apps using the same API so the JSON is correct.. No clue what's wrong here
Illegal Argument Exception comes in JSON case while reading it. So invalid json because of those urls. Also for next communication, place the logcat as the text pls.
Try to display the JSON response in JSONlint.com without this url part of :
"url": "http:\/\/cs510.vkontakte.ru\/u2082836\/audio\/
d100f76cb84e.mp3"
You will find, the response will be validated properly.
I think there is some space characters present in the url part (between audio\/ and d100f76cb84e.mp3) which is coming from response:
"url": "http:\/\/cs510.vkontakte.ru\/u2082836\/audio\/
d100f76cb84e.mp3"

How do I use the command: HttpEntity?

I wish to settle my long term problem by this question and hope you guys would help, but firstly; I have been having issues to connect to a HTTPS self-signed certificate server for almost 3 weeks. Despite the multiple solutions here, I cannot seem to resolve my problem. Probably I did not know how to use it properly or did not have some files or imported the correct libraries.
I came across some websites that requires me to download a certificate from the https site that I am trying to connect into, and when I did that. I have to do the some steps before I can use the certificate or keystore that I created. I got this solution from this website:
Android: Trusting SSL certificates
// Instantiate the custom HttpClient
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://www.mydomain.ch/rest/contacts/23");
// Execute the GET call and obtain the response
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();
I have a problem, after the last line, as stated above. What do I do with the responseEntity? How do I use it if I wish to display the https website on a WebView? Some help and explanation would be nice :)
If you want the content from the HttpEntity the correct way does not include calling HttpEntity#getContent() to retrieve a stream and doing tons of pointless stuff already available in the Android SDK.
Try this instead.
// Execute the GET call and obtain the response
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();
// Retrieve a String from the response entity
String content = EntityUtils.toString(responseEntity);
// Now content will contain whatever the server responded with and you
// can pass it to your WebView using #loadDataWithBaseURL
Consider using WebView#loadDataWithBaseURL when displaying content - it behaves a lot nicer.
You need to call responseEntity.getContent() to get response in InputStream against your requested URL. Use that stream in your way to present data as you want. For example, if the expected data is String, so you may simply convert this stream into string with the following method:
/**
* Converts InputStream to String and closes the stream afterwards
* #param is Stream which needs to be converted to string
* #return String value out form stream or NULL if stream is null or invalid.
* Finally the stream is closed too.
*/
public static String streamToString(InputStream is) {
try {
StringBuilder sb = new StringBuilder();
BufferedReader tmp = new BufferedReader(new InputStreamReader(is),65728);
String line = null;
while ((line = tmp.readLine()) != null) {
sb.append(line);
}
//close stream
is.close();
return sb.toString();
}
catch (IOException e) { e.printStackTrace(); }
catch (Exception e) { e.printStackTrace(); }
return null;
}
InputStream is = responseEntity.getContent();
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
sb.append(reader.readLine() + "\n");
String line="0";
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
String result=sb.toString();
is.close();
}catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
you will have all the content in the String "result"

Android app using data from webservice

I want to write an Android application that can display some data received(polled) from an internet resource.
I guess that I need to write some logic that will periodically call and get data from some endpoint, parse the response and display it. Is there a good tutorial for all this steps?
I know very little about Android programming at the momment and maybe it is better to start with something simpler. I just want to know what to look for while learning an gather some resources on this.
What you want to do is developing a rest api that provides data for your android app. E.g. you website has some content that you want use in your app, then you could write a php script that just returns that data in a specific format.
E.g. mysite.net/rest/fetchAllLocations.php?maybe_some_parameters
This would return locations in e.g. json format, here is an example how that looks like:
[{"id":1,"shop_lng":8.5317153930664,"shop_lat":52.024803161621,"shop_zipcode":33602,"shop_city":"Bielefeld","shop_street":"Arndtstra\u00dfe","shop_snumber":3,"shop_name":"M\u00fcller","shop_desc":"Kaufhaus"}]
Here is an example for a rest api request:
http://shoqproject.supervisionbielefeld.de/public/gateway/gateway/get-shops-by-city/city/Bielefeld
So when you have your rest api set up you can deal with receiving that data with your android phone. I use a static method to get this data:
public class JsonGrabber{
public static JSONArray receiveData(){
String url = "your url";
String result = "";
DefaultHttpClient client = new DefaultHttpClient();
HttpGet method = new HttpGet(url);
HttpResponse res = null;
try {
res = client.execute(method);
} catch (ClientProtocolException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
try{
InputStream is = res.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"));
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());
}
JSONArray jArray = null;
try{
jArray = new JSONArray(result);
}catch(JSONException e){
Log.e("log_tag", "Error parsing data "+e.toString());
}
return jArray;
}
}
Well thats all, once you have your data in json format you just have to parse it:
JSONArray test = (JSONArray) JsonGrabber.receiveData()
try {
for(int i=0;i<test.length();i++){
JSONObject json_data = test.getJSONObject(i);
int id = json_data.getInt("id");
}
}
The web request should run in another thread, because it can be a time consuming process. So you need to deal with AsyncTask. Here are some resources:
Painless Threading
Multithreading for performance
Hello Android Tutorial

Categories

Resources