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();
Related
I'm following an example of using the Reddit API in an Android app. I'm using Android Studio and Java. I have a link which returns a JSON object on a GET request (let's say http://www.reddit.com/r/dragonforce/.json), and the tutorial has this piece of code:
public static HttpURLConnection getConnection(String url){
System.out.println("URL: "+url);
HttpURLConnection hcon = null;
try {
hcon=(HttpURLConnection) new URL(url).openConnection();
hcon.setReadTimeout(30000); // Timeout at 30 seconds
hcon.setRequestProperty("User-Agent", "Alien V1.0");
} catch (MalformedURLException e) {
Log.e("getConnection()",
"Invalid URL: "+e.toString());
} catch (IOException e) {
Log.e("getConnection()",
"Could not connect: "+e.toString());
}
return hcon;
}
and
public static String readContents(String url){
HttpURLConnection hcon=getConnection(url);
if(hcon==null) return null;
try{
StringBuffer sb=new StringBuffer(8192);
String tmp="";
BufferedReader br=new BufferedReader(
new InputStreamReader(
hcon.getInputStream()
)
);
tmp = br.readLine();
while(tmp !=null) {
sb.append(tmp).append("\n");
tmp = br.readLine();
}
br.close();
return sb.toString();
}catch(IOException e){
Log.d("READ FAILED", e.toString());
return null;
}
}
I separated the tmp assignment for debug purposes. The problem is that nothing is read from the inputStream, and it returns an empty buffer to the JSONObject parser, resulting in JSONException end of input at character 0 of. I have user-permission in the Manifest for INTERNET, and the syntax for reading from the URL seems to be backed up by other sources on the internet, but it still seems something is amiss. Any help would be appreciated.
For anyone who is reading this down the line, the problem was that the URL in the tutorial was using HTTP instead of HTTPS, leading to a redirect response code and wasn't returning anything.
I've got a requirement to log message from the Android client. Is there any sumo logic API to log message from the Android application?
You can post your log message/ any message from your Android application to Summo Logic cloud-based log management.
Summo Logic provides Web Services/ REST to perform POST, GET Request.
You just need to post your data on the request body and mention your
Sumo collection endpoint as well as UniqueHTTPCollectorCode.
REST Service/ Web Service : https://[SumoEndpoint]/receiver/v1/http/[UniqueHTTPCollectorCode]
For Instance:
"https://endpoint1.collection.us2.sumologic.com/receiver/v1/http/SanTC12dhaV1oma90Vvb..."
You can use Retorfit / Volley library for REST Communication .
I have given a below pseudo code which conveys the basic REST Communication in background through Android Async Task.
I strictly recommend to use the above mentioned libraries.
public static String performPostRequest(String summoUrl, String payload,
Context context) throws IOException {
URL url = new URL(summoUrl);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
String line;
StringBuffer jsonString = new StringBuffer();
uc.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
uc.setRequestMethod("POST");
uc.setDoInput(true);
uc.setInstanceFollowRedirects(false);
uc.connect();
OutputStreamWriter writer = new OutputStreamWriter(uc.getOutputStream(), "UTF-8");
writer.write(payload);
writer.close();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));
while((line = br.readLine()) != null){
jsonString.append(line);
}
br.close();
} catch (Exception ex) {
ex.printStackTrace();
}
uc.disconnect();
return jsonString.toString();
}
Async task
new AsyncTask<String, String, String>() {
#Override
protected String doInBackground(String... params) {
try {
String response = makePostRequest(""https://endpoint1.collection.us2.sumologic.com/receiver/v1/http/ZaVnC4dhaV1oma90Vvb..."",
// Sample JSON Data "
{ \"organization": \"organization.name\",
\"environment": \"environment.name\",
\"apiProduct": \("apiproduct.name"),
\"proxyName": \("apiproxy.name"),
\"appName": \("developer.app.name"),
\"verb": \("request.verb"),
\"url": '' + \("client.scheme") + '://' + \("request.header.host") + \("request.uri"),
\"responseCode": \("message.status.code"),
\"responseReason": \("message.reason.phrase"),
\"clientLatency": total_client_time,
\"targetLatency": total_target_time,
\"totalLatency": total_request_time
}", getApplicationContext());
// Hard coded Success as response from Server, replace with this as per your need
return "Success";
} catch (IOException exception) {
exception.printStackTrace();
return exception.getMessage();
}
}
}.execute("");
For more information, Please refer the documentation from Official Sumo Webpage
https://help.sumologic.com/Send-Data/Sources/02Sources-for-Hosted-Collectors/HTTP-Source/Upload-Data-to-an-HTTP-Source
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.
I'm trying to send custom exceptions from ASP.NET Web API , but when I consume these WebService from Android I'm always getting a different message:
This how I read the webservice in Android:
public Object doRequest(String url) {
String charset = Charset.defaultCharset().displayName();
try {
if (mFormBody != null) {
// Form data to post
mConnection
.setRequestProperty("Content-Type",
"application/json; charset="
+ charset);
mConnection.setFixedLengthStreamingMode(mFormBody.length());
}
mConnection.connect();
if (mFormBody != null) {
OutputStream out = mConnection.getOutputStream();
writeFormData(charset, out);
}
// Get response data
int status = mConnection.getResponseCode();
if (status >= 300) {
String message = mConnection.getResponseMessage();
return new HttpResponseException(status, message);
}
InputStream in = mConnection.getInputStream();
String enconding = mConnection.getContentEncoding();
if (enconding == null) {
enconding = "UTF-8";
}
BufferedReader reader = new BufferedReader(new InputStreamReader(
in, enconding));
StringBuilder sb = new StringBuilder();
String line=null;
while ((line=reader.readLine()) != null) {
sb.append(line);
}
return sb.toString().trim();
} catch (Exception e) {
return e;
}
finally{
if(mConnection!=null){
mConnection.disconnect();
}
}
}
As you can see, I check the value returned by getResponseCode() and if it's equal or greater than 300 I throw an Exception. Everything works except for the fact that getResponseMessage() doesn't return the string I used when I created the exception in WebApi. Instead I get this error:
From WebApi,all I'm doing in the catch block is to throw the exception:
try
{
}
catch (Exception ex)
{
throw ex;
}
Using fiddler realized I was getting this message:
{"Message":"Error."}
Well, looking for a solution on Internet, I found that I could do something like this:
try
{
}
catch (Exception ex)
{
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, ex.Message));
//throw (ex);
}
But unfortunately this didn't work either. Although fiddler now shows the message I used to create the Exception.
When I read the value of getResponseMessage() is returns this string : "Not Found".
Do you know what I need to do so that the message that is being sent from WebApi through the Exception make its way to Android, specifically to the getResponseMessage() property?
Thanks in advance.
Well, I think you need to create a HttpResponseMessage object first, and based on that object create the HttpResponseException that you're going to throw.
Setting a HttpResponseMessage object is pretty easy. Most of the time you only need to set two properties: Content and ReasonPhrase.
try
{
}
catch (Exception ex)
{
HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent(string.Format("Excepción")),
ReasonPhrase = ex.Message
};
throw new HttpResponseException(msg);
}
As you can see is ReasonPhrase where we passed the exception message.
Hope it helps.
Im doing a simple http get,
I see on my result an incomplete response,
what Im doing wrong?
here the code:
class GetDocuments extends AsyncTask<URL, Void, Void> {
#Override
protected Void doInBackground(URL... urls) {
Log.d("mensa", "bajando");
//place proper url
connect(urls);
return null;
}
public static void connect(URL[] urls)
{
HttpClient httpclient = new DefaultHttpClient();
// Prepare a request object
HttpGet httpget = new HttpGet("http://tiks.document.dev.chocolatecoded.com.au/documents/api/get?type=tree");
// Execute the request
HttpResponse response;
try {
response = httpclient.execute(httpget);
// Examine the response status
Log.d("mensa",response.getStatusLine().toString());
// Get hold of the response entity
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release
if (entity != null) {
// A Simple JSON Response Read
InputStream instream = entity.getContent();
String result= convertStreamToString(instream);
// now you have the string representation of the HTML request
Log.d("mensa", "estratagema :: "+result);
JSONObject jObject = new JSONObject(result);
Log.d("mensa", "resposta jObject::"+jObject);
Log.d("mensa", "alive 1");
JSONArray contacts = null;
contacts = jObject.getJSONArray("success");
Log.d("mensa", "resposta jObject::"+contacts);
Log.d("mensa", "alive");
//instream.close();
}
} catch (Exception e) {}
}
private static String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the BufferedReader.readLine()
* method. We iterate until the BufferedReader return null which means
* there's no more data to read. Each line will appended to a StringBuilder
* and returned as String.
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
Log.d("mensa", "linea ::"+line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
i call it with:
GetDocuments get = new GetDocuments();
URL url = null;
try {
url = new URL("ftp://mirror.csclub.uwaterloo.ca/index.html");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//URL url = new URL("http://www.google.es");
get.execute(url);
edit 1
I refer to incomplete as the response that gets truncated?
please notice in below image of response how string gets truncated,
is this because of the log size?,
but the other problem is that it doesn't parse?
thanks!
I don't know if this is going to resolve your problem but you can get rid of your method and use simply:
String responseString = EntityUtils.toString(response.getEntity());
I've had exactly the same issue for the last couple of days. I found that my code worked over WiFi but not 3G. In other words I eliminated all the usual threading candidates. I also found that when I ran the code in the debugger and just waited for (say) 10 seconds after client.execute(...) it worked.
My guess is that
response = httpclient.execute(httpget);
is an asynchronous call in itself and when it's slow returns a partial result... hence JSON deserialization goes wrong.
Instead I tried this version of execute with a callback...
try {
BasicResponseHandler responseHandler = new BasicResponseHandler();
String json = httpclient.execute(httpget, responseHandler);
} finally {
httpclient.close();
}
And suddenly it all works. If you don't want a string, or want your own code then have a look at the ResponseHandler interface. Hope that helps.
I have confirmed that this is because size limit of java string. I have checked this by adding the string "abcd" with the ressponse and printed the response string in logcat. But the result is the truncated respose without added string "abcd".
That is
try {
BasicResponseHandler responseHandler = new BasicResponseHandler();
String json = httpclient.execute(httpget, responseHandler);
json= json+"abcd";
Log.d("Json ResponseString", json);
} finally {
httpclient.close();
}
So I put an arrayString to collect the response. To make array, I splitted My json format response by using "}"
The code is given below(This is a work around only)
BasicResponseHandler responseHandler = new BasicResponseHandler();
String[] array=client.execute(request, responseHandler).split("}");
Then you can parse each objects in to a json object and json array with your custom classes.
If you get any other good method to store response, pls share because i am creating custom method for every different json responses );.
Thank you
Arshad
Hi Now I am using Gson library to handle the responses.
http://www.javacodegeeks.com/2011/01/android-json-parsing-gson-tutorial.html
Thanks
Arshad
I cant' comment directly due to reputation, but in response to https://stackoverflow.com/a/23247290/4830567 I felt I should point out that the size limit of a Java String is about 2GB (Integer.MAX_VALUE) so this wasn't the cause of the truncation here.
According to https://groups.google.com/d/msg/android-developers/g4YkmrFST6A/z8K3vSdgwEkJ it is logcat that has a size limit, which is why appending "abcd" and printing in logcat didn't work. The String itself would have had the appended characters. The previously linked discussion also mentioned that size limits with the HTTP protocol itself can occasionally be a factor, but that most servers and clients handle this constraint internally so as to not expose it to the user.