Gson parsing during asyntask [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am doing a request which gives me the following answer :
{
"SuL":[
{"IdS":"63","Nam":"Quiz1","Cat":"4097"},
{"IdS":"64","Nam":"6e","Cat":"4099"},
{"IdS":"65","Nam":"CP","Cat":"4100"},
{"IdS":"66","Nam":"CE1","Cat":"4098"}
],
"CaL":[
{"Cod":"4097","Lab":"Categorie1"},
{"Cod":"4098","Lab":"Math"},
{"Cod":"4099","Lab":"Anglais"},
{"Cod":"4100","Lab":"GĂ©ographie"}
]
}
What I am trying to do is to place all the "Lab" values in a List of string.
SuL represent a list of available objects on a server (which im not interested in right now) and CaL represents categories.
Here is my Categorie class :
public class Categorie {
public String Cod;
public String Lab;
public String getCode() {
return Cod;
}
public void setCode(String code) {
this.Cod = code;
}
public String getName() {
return Lab;
}
public void setName(String name) {
this.Lab = name;
}
}
And here is my AsyncTask doing the request and the Gson parsing :
class DownloadQuizCategory extends AsyncTask<String, String, String> {
protected String doInBackground(String...uri) {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
String responseString = null;
ByteArrayOutputStream out;
try {
response = httpclient.execute(new HttpGet(uri[0]));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
} else {
// Closes the connection.
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
} catch (ClientProtocolException e) {
// TODO Handle problems..
} catch (IOException e) {
// TODO Handle problems..
}
Log.i("AsyncTask", "responseString : " + responseString);
return responseString;
}
#Override
protected void onPostExecute(String resultat) {
super.onPostExecute(resultat);
//PARSING HERE :(
}
}
This is called by :
new DownloadQuizCategory().execute(URL_category); //where my results are

You only need to create another class apart from your Categorie class. Something like this:
public class Response {
private List<Categorie> CaL;
//getter & setter
}
Then parse your response with:
Gson gson = new Gson();
Response response = gson.fromJson(resultat, Response.class);
Gson will automatically and silently skip all the values into "SuL", since there's no attribute called SuL into your Response class...
EDIT: Then, if you want all the "Lab" vlaues into a List<String>, you just need to do (this is Java basics...):
List<String> labs = new ArrayList<String>();
for (Categorie c : response.getCaL()) {
labs.add(c.getName());
}

You have to deserialize your Json, try this lines above. Your JSONArray Lab should contain your list of "Lab".
#Override
protected void onPostExecute(String resultat)
{
super.onPostExecute(resultat);
JSONObject Response = new JSONObject(resultat);
JSONArray Lab= (JSONArray) Response.get("Lab");
System.out.print(Lab);
}

Related

How to Load an Array from .json file into App

My plan is do analyze an image via tensorflow and send the result to an app. Der result is written in a json file. The json file looks like that:
{"file": "image.jpg", "objects": [{"bbox": [177, 14, 508, 773], "label": "spanishguitar", "prob": 0.7284}]
my class in android studio is:
`
private class Downloadjson extends AsyncTask<Void, Void, Void> {
String name;
String label;
public Downloadjson(String name) {
this.name = name;
}
#Override
protected Void doInBackground(Void... params) {
String url = SERVER_ADRESS + name;
sleep(5000);
//animation start
for (int i = 0; i < 600; i++) {
HttpClient client = new DefaultHttpClient(getHttpRequestParams());
HttpGet getJson = new HttpGet(url);
try {
HttpResponse jsonResponse = client.execute(getJson);
if (200 == jsonResponse.getStatusLine().getStatusCode()) {
try {
InputStream inputStream = jsonResponse.getEntity().getContent();
String json = IOUtils.toString(inputStream);
Downloadjson downloadjson = new Gson().fromJson(json, Downloadjson.class);
String label = downloadjson.label;
TextView Result = (TextView) findViewById(R.id.textView);
Result.setText("Your instrument could be a " + downloadjson.label);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
//exucte
sleep(5000);
}
//stop animation
return null;
}
`
When I change "label" to "file" it works and the output is "image.jpg". But i need the "label" array with the output "spanishguitar". So, I think the problem is, that the object is not "label" but "objects" (in my json file). And label is an array? Do you know what I have to change to get the "label" ?
As I understand, you just need to properly traverse the json and assign value for label. Please try:
String label = downloadjson.objects[0].label;

I cannot add in my ArrayList [Android] [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
In my class I created a variable named taskArray and initialized it in my onCreate like this
public class ActivityOne extends Activity {
ArrayList<WorkTask> taskArray = null;
#Override
protected void onCreate(Bundle savedState) {
taskArray = new ArrayList<WorkTask>();
final GetTasks getTasks = new GetTasks();
getTasks.execute();
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run() {
if ( getTasks.getStatus() == AsyncTask.Status.RUNNING ) {
getTasks.cancel(true);
Toast.makeText(ActivityOne.this, "Connection Timeout", Toast.LENGTH_SHORT).show();
}
}
}, 60000 );
}
And then in my AsyncTask in doInBackground I'm adding the data on the branchesArray but It doesn't add. Before it is working correctly, but now it doesn't. My code looks like this
public final class GetTasks extends AsyncTask<Void, Void, Employee> {
protected Employee doInBackground(Void... params) {
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(URL_STRING);
HttpResponse response = httpclient.execute(httpget);
str = EntityUtils.toString(response.getEntity());
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try{
JSONObject jsonObject = new JSONObject(str);
JSONObject data = jsonObject.getJSONObject("DATA");
//Employee info
empObj = new Employee();
empObj.setId(data.getInt("id"));
empObj.setName(data.getString("name").toString());
JSONArray jArray = data.getJSONArray("worktask");
for (int i = 0, count = jArray.length(); i < count; i++) {
JSONObject jObj = jArray.getJSONObject(i);
WorkTask workTask = new WorkTask();
workTask.setId(jObj.getInt("id"));
workTask.setTaskName(jObj.getInt("task_name"));
taskArray.add(workTask);
}
}catch (JSONException e){
e.printStackTrace();
return null;
}
return empObj;
}
Here is my model WorkTask
public class WorkTask implements Serializable {
private int id;
private String taskName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getTaskName() {
return taskName;
}
public void setTaskName(int taskName) {
this.taskName = taskName;
}
I think you write more information about your code.
It can occurred by count is zero that means jArray is empty list.
Frist, you check your json data about worktask.
I made a stupid mistake here, my other values is getting data from jObj that should be from empObj that's why it always go to the catch. I already fixed it now and working correctly.

Android anonymous asyncTask return value in method

Now in my app i try to do http parsing from url, but i didn't carry about threads, before this time...
I have such class and method:
public class TwitterOAuthHelper {
public String httpQueryToApi(String url) {
HttpGet get = new HttpGet(url);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setUseExpectContinue(params, false);
get.setParams(params);
String response = null;
try {
SharedPreferences settings = context.getSharedPreferences("my_app", 0);
String userKey = settings.getString("user_key", "");
String userSecret = settings.getString("user_secret", "");
consumer.setTokenWithSecret(userKey, userSecret);
consumer.sign(get);
DefaultHttpClient client = new DefaultHttpClient();
response = client.execute(get, new BasicResponseHandler());
} catch (Exception e) {
displayToast("Failed to get data.");
}
return response;
}
}
and now i try to move this logic into asyncTask:
String result;
public String httpQueryToApi(String url) {
new AsyncTask<String,Void,String>(){
#Override
protected String doInBackground(String... params) {
HttpGet get = new HttpGet(String.valueOf(params));
HttpParams param = new BasicHttpParams();
HttpProtocolParams.setUseExpectContinue(param, false);
get.setParams(param);
String response = null;
try {
SharedPreferences settings = context.getSharedPreferences("my_app", 0);
String userKey = settings.getString("user_key", "");
String userSecret = settings.getString("user_secret", "");
consumer.setTokenWithSecret(userKey, userSecret);
consumer.sign(get);
DefaultHttpClient client = new DefaultHttpClient();
response = client.execute(get, new BasicResponseHandler());
} catch (Exception e) {
displayToast("Failed to get data.");
}
result = response;
return response;
}
}.execute(url);
return result;
}
but how can i return my response result value to method?
what is the best practice of doing that?
dd below method to asynctask body (below doInBackground method):
#Override
protected void onPostExecute(String result) {
// result is your returned value from doInBackground
// now we are in main ui thread
}
If you want a callback to antoher method it should be interface
public interface ResultInterface {
public void resultFromHttp(String result);
}
then your method
public String httpQueryToApi(String url, final ResultInterface ri){
//as bove
#Override
protected void onPostExecute(String result) {
if(ri!=null)
ri.resultFromHttp(result);
}
}
implement ResultInterface in your Activity/Fragment/whatever is calling httpQueryToApi, pass this as second param (ri interface)
You can't since the Task will be executed in another thread.
However you could use a callback to get the result.
Take a look at: https://stackoverflow.com/a/19520293/4299154.
Initially your function returned a string which you then further processed. Fine.
But you can not use threading like that. You can not return result from the function, because it has not been set yet (well you can but it will return null). The correct way of doing this is
public void httpQueryToApi(String url) {
new AsyncTask<String,Void,String>(){
#Override
protected String doInBackground(String... params) {
HttpGet get = new HttpGet(String.valueOf(params));
HttpParams param = new BasicHttpParams();
HttpProtocolParams.setUseExpectContinue(param, false);
get.setParams(param);
String response = null;
try {
SharedPreferences settings = context.getSharedPreferences("my_app", 0);
String userKey = settings.getString("user_key", "");
String userSecret = settings.getString("user_secret", "");
consumer.setTokenWithSecret(userKey, userSecret);
consumer.sign(get);
DefaultHttpClient client = new DefaultHttpClient();
response = client.execute(get, new BasicResponseHandler());
} catch (Exception e) {
displayToast("Failed to get data.");
}
return response;
}
#Override
protected void onPostExecute(String s) {
//here s is the response string, do what ever you want
super.onPostExecute(s);
}
}.execute(url);
}
You will have to shift your further processing logic to onPostExecute, no other way :)
If you want do dig a little deeper look into Future<>
1) Create separate class for you Async (not anonymous).
2) Create interface class.
public interface AsyncResponse {
void onProcessFinish(String output);
}
3) In your Async class, you need to declare it (interface : AsyncResponse):
public class MyAsyncTask extends AsyncTask<String,Void,String>(){
public AsyncResponse listener = null;
public MyAsyncTask(AsyncResponse l) {
this.listener = l;
}
{...}
#Override
protected String doInBackground(String... params) {
HttpGet get = new HttpGet(String.valueOf(params));
HttpParams param = new BasicHttpParams();
HttpProtocolParams.setUseExpectContinue(param, false);
get.setParams(param);
String response = null;
try {
SharedPreferences settings = context.getSharedPreferences("my_app", 0);
String userKey = settings.getString("user_key", "");
String userSecret = settings.getString("user_secret", "");
consumer.setTokenWithSecret(userKey, userSecret);
consumer.sign(get);
DefaultHttpClient client = new DefaultHttpClient();
response = client.execute(get, new BasicResponseHandler());
} catch (Exception e) {
displayToast("Failed to get data.");
}
result = response;
return response;
}
#Override
protected void onPostExecute(String result) {
listener.onProcessFinish(result);
}
}
4) In your class (where you call AssyncClass, for example in your Activity) you need to implements interface you created earlier AsyncResponse.
public class MainActivity implements AsyncResponse{
{...}
void onProcessFinish(String output){
//this you will received result fired from async class of onPostExecute(result) method.
}
}
6) now you can call in MainActivity:
new MyAsyncTask(this).execute("your_url");

best way to handle json from httpresponse android

I have used httpclient to call a restapi written in django. It returned the json output. My httpresponse variable stored it and later convert the reponse to string and then to json object, i think its lengthy though it is working . I am really new to java , can anybody advise me , what is the best alternative logic to the code below
public void onClick(View v) {
// TODO Auto-generated method stub
HttpClient httpclient = new DefaultHttpClient();
HttpGet httppost = new HttpGet("http://10.0.2.2:8000/api/ca/entry/?
format=json&username=pragya");
try {
// Add your data
//List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
//nameValuePairs.add(new BasicNameValuePair("username", un.getText().toString()));
//nameValuePairs.add(new BasicNameValuePair("username", pw.getText().toString()));
//httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
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();
}
}
try {
JSONObject jsonObject = new JSONObject(sb.toString());
JSONObject meta = jsonObject.getJSONObject("meta");
String limit = meta.getString("limit");
Toast.makeText(HelloWorldActivity.this, limit, Toast.LENGTH_SHORT).show();
JSONArray array = jsonObject.getJSONArray("objects");
String key = array.getJSONObject(0).getString("api_key");
String uname = array.getJSONObject(0).getString("username");
Toast.makeText(HelloWorldActivity.this, uname + " " + key,
Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Toast.makeText(HelloWorldActivity.this, sb.toString(), Toast.LENGTH_SHORT).show();
} catch (ClientProtocolException e) {
Toast.makeText(HelloWorldActivity.this, e.toString(), Toast.LENGTH_SHORT).show();
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
Toast.makeText(HelloWorldActivity.this, e.toString(), Toast.LENGTH_SHORT).show();
}
}
});
the json is as follows
{"meta": {"limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 1}, "objects": [{"api_key": "c87391754b522d0c83b2c8b5e4c8cfd614559632deee70fdf1b48d470307e40e", "homeAddress": "kathmandu", "resource_uri": "/api/ca/entry/1/", "username": "sumit"}]}
Use Gson library from google, it is perfect for these kind of tasks.
All you need to do is define a new class that contains fields with the names of the keys in the json object and then use Gson to parse the Json string directly into the object or vice versa.
So for example:
Json looks like this: "limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 1.
Java Class will be:
public class MyClass {
private int limit;
private int next;
private int offset;
private int previous;
private int total_count;
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getNext() {
return next;
}
public void setNext(int next) {
this.next = next;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getPrevious() {
return previous;
}
public void setPrevious(int previous) {
this.previous = previous;
}
public int getTotal_count() {
return total_count;
}
public void setTotal_count(int total_count) {
this.total_count = total_count;
}
}
And use Gson code like that:
Gson gson = new Gson(); // Or use new GsonBuilder().create();
MyClass myClass = gson.fromJson(json, MyClass.class); // deserializes json into MyClass
Please note that the name of the class fields have to match exactly the name of the keys in the json string.
Always perform lengthy non-UI task using AsyncTask. All the operations you described, fetching of json and parsing them, can be performed in AsyncTask. Write the entire code which you have currently written in onClick event and write it doInBackground() of an AsyncTask.
Check the following for more details:
http://developer.android.com/reference/android/os/AsyncTask.html

Return data from AsyncTask class

How do I get the data from my AsyncTask? My MainActivity is calling the DataCall.getJSON function that triggers the AsyncTask but I am not sure how to get the data back to the original Activity.
MainActivity with call to DataCall that should return a string and save it in state_data
String state_data = DataCall.getJSON(spinnerURL,spinnerContentType);
DataCall:
public class DataCall extends Activity {
private static final String TAG = "MyApp";
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
protected void onPostExecute(String result) {
//THIS IS WHERE I NEED TO RETURN MY DATA TO THE MAIN ACTIVITY. (I am guessing)
}
}
public void getJSON(String myUrlString, String contentType) {
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] { "http://www.mywebsite.com/" + myUrlString });
}
}
modify your AsyncTask as below:
public class GetData extends AsyncTask<String, Void, String>
{
DataDownloadListener dataDownloadListener;
public GetData()
{
//Constructor may be parametric
}
public void setDataDownloadListener(DataDownloadListener dataDownloadListener) {
this.dataDownloadListener = dataDownloadListener;
}
#Override
protected Object doInBackground(Object... param)
{
// do your task...
return null;
}
#Override
protected void onPostExecute(Object results)
{
if(results != null)
{
dataDownloadListener.dataDownloadedSuccessfully(results);
}
else
dataDownloadListener.dataDownloadFailed();
}
public static interface DataDownloadListener {
void dataDownloadedSuccessfully(Object data);
void dataDownloadFailed();
}
}
and use it in your Activity
GetData getdata = new GetData();
getdata.setDataDownloadListener(new DataDownloadListener()
{
#SuppressWarnings("unchecked")
#Override
public void dataDownloadedSuccessfully(Object data) {
// handler result
}
#Override
public void dataDownloadFailed() {
// handler failure (e.g network not available etc.)
}
});
getdata.execute("");
NOTE: For the people who are reading this.
Please consider this post for the best and perhaps right implementation.
The key for me was to create a class called URLWithParams or something because AsyncTask will allow only 1 type to be sent IN, and I needed both the URL and the params for the HTTP request.
public class URLWithParams {
public String url;
public List<NameValuePair> nameValuePairs;
public URLWithParams()
{
nameValuePairs = new ArrayList<NameValuePair>();
}
}
and then I send it to a JSONClient:
public class JSONClient extends AsyncTask<URLWithParams, Void, String> {
private final static String TAG = "JSONClient";
ProgressDialog progressDialog ;
GetJSONListener getJSONListener;
public JSONClient(GetJSONListener listener){
this.getJSONListener = listener;
}
#Override
protected String doInBackground(URLWithParams... urls) {
return connect(urls[0].url, urls[0].nameValuePairs);
}
public static String connect(String url, List<NameValuePair> pairs)
{
HttpClient httpclient = new DefaultHttpClient();
if(url == null)
{
Log.d(TAG, "want to connect, but url is null");
}
else
{
Log.d(TAG, "starting connect with url " + url);
}
if(pairs == null)
{
Log.d(TAG, "want to connect, though pairs is null");
}
else
{
Log.d(TAG, "starting connect with this many pairs: " + pairs.size());
for(NameValuePair dog : pairs)
{
Log.d(TAG, "example: " + dog.toString());
}
}
// Execute the request
HttpResponse response;
try {
// Prepare a request object
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(pairs));
response = httpclient.execute(httpPost);
// Examine the response status
Log.i(TAG,response.getStatusLine().toString());
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String json = reader.readLine();
return json;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String json ) {
getJSONListener.onRemoteCallComplete(json);
}
public interface GetJSONListener {
public void onRemoteCallComplete(String jsonFromNet);
}
}
Then call it from my main class like this
public class BookCatalog implements GetJSONListener {
private final String TAG = this.getClass().getSimpleName();
private String catalog_url = "URL";
private void getCatalogFromServer() {
URLWithParams mURLWithParams = new URLWithParams();
mURLWithParams.url = catalog_url;
try {
JSONClient asyncPoster = new JSONClient(this);
asyncPoster.execute(mURLWithParams);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onRemoteCallComplete(String jsonBookCatalogList) {
Log.d(TAG, "received json catalog:");
Log.d(TAG, jsonBookCatalogList);
JSONObject bookCatalogResult;
try {
bookCatalogResult = (JSONObject) new JSONTokener(jsonBookCatalogList).nextValue();
JSONArray books = bookCatalogResult.getJSONArray("books");
if(books != null) {
ArrayList<String> newBookOrdering = new ArrayList<String>();
int num_books = books.length();
BookCatalogEntry temp;
DebugLog.d(TAG, "apparently we found " + Integer.toString(num_books) + " books.");
for(int book_id = 0; book_id < num_books; book_id++) {
JSONObject book = books.getJSONObject(book_id);
String title = book.getString("title");
int version = book.getInt("price");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Although i disagree creating a new activity for that simple task there is
startActivityForResult()
to get data from another activity.
Check this. You can store your data to the Intent's extras. But still if you have a large amount of data you better off write it to a file get the result from the other activity that is done downloading and then read the file.
Serialize it and then read it. The only way I'm aware of.
Some options:
a) Make your bean implement Serializable interface, you can then pass your bean through Intent.
b) Implement Application interface (you need to make an entry in manifest), Have setter\getter method in your Application class. You can set your bean in Application from AsyncTask and later retrieve from Activity.
Sorry for answering so late, i think by this time you might have solved this problem. when i was searching for something else, i came across your question. I'm pasting a link here which might of some help for others.

Categories