2

I would like to connect to a Api url, retrieve the json and store everything in a object list. Here is an example of what the url can return as Json. Notice at the beginning there is a count, page and last_page. These are how many items there are on the page, what page you are on and how many pages there are in total (max 50 counts on 1 page). A unspecific search could easily return up to 1000 pages of results

I have this code in c# which works flawlessly but after searching and trying for a long time i have no idea how to recreate this in Android java.

This is api_handler.cs

public class api_Handler
    {
        public static RootObject objFromApi_idToName(string spidyApiUrl, int page){
            RootObject rootObject = null;
            RootObject tempRootObject = null;

            do{
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(spidyApiUrl + "/" + page);

                WebResponse response = request.GetResponse();
                using (Stream responseStream = response.GetResponseStream()){
                    StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
                    var jsonReader = new JsonTextReader(reader);
                    var serializer = new JsonSerializer();
                    tempRootObject = serializer.Deserialize<RootObject>(jsonReader);

                    if (rootObject == null){
                        rootObject = tempRootObject;
                    }
                    else{
                        rootObject.results.AddRange(tempRootObject.results);
                        rootObject.count += tempRootObject.count;
                    }
                }
                page++;
            }

            while (tempRootObject != null && tempRootObject.last_page != tempRootObject.page);
            return rootObject;
        }
}

Which i called in the main_form.cs like this

// url will become = http://www.gw2spidy.com/api/v0.9/json/item-search/ + textbox.text
// full example = http://www.gw2spidy.com/api/v0.9/json/item-search/Sunrise
    string spidyApiUrl = String.Format("{0}{1}/api/{2}/{3}/{4}/{5}", Http, spidyHost, spidyApiVersion, format, spidyApiType, dataId);
    var spidyApi_idByName = api_Handler.objFromApi_idToName(spidyApiUrl, startPage);

And ofcourse the constructors though I would assume these arent really important to include in the question.

public class Result
    {
        public int data_id { get; set; }
        public string name { get; set; }
        public int rarity { get; set; }
        public int restriction_level { get; set; }
        public string img { get; set; }
        public int type_id { get; set; }
        public int sub_type_id { get; set; }
        public string price_last_changed { get; set; }
        public int max_offer_unit_price { get; set; }
        public int min_sale_unit_price { get; set; }
        public int offer_availability { get; set; }
        public int sale_availability { get; set; }
        public int sale_price_change_last_hour { get; set; }
        public int offer_price_change_last_hour { get; set; }
    }

    public class RootObject
    {
        public int count { get; set; }
        public int page { get; set; }
        public int last_page { get; set; }
        public int total { get; set; }
        public List<Result> results { get; set; }
    }

How can i turn this working code in c# to android java? Or is it a better idea to start all over from scratch (i would still require some guidance as i have tried quite few times without success)

Also:

in C# on a pc this would run in a perfect acceptable time maybe load 1-2 sec for a 1000x50 objects which is a very unspecific search. These unspecific searches can ofcourse happen since its determined from user input but it wont happen too often, a normal search could be from 1 page to 50. is a phonecapable of doing this in a acceptable time?

TL;DR Connect to api > retrieve all json values > store all in object list > send back to activity.java

4
  • Though I don't have time to post a full answer, I recommend using the Retrofit library. It wraps up making asynchronous web requests and also uses the google json serialization/de-serialization library (known as gson) to parse JSON into POJOs and vice-versa. I haven't found a better, more fluid library yet. Commented Apr 11, 2015 at 21:23
  • No problem! There is a bit of a learning curve, but when I need to connect to a new endpoint and parse a new set of JSON I can do it in about 30 seconds with the retrofit library. Best of luck! Commented Apr 11, 2015 at 21:31
  • If you have time I would love to have some help, seemd you know exactly what to do. I am trying the proposed solution from the other user but so far im not gettin any wiser. Commented Apr 11, 2015 at 21:34
  • I will write up a proper response now. Commented Apr 11, 2015 at 21:36

3 Answers 3

4

Using AsyncTask in Android

Activity:

public class MainActivity extends Activity implements onResponse {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    String URL = "http://www.gw2spidy.com/api/v0.9/json/item-search/Sunrise";
    AsyncFetch parkingInfoFetch = new AsyncFetch(this);
    parkingInfoFetch.setOnResponse(this);
    parkingInfoFetch.execute(URL);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main, menu);

    return true;
}

@Override
public void onResponse(JSONObject object) {
    Log.d("Json Response", "Json Response" + object);

    ResultClass resultClass = new ResultClass();

    try {
        resultClass.setCount(object.getInt("count"));
        resultClass.setPage(object.getInt("page"));
        resultClass.setLast_page(object.getInt("last_page"));
        resultClass.setTotal(object.getInt("total"));
        JSONArray array = new JSONArray(object.getString("results"));
        for (int i = 0; i < resultClass.getTotal(); i++) {
            JSONObject resultsObject = array.getJSONObject(i);
            resultClass.setData_id(resultsObject.getInt("data_id"));
            resultClass.setName(resultsObject.getString("name"));
            resultClass.setRarity(resultsObject.getInt("rarity"));
            resultClass.setRestriction_level(resultsObject
                    .getInt("restriction_level"));
            resultClass.setImg(resultsObject.getString("img"));
            resultClass.setType_id(resultsObject.getInt("type_id"));
            resultClass.setSub_type_id(resultsObject.getInt("sub_type_id"));
            resultClass.setPrice_last_changed(resultsObject
                    .getString("price_last_changed"));
            resultClass.setMax_offer_unit_price(resultsObject
                    .getInt("max_offer_unit_price"));
            resultClass.setMin_sale_unit_price(resultsObject
                    .getInt("min_sale_unit_price"));
            resultClass.setOffer_availability(resultsObject
                    .getInt("offer_availability"));
            resultClass.setSale_availability(resultsObject
                    .getInt("sale_availability"));
            resultClass.setSale_price_change_last_hour(resultsObject
                    .getInt("sale_price_change_last_hour"));
            resultClass.setOffer_price_change_last_hour(resultsObject
                    .getInt("offer_price_change_last_hour"));

        }

    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}}

AsyncTask Class:

public class AsyncFetch extends AsyncTask<String, Void, JSONObject> {

public AsyncFetch(Context context) {
    this.context = context;
}

private Context context;
private JSONObject jsonObject;
private onResponse onResponse;

public onResponse getOnResponse() {
    return onResponse;
}

public void setOnResponse(onResponse onResponse) {
    this.onResponse = onResponse;
}

@Override
protected JSONObject doInBackground(String... params) {
    // TODO Auto-generated method stub
    try {
        HttpGet get = new HttpGet(params[0]);
        HttpClient client = new DefaultHttpClient();

        HttpResponse response = client.execute(get);
        HttpEntity entity = response.getEntity();
        String result = EntityUtils.toString(entity);
        jsonObject = new JSONObject(result);
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return jsonObject;
}

@Override
protected void onPostExecute(JSONObject result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
    this.onResponse.onResponse(result);
}

public interface onResponse {
    public void onResponse(JSONObject object);
}

}

Model Class:

public class ResultClass {

public int data_id;
public String name;
public int rarity;
public int restriction_level;
public String img;
public int type_id;
public int sub_type_id;
public String price_last_changed;
public int max_offer_unit_price;
public int min_sale_unit_price;
public int offer_availability;
public int sale_availability;
public int sale_price_change_last_hour;
public int offer_price_change_last_hour;

public int count;
public int page;
public int last_page;
public int total;

public int getData_id() {
    return data_id;
}

public void setData_id(int data_id) {
    this.data_id = data_id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getRarity() {
    return rarity;
}

public void setRarity(int rarity) {
    this.rarity = rarity;
}

public int getRestriction_level() {
    return restriction_level;
}

public void setRestriction_level(int restriction_level) {
    this.restriction_level = restriction_level;
}

public String getImg() {
    return img;
}

public void setImg(String img) {
    this.img = img;
}

public int getType_id() {
    return type_id;
}

public void setType_id(int type_id) {
    this.type_id = type_id;
}

public int getSub_type_id() {
    return sub_type_id;
}

public void setSub_type_id(int sub_type_id) {
    this.sub_type_id = sub_type_id;
}

public String getPrice_last_changed() {
    return price_last_changed;
}

public void setPrice_last_changed(String price_last_changed) {
    this.price_last_changed = price_last_changed;
}

public int getMax_offer_unit_price() {
    return max_offer_unit_price;
}

public void setMax_offer_unit_price(int max_offer_unit_price) {
    this.max_offer_unit_price = max_offer_unit_price;
}

public int getMin_sale_unit_price() {
    return min_sale_unit_price;
}

public void setMin_sale_unit_price(int min_sale_unit_price) {
    this.min_sale_unit_price = min_sale_unit_price;
}

public int getOffer_availability() {
    return offer_availability;
}

public void setOffer_availability(int offer_availability) {
    this.offer_availability = offer_availability;
}

public int getSale_availability() {
    return sale_availability;
}

public void setSale_availability(int sale_availability) {
    this.sale_availability = sale_availability;
}

public int getSale_price_change_last_hour() {
    return sale_price_change_last_hour;
}

public void setSale_price_change_last_hour(int sale_price_change_last_hour) {
    this.sale_price_change_last_hour = sale_price_change_last_hour;
}

public int getOffer_price_change_last_hour() {
    return offer_price_change_last_hour;
}

public void setOffer_price_change_last_hour(int offer_price_change_last_hour) {
    this.offer_price_change_last_hour = offer_price_change_last_hour;
}

public int getCount() {
    return count;
}

public void setCount(int count) {
    this.count = count;
}

public int getPage() {
    return page;
}

public void setPage(int page) {
    this.page = page;
}

public int getLast_page() {
    return last_page;
}

public void setLast_page(int last_page) {
    this.last_page = last_page;
}

public int getTotal() {
    return total;
}

public void setTotal(int total) {
    this.total = total;
}

}

Hope this will help you,

Sign up to request clarification or add additional context in comments.

7 Comments

Wow! Thats a great bunch of code! Just 1 problem so far, it doesnt recognize onResponse anywhere. It doesnt know it at the activity public class implements onResponse nor anywhere in the AsyncFetch class. Cannot resolve symbol 'onResponse'
onResponse is a interface which I have created in AsyncFetch class to get a callback from onPostExecute to my mainActivty
I still dont fully understand onResponse. Is it just to visualize the object on screen through a widget or something? Where can i call on the object and display its data?
My Activity Class should not be bothered with the exact details for Making any WebService Call, So What I did, is I have used AsyncFetch Class for it which is a sub class of AsyncTask, Here I have created a Interface ( read about Java Interface here :tutorialspoint.com/java/java_interfaces.htm ) onResponse which give a call back in the Activity if the Request is Success or Failure and in case of success it will pass JsonObject to my Activity
Alright I think I understand the purpose of interfaces but i sadly still have a problem. new AsyncTask(this); gives a error AsynTask is abstract; cannot be instantiated also implements onResponse cannot resolve symbol. I see what your code is doing and how it works but i do not understand these errors nor where i can now access my object. Please bare with this beginner
|
1

I would recommend using the retrofit library. It will result in very clean code and will make adding new endpoints or model objects very easy. Using the retrofit library, you would do something like this:

Create your POJO for parsing

public class ResponseObject {

    /**
     * Retrofit will use reflection to set the variable values, so you can
     * make them private and only supply getter methods, no setters needed
     */
    public int count;
    public int page;
    public int last_page;
    public int total;
    public List<Result> results;

    class Result {
        public int data_id;
        public String name;
        public int rarity;
        public int restriction_level;
        public String img;
        public int type_id;
        public int sub_type_id;
        public String price_last_changed;
        public int max_offer_unit_price;
        public int min_sale_unit_price;
        public int offer_availability;
        public int sale_availability;
        public int sale_price_change_last_hour;
        public int offer_price_change_last_hour;
    }
}

Create an API interface

public interface YourWebApi {
    @GET("/item-search/{query}/{page}")
    ResponseObject getItemsList(@Path("query") String query, @Path("page") Integer page, Callback<ResponseObject> callback);
}

Create callback class (probably an inner class, wherever you are making request)

The methods inside are called when the asynchronous request finishes

// this Callback<T> interface is from the retrofit package!!!!!
private class CustomCallback<ResponseObject> implements Callback<ResponseObject> {

    /** Successful HTTP response. */
    void success(RepsonseObject responseObject, Response response) {
        List<Result> results = responseObject.results;
        // do something with your results
    }

    /**
     * Unsuccessful HTTP response due to network failure, non-2XX status 
     * code, or unexpected exception.
     */
    void failure(RetrofitError error) {
        // present toast or something if there's a failure
    }
}

Create your request

RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint("http://www.gw2spidy.com/api/v0.9/json")
        .build();

YourWebApi api = restAdapter.create(YourWebApi.class);

/** 
 * This is the asynchronous request, from here either success or failure
 * methods of your CustomCallback class will be executed when the request
 * finishes. The JSON will be parsed into the ResponseObject automatically
 * using the gson library based off the variable names in ResponseObject
 * thanks to Java's reflection
 */
api.getItemsList("some query string", 1, new CustomCallback<ResponseObject>()); // second param is page int

Please edit if I have made some syntax errors I do not have the ability to test this right now!

Comments

0

For this you will need Service. This is what I suggest you should do :

  1. From your current activity, call a Service
  2. Return the value of that asych task to the activity, as a JSON object
  3. Parse the JSON into the desired format that you would want. In this case, objects.

For how to use Asynch Task, a simple Google Search "Android Asynch Task Tutorial" would be enough.

Code for ServiceHandler.java

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

public class ServiceHandler {

static String response = null;
public final static int GET = 1;
public final static int POST = 2;

public ServiceHandler() {

}

/**
 * Making service call
 * @url - url to make request
 * @method - http request method
 * */
public String makeServiceCall(String url, int method) {
    return this.makeServiceCall(url, method, null);
}

/**
 * Making service call
 * @url - url to make request
 * @method - http request method
 * @params - http request params
 * */
public String makeServiceCall(String url, int method,
                              List<NameValuePair> params) {
    try {
        // http client
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpEntity httpEntity = null;
        HttpResponse httpResponse = null;

        // Checking http request method type
        if (method == POST) {
            HttpPost httpPost = new HttpPost(url);
            // adding post params
            if (params != null) {
                httpPost.setEntity(new UrlEncodedFormEntity(params));
            }

            httpResponse = httpClient.execute(httpPost);

        } else if (method == GET) {
            // appending params to url
            if (params != null) {
                String paramString = URLEncodedUtils
                        .format(params, "utf-8");
                url += "?" + paramString;
            }
            HttpGet httpGet = new HttpGet(url);

            httpResponse = httpClient.execute(httpGet);

        }
        httpEntity = httpResponse.getEntity();
        response = EntityUtils.toString(httpEntity);

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return response;

}
}

How to use this ServiceHandler in your activity? You will need to use an Asych Task to call this service which will connect to you to your API and get you a JSON result.

private class GetJSON extends AsyncTask<Void, Void, Void> {

    WeakReference<Activity> mActivityReference;

    public GetJSON(Activity activity){
        this.mActivityReference = new WeakReference<Activity>(activity);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // Showing progress dialog
        pDialog = new ProgressDialog(Activity.this);
        pDialog.setMessage("getting data");
        pDialog.setCancelable(false);
        pDialog.show();

    }

    @Override
    protected Void doInBackground(Void... voids) {
        // Creating service handler class instance
        ServiceHandler sh = new ServiceHandler();

        // Making a request to url and getting response
        String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);

        Log.d("Response: ", "> " + jsonStr);

        if(jsonStr != null) {
            try {
                //Process
                }

            }catch (JSONException e){
                //Process
            }

        }
        else{
            Log.e("ServiceHandler", "Couldn't get any data from the url");
        }


        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        // Dismiss the progress dialog
        if (pDialog.isShowing())
            pDialog.dismiss();

        }
    }
}

2 Comments

Asynctask is to process something in the background. That still leaves me to question how to connect to the Api, take json and create a object list.
Added Code to explain what I meant

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.