i am new to programming and I am making a json parser, but my thread method is not accessible, how do I go about doing this. When I debug, it goes into my getjson method but then skips the run method.
I searched on stack over flow already but I am very confused about threading is there any good way to do this?
public class jsonParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public jsonParser() {
}
public JSONObject getJSONFromUrl(final String url) {
Thread t = new Thread() {
public void run() {
Looper.prepare(); //For Preparing Message Pool for the child Thread
// Making HTTP request
try {
// defaultHttpClient
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, "iso-8859-1"), 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 parse the string to a JSON object
try {jObj = new JSONObject(json);
} catch (JSONException e) {
// TODO Auto-generated catch block
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
Looper.loop();
return;
}
}; t.start();
return jObj;
}
}
It goes to the run() method. But the principle of a thread is that it's executed in parallel to the current thread. So here's what happens on the time line:
main thread
_______________________________________________________________________
| |
start parser thread return jObj
parser thread
_________________________________________________________________
| |
execute an HTTP request and parse json assign JSON object to jObj
When you return jObj from the current thread, you have just started the parser thread. Maybe it hasn't even started executing yet. Maybe it's still waiting for the HTTP response. What's sure is that there is 0% chance that it has finished executing and stored the result in the static jObj variable yet. So, the value returned from the current thread is null.
It's hard to tell you what you should do, except read more on threading and on the supporting classes provided by android.
Related
Hi I am new to android programming and I am working on a project that converts a list into json object and stores it in the server and retrieves it. I am able to send the json object to the server and store it but i am not able to retrieve it. What approach should i use to retrieve the json object stored on the server?
You can reffer bellow class ...... call getJSONfromURL(YOUR_JOSN_URL) and method will return you JSONObject.
I hope this will work
public class JSONfunctions {
public static JSONObject getJSONfromURL(String url) {
InputStream is = null;
JSONObject jObj = null;
String json = "";
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpget);
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 parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
To retrieve JSON from server you have to establish a connection with server first by using DefaultHttpClient Hope you did that. If yes, post your code and if no then have look on
www.androidhive.info/2012/01/android-json-parsing-tutorial
Or google it you will lot of help to parse the JSON when you have URL with you.
I have to download more than 40,000 json records from my web service, but it is taking so long time to download. The downloaded data is storing into a string, but I am not able parse that string. Please tell me a solution to solve this problem.
URL: https://buzoonga.co.uk/appapi/contacts.php?user_id=531
public JSONObject getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
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, "iso-8859-1"), 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 parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
check out gzip. excellent text compressor. you are going to remove ~70% of the size :) you just have to gzip it serverside and unzip it clientside. if this overhead increases the time but the download is a third of the time, you might win in the end.
Also consider designing a better schema to reduce the size of your jsons.
Like, instead of "animalBodyParts" put "abp" or something. you have not put an example of your jsons so I am just guessing.
You can use the JSONTokener class and pass the InputStream
jObj = new JSONObject(new JSONTokener(httpEntity.getContent()));
To reduce the time to download you need to support gzipped downloads on the server side or change your JSON structure to a more compact array based format
I am working on an android app, and am running into some troubles with registering users. I want to post a JSON object to my server and receive one back. I can successfully create a JSON object with the right information but when I go to post it I get a NetworkOnMainThreadException or my HttpClient class returns null when it should be returning a JSONObject and I am very confident that my web server works correctly. I understand that you cannot connect to the network on the main thread and have created an HttpClient class that uses AsnycTask (although probably not correctly). I have been working on this for quite a while and would appreciate any guidance in the right direction.
//Main activity
#Override
public void onClick(View arg0) {
if(!(isEmpty(name) || isEmpty(username) || isEmpty(password) || isEmpty(email))) {
user = new JSONObject();
try {
user.put("username", username.getText().toString());
user.put("name", name.getText().toString());
user.put("email", email.getText().toString());
user.put("password", password.getText().toString());
} catch (JSONException e) {
e.printStackTrace();
}
jRegister = new JSONObject();
try {
jRegister.put("apiToken", Utilities.apiToken);
jRegister.put("user", user);
Log.i("MainActivity", jRegister.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
//
HttpClient client = new HttpClient(url, jRegister);
result = client.getJSONFromUrl();
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}else {
tv.setText("");
}
}
HttpClient Class
public class HttpClient extends AsyncTask<Void, Void, JSONObject>{
private final String TAG = "HttpClient";
private String URL;
private JSONObject jsonObjSend;
private JSONObject result = null;
public HttpClient(String URL, JSONObject jsonObjSend) {
this.URL = URL;
this.jsonObjSend = jsonObjSend;
}
public JSONObject getJSONFromUrl() {
this.execute();
return result;
}
#Override
protected JSONObject doInBackground(Void... params) {
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(URL);
StringEntity se;
se = new StringEntity(jsonObjSend.toString());
// Set HTTP parameters
httpPostRequest.setEntity(se);
httpPostRequest.setHeader("Accept", "application/json");
httpPostRequest.setHeader("Content-type", "application/json");
long t = System.currentTimeMillis();
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
Log.i(TAG, "HTTPResponse received in [" + (System.currentTimeMillis()-t) + "ms]");
HttpEntity entity = response.getEntity();
if (entity != null) {
// Read the content stream
InputStream instream = entity.getContent();
// convert content stream to a String
String resultString= convertStreamToString(instream);
instream.close();
resultString = resultString.substring(1,resultString.length()-1); // remove wrapping "[" and "]"
JSONObject jsonObjRecv = new JSONObject(resultString);
// Raw DEBUG output of our received JSON object:
Log.i(TAG,"<JSONObject>\n"+jsonObjRecv.toString()+"\n</JSONObject>");
return jsonObjRecv;
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(JSONObject jObject) {
result = jObject;
}
private 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) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
I understand that you cannot connect to the network on the main thread
and have created an HttpClient class that uses AsnycTask (although
probably not correctly).
You are right you have not implemented it the right way.
In your onClick events (still on Main thread) you performed a network activity causing the error:
HttpClient client = new HttpClient(url, jRegister);
result = client.getJSONFromUrl();
Instead you should run the network operation inside of the AsnycTask
public class GetJsonTask extends AsyncTask<Void, Void, JSONObject >{
private String URL;
private JSONObject jsonObjSend;
public GetJsonTask(String URL, JSONObject jsonObjSend) {
this.URL = URL;
this.jsonObjSend = jsonObjSend;
}
#Override
protected JSONObject doInBackground(Void... params) {
JSONObject jsonObjRecv;
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(URL);
StringEntity se;
se = new StringEntity(jsonObjSend.toString());
// Set HTTP parameters
httpPostRequest.setEntity(se);
httpPostRequest.setHeader("Accept", "application/json");
httpPostRequest.setHeader("Content-type", "application/json");
long t = System.currentTimeMillis();
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
Log.i(TAG, "HTTPResponse received in [" + (System.currentTimeMillis()-t) + "ms]");
HttpEntity entity = response.getEntity();
if (entity != null) {
// Read the content stream
InputStream instream = entity.getContent();
// convert content stream to a String
String resultString= convertStreamToString(instream);
instream.close();
resultString = resultString.substring(1,resultString.length()-1); // remove wrapping "[" and "]"
jsonObjRecv = new JSONObject(resultString);
// Raw DEBUG output of our received JSON object:
Log.i(TAG,"<JSONObject>\n"+jsonObjRecv.toString()+"\n</JSONObject>");
}
}
catch (Exception e) {
e.printStackTrace();
}
return jsonObjRecv;
}
protected void onPostExecute(JSONObject result) {
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}else {
tv.setText("");
}
}
}
Then you call your async in onclik method like this:
public void onClick(View arg0) {
//.......
GetJsonTask client = new GetJsonTask(url, jRegister);
client.execute();
}
One problem in your code is that your expectations of AsyncTask aren't quite right. In particular this function:
public JSONObject getJSONFromUrl() {
this.execute();
return result;
}
AsyncTask runs the code in the doInBackground() function in a separate thread. This means that once you call execute() you have two parallel lines of execution. You end up with what's called a Race Condition. When you reach the return result line, a couple of things can be happening:
doInBackground() hasn't run and therefore result is still has the default value. In this case null.
doInBackground() can be in the middle of the code. In your particular case because it doesn't modify result then this doesn't affect you much. But it could be on any line (or middle of a line sometimes if operations aren't atomic) when that return happens.
doInBackground() could've finished, but since onPostExecute() runs on the UI thread it has to wait until your onClick handler is finished. By the time onPostExecute() has a chance to run onClick already tried to update tv with whatever it was that getJSONFromUrl returned, most likely null.
The way to set up tasks with AsyncTask is to give it the information it needs to do it's work, start it up with execute, and since you can't know how long it will take to complete, let it handle the finishing steps of the task.
This means that after calling execute you don't wait around for it's result to update views (like in your case), but rather rely on the AsyncTask's onPostExecute or related methods to take over the next steps.
For your case this would mean that your onPostExecute should look something like:
protected void onPostExecute(JSONObject result) {
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}
I created a json result in mvc and I'm building an Android app to get the json result. This is what my json result looks like
{"name":"Mr. Spock","gender":"Male"}
This is my controller
public ActionResult Index()
{
var result = new { name = "Mr. Spock", gender = "Male" };
return Json(result, JsonRequestBehavior.AllowGet);
}
And this I'm using in android
// Creating JSON Parser instance
JSONParser jParser = new JSONParser();
// getting JSON string from URL
JSONObject json = jParser.getJSONFromUrl(url);
JSONParser class
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
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, "iso-8859-1"), 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 parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
I have a declared variable url. Every time I debug, the json variable does not have any values and says "errors during the evaluation"
Anyone with a tip? I tried working with Gson, but no succes
Kind regards
I'll give you some code for Gson. It really is much easier to work with than the built in JSON parsing code. Here's a minimal example using your JSON.
Person.class:
package com.example.tutorial.models;
import com.google.gson.annotations.SerializedName;
public class Person {
#SerializedName("gender")
public String gender = "";
#SerializedName("name")
public String name = "";
}
The annotations are really only necessary when your variable and JSON name differ, but I tend to always include them as it reinforces that they are coming from JSON.
To deserialize:
Gson gson = new GsonBuilder().create();
Person person = gson.fromJson(json, Person.class);
It really is that simple. If this does not work, log the result from the web server and make sure it really is the valid JSON string you expect it to be.
I do have one question, where is your AsyncTask? Your attempt to open a connection to the webserver in the UI thread will definitely cause a NetworkOnMainThreadException. I created a library to do RESTful calls on Android. It's licensed under BSD, so feel free to use it as a guide or outright use it: https://github.com/nedwidek/Android-Rest-API
I am not new to android platform, i have parsed many json pages before, but one link is creating problem. I am using following function to return the json object. The program stops at reader.readline() and loading does not stop.
public JSONObject getJSONFromUrl(String url) {
DefaultHttpClient httpClient = new DefaultHttpClient();
try {
HttpResponse httpResponse = httpClient.execute(new HttpGet(url));
if (httpResponse.getStatusLine().getStatusCode()==200)
{
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
System.out.println("Unsupported Encoding");
} catch (ClientProtocolException e) {
e.printStackTrace();
System.out.println("Client Protocol");
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO");
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
is.close();
jsonStr = sb.toString();
} catch (Exception e) {
System.out.println("Error here");
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(jsonStr);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
return jObj;
}
can any one suggest something?
I am pretty sure that this is caused by the server not finishing the response in your case. Try to isolate that using "curl" as a client first.
Also there is an easier way to fetch body into String if you use EntitUtils like this:
EntityUtils.toString(entity);
You can also specify encoding as second parameter.
http://developer.android.com/reference/org/apache/http/util/EntityUtils.html