How to handle huge data response from server in android - android

I am using eclipse ADT for my android development. let me explain my problem. I can receive the response from my server api, the problem is, the data is very huge and am unable to display entire response in my logcat. I used AsynTask for getting response.
DoinBackground method
getBookingResults = ServerConnection.getbookings(
BookingsActivity.this, Utils.URL + "users/"
+ "123145/" + "subscribed");
This is my Get() in separate class
public static String getData(Context ctx, String uri) {
BufferedReader reader = null;
StringBuilder sb = null;
try {
Log.d("Serverconnection URL ", uri);
URL url = new URL(uri);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(200000);
// save status code
Utils.statusCode = con.getResponseCode();
// String responseBody = EntityUtils.toString(response.getEntity());
sb = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
Log.d("server connection getData", "" + sb.toString());
return sb.toString();
} catch (SocketTimeoutException e) {
Log.d("server connection getData Error ", "" + e);
} catch (IOException e) {
e.printStackTrace();
return " ";
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
return " ";
}
}
}
return sb.toString();
}
When i am checking the response string in my logcat is shows string length 11743. The logcat is not displaying entire response
Help me out to handle huge data response
Thanks in advance

Thing is that you cannot blindly allocate all the data from server otherwise risk of OOM is very high. You should use technique similar to what android suggests with list, keep in memory only those elements visible to user. In other words, first you have to figure out what the size is or expect that size may be huge. Then load data chunk by chunk to some UI element and implement some kind of "load by scroll". In case you cannot load from the net as you scroll, perhaps due to nature of the connection, then you should load chunk by chunk and save the data to local store. And then display it chunk by chunk as described above. This is how I would do it. Sorry, not exactly the answer you look for.

Related

HTTPResponseCache stores but never hits

I'm working on a application in Android which has a heavy load of web service requests.
I already have a LoginActivity in which the user introduces the username and the password and the server responses with the result and a token. Then, several activities (all of them extend from a common BaseActivity) do the heavy requests.
I have also a ServiceManager class which is responsible for all the service requests and HTTP petitions.
I'm working on implementing the HttpResponseCache to relieve this net load. Right now I have the following code:
In my LoginActivity's (the first being launched) onCreate:
//HTTP cache
try {
File httpCacheDir = new File(this.getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; //10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
Log.d(TAG, "Cache installed");
} catch (IOException e) {
Log.i(TAG, "HTTP response cache installation failed:" + e);
}
In my ServiceManager's httpRequest function, which is the one actually being executed every time I try to make an HTTP request:
//HTTPS connection
URL requestedUrl = new URL(uri);
httpsConnection = (HttpURLConnection) requestedUrl.openConnection();
httpsConnection.setUseCaches(true);
httpsConnection.setDefaultUseCaches(true);
httpsConnection.setRequestMethod("GET");
BufferedReader br = new BufferedReader(
new InputStreamReader(httpsConnection.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
httpResponse += line;
}
br.close();
httpsConnection.disconnect();
HttpResponseCache cache = HttpResponseCache.getInstalled();
Log.d(TAG, "Cache: " + cache);
if (cache != null) {
Log.d(TAG, "Net count: " + cache.getNetworkCount());
Log.d(TAG, "Hit count: " + cache.getHitCount());
Log.d(TAG, "Request count: " + cache.getRequestCount());
cache.flush();
}
try{
URI uriCached = new URI("<myurl>");
CacheResponse cr = cache.get(uriCached, "GET", null);
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(cr.getBody()));
while ((line = br.readLine()) != null) {
Log.d(TAG, line);
}
} catch (URISyntaxException e1) {
e1.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}
Right now, since the server side is not ready, the URL I'm doing the requests to is always the same.
As you can see, I'm debugging a few things, these are the results:
Cache installed
Cache: android.net.http.HttpResponseCache#b3e3b6
Net count: X
Hit count: 0
Request count: X
{myJson}
As you can see, the cache is able to read my JSON when I get it via the cache.get() method, but it's never hitting.
My server side directive Cache-Control in the header of the response is:
Cache-Control:public
Cache-Control:max-age=3800
Why is the cache never hitting?
Thank you very much!
I found the problem.
I was trying to cache petitions to a PHP that returns JSON. PHP is always considered as dynamic content (and it actually is), and it's never cached.
The path to follow when trying to cache JSON y application-side only and not server-side. This way, it won't event make a request.
Best.
EDIT
Best solution for this kind of trouble is, undoubtedly, to use Volley

BufferReader vs InputStream vs StringBuffer

Confused too much! What is the sole purpose of using BufferReader, InputStream and StringBuffer. Why they should be used and in what kind of a sequence / pattern we should code them. I recently came across a chunk of code while understanding how to send and receive HTTP requests using HttpUrlConnection in android. I tried to search for all these terms and I did not get what I need. In this case, how to use each of them in a sequence or pattern? Any simple example for using all these three in combination would be great. And also kindly what should be all these 3 in layman terms? Thanks
InputStream is used for reading byte based data from the web server (or url) one byte at a time.
BufferReader it is used for reading data from an input stream all by once
StringBuffer A modifiable sequence of characters for use in creating strings, where all accesses are synchronized. This class has mostly been replaced by StringBuilder because this synchronization is rarely useful. This class is mainly used to interact with legacy APIs that expose it. [Did not understand what it means as my official language is not English]
//These two need to be declared outside the try/catch
//so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
//Will contain the raw JSON response as a string.
String forecastJsonStr = null;
try {
//Construct the URL for the OpenWeatherMap query
//Possible parameters are avaiable at OWM's forecast API page, at
//http://openweathermap.org/API#forecast
URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7");
//Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
//Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
//Nothing to do.
forecastJsonStr = null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
//Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
//But it does make debugging a *lot* easier if you print out the completed
//buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
//Stream was empty. No point in parsing.
forecastJsonStr = null;
}
forecastJsonStr = buffer.toString();
} catch (IOException e) {
Log.e("PlaceholderFragment", "Error ", e);
//If the code didn't successfully get the weather data, there's no point in attemping
//to parse it.
forecastJsonStr = null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}

JSONExecption Unterminated String - Android

I am building an app that connects to a blog then gathers the data in JSON. Currently I amgeting this error (sorry about all JSON dat not sure whether to include):
Exception Caught
org.json.JSONException: Unterminated string at character 6564 of {"status":"ok","count":20,"count_total":1727,"pages":87,"posts":[{"id":23419,"url":"http:\/\/blog.teamtreehouse.com\/happy-mothers-day-ones-whove-shaped-web-careers","title":"Happy Mother\u2019s Day! Thanks, Mom, for Helping Us Learn","date":"2014-05-08 11:00:29","author":"Ryan Brinks","thumbnail":"http:\/\/blog.teamtreehouse.com\/wp-content\/uploads\/2014\/05\/mothers-dayHaik-Avanian-150x150.jpg"},{"id":23412,"url":"http:\/\/blog.teamtreehouse.com\/technology-brings-people-attitude-public-data-projects","title":"Public Data Brings ‘We the People’ Attitude to Technology","date":"2014-05-08 10:08:22","author":"Kelley King","thumbnail":"http:\/\/blog.teamtreehouse.com\/wp-content\/uploads\/2014\/05\/adoptahydrant-150x150.jpg"},{"id":23409,"url":"http:\/\/blog.teamtreehouse.com\/help-students-learn-computer-programming","title":"A Push for More Computer Programming in Public Schools","date":"2014-05-07 15:50:51","author":"Tim Skillern","thumbnail":"http:\/\/blog.teamtreehouse.com\/wp-content\/uploads\/2014\/05\/student-computer-class-woodleywonderworks-flickr-150x150.jpg"},{"id":23398,"url":"http:\/\/blog.teamtreehouse.com\/military-veterans-finding-technology-jobs-secure-bet","title":"Technology Jobs a Secure Bet for Military Veterans","date":"2014-05-06 13:45:13","author":"Anayat Durrani","thumbnail":"http:\/\/blog.teamtreehouse.com\/wp-content\/uploads\/2014\/05\/durrani-kopser-150x150.jpg"},{"id":23407,"url":"http:\/\/blog.teamtreehouse.com\/typography-sidebars-style-guides-treehouse-show-ep-89","title":"Typography, Sidebars, Style Guides | The Treehouse Show Ep 89","date":"2014-05-06 10:15:43","author":"Jason Seifer","thumbnail":null},{"id":23393,"url":"http:\/\/blog.teamtreehouse.com\/5-tips-creating-perfect-web-design-portfolio","title":"5 Tips for Creating the Perfect Web Design Portfolio","date":"2014-05-05 17:55:08","author":"Nick Pettit","thumbnail":"http:\/\/blog.teamtreehouse.com\/wp-content\/uploads\/2014\/05\/how-to-make-a-website-150x150.jpg"},{"id":23381,"url":"http:\/\/blog.teamtreehouse.com\/writing-tips-better-business-marketing","title":"11 Rules for Better Writing, or How Not to Use a Thesaurus","date":"2014-05-01 18:38:32","author":"Tim Skillern","thumbnail":"http:\/\/blog.teamtreehouse.com\/wp-content\/uploads\/2014\/05\/pencils-wikimedia-150x150.jpg"},{"id":23387,"url":"http:\/\/blog.teamtreehouse.com\/web-job-perks-unlimited-vacation-catered-lunch-part-amazing-opportunity-weebly-com-programmer","title":"Web Job Perks: Unlimited Vacation, Catered Lunch Part of \u2018Amazing Opportunity\u2019 for Weebly.com Programmer","date":"2014-05-01 17:00:28","author":"Jimmy Alford","thumbnail":"http:\/\/blog.teamtreehouse.com\/wp-content\/uploads\/2014\/05\/weebly-guy0-2-150x150.jpg"},{"id":23375,"url":"http:\/\/blog.teamtreehouse.com\/illustrator-ben-obrien-inspiration","title":"Noted Illustrator Ben O’Brien Talks About Finding Inspiration, Taking Chances","date":"2014-04-29 18:13:58","author":"Gillian Carson","thumbnail":"http:\/\/blog.teamtreehouse.com\/wp-content\/uploads\/2014\/04\/obrien3-150x150.jpg"},{"id":23373,"url":"http:\/\/blog.teamtreehouse.com\/gulp-sketch-3-bud-treehouse-show-episode-88","title":"Gulp | Sketch 3 | Bud | The Treehouse Show Episode 88","date":"2014-04-29 15:29:20","author":"Jason Seifer","thumbnail":null},{"id":23361,"url":"http:\/\/blog.teamtreehouse.com\/flexbox-next-generation-css-layout-arrived","title":"Flexbox: The Next Generation of CSS Layout Has Arrived","date":"2014-04-29 11:53:40","author":"Nick Pettit","thumbnail":"http:\/\/blog.teamtreehouse.com\/wp-content\/uploads\/2014\/04\/Screen-Shot-2014-04-28-at-1.00.03-AM-150x150.png"},{"id":23364,"url":"http:\/\/blog.teamtreehouse.com\/help-wanted-women-color-needed-technology-web-jobs","title":"Help Wanted: Women of Color Needed in Technology, Web Jobs","date":"2014-04-28 12:28:56","author":"Anayat Durrani","thumbnail":"http:\/\/blog.teamtreehouse.com\/wp-content\/uploads\/2014\/04\/poorn
This is where teh error is being caught:
public void updateList() {
if (mBlogData == null) {
// TODO: Handle Error
}
else {
try {
Log.d(TAG, mBlogData.toString(2));
}
catch (JSONException e) {
Log.e(TAG, "Exception Caught", e);
}
}
}
I am not sure what is causing this error so any suggestions are welcome. I can provide more code if needed. Thank You.
Just wanted to add to eMad's answer which helped me solve the same problem you are having. I hope this helps anybody who is to come after me because this darn bug killed 2 hours of my day (or night, I'm nocturnal). Well, with out further (ado? adieu?), here you go : P.S. the below code will go in your private class GetBlogPostsTask AsynnTask...
protected JSONObject doInBackground(Object... arg0) {
int responseCode = -1;
JSONObject jsonResponse = null;
try {
//set API URL
URL blogFeedUrl = new URL("http://blog.teamtreehouse.com/api/get_recent_summary/? count=" + NUMBER_OF_POSTS);
//open URL connection
URLConnection connection = blogFeedUrl.openConnection();
//create BufferedReader to read the InputStream return from the connection
BufferedReader in = new BufferedReader(
new InputStreamReader ( connection.getInputStream() )
);
//initiate strings to hold response data
String inputLine;
String responseData = "";
//read the InputStream with the BufferedReader line by line and add each line to responseData
while ( ( inputLine = in.readLine() ) != null ){
responseData += inputLine;
}
//check to make sure the responseData is not empty
if( responseData!= "" ){
/*initiate the jsonResponse as a JSONObject based on the string values added
to responseData by the BufferedReader */
jsonResponse = new JSONObject(responseData);
}
/*return the jsonResponse JSONObject to the postExecute() method
to update the UI of the context */
return jsonResponse;
}
catch (MalformedURLException e) {
Log.e(TAG, "Exception caught: ", e);
}
catch (IOException e) {
Log.e(TAG, "Exception caught: ", e);
}
catch (Exception e) {
Log.e(TAG, "Exception caught: ", e);
}
return jsonResponse;
}
#Override
protected void onPostExecute(JSONObject result) {
/* set the class' member JSONObject mBlogData to the result
to be used by the handleBlogResponse() method to update the UI */
mBlogData = result;
/*call the handleBlogResponse() method to update the UI with the result of this AsyncTask
which will be a JSONObject in best case scenario or a null object in worst case */
handleBlogResponse();
}
A friend of mine brought me a code that was generating the same output as yours. I think this is the solution that you're looking for. Given code is
// inside the class which connects to URL (Probably MainList)
InputStream inputStream = connection.getInputStream();
Reader reader = new InputStreamReader(inputStream);
int contentLength = connection.getContentLength();
char[] charArray = new char[contentLength];
reader.read(charArray);
String responseData = new String(charArray);
jsonResponse = new JSONObject(responseData);
But don't know why using above code, you either not get the full string or get the ContentLenght right but the last few characters aren't received properly. Use following code instead which reads complete response:
URLConnection yc = blogFeedUrl.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
yc.getInputStream()));
String inputLine;
responseData = "";
while ((inputLine = in.readLine()) != null) // read till you can receive any data
responseData += inputLine;
in.close();

Android: Quick web requests

For my application I need to have the latest data from an webpage that is hosted on a server on my local network.
So I request the latest page with a HTTP GET and when the data is received, I send another request.
With my current implementation I reach around the 100 - 120 ms per request. Is there a possibility to make this quicker because it's the same url that is requested.
For example keep the connection open to the page and grep the latest data without setting up a new connection?
This page is around the 900-1100 bytes.
HTTP get code:
public static String makeHttpGetRequest(String stringUrl) {
try {
URL url = new URL(stringUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setReadTimeout(300);
con.setConnectTimeout(300);
con.setDoOutput(false);
con.setDoInput(true);
con.setChunkedStreamingMode(0);
con.setRequestMethod("GET");
return readStream(con.getInputStream());
} catch (IOException e) {
Log.e(TAG, "IOException when setting up connection: " + e.getMessage());
}
return null;
}
Reading inputstream
private static String readStream(InputStream in) {
BufferedReader reader = null;
StringBuilder total = new StringBuilder();
try {
String line = "";
reader = new BufferedReader(new InputStreamReader(in));
while ((line = reader.readLine()) != null) {
total.append(line);
}
} catch (IOException e) {
Log.e(TAG, "IOException when reading InputStream: " + e.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return total.toString();
}
As I know there isn't an implementation like you are asking for. I've been dealing a lot with http requests and the best thing you can do is your code. There is another thing which need some attention...your connection maybe slow and depending on that connection time can be more or in some cases which I've been dealing a lot the connection's timeout isn't enough big, but that's server problem.
In my opinion you should use what you have now.

Memory leak with Android app?

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.

Categories

Resources