I am developing an application where I want to hit the web services and get the data. I am using Google Volley to hit the web service. I am doing it all right but unable to parse JSON using GSON. I am unable to understand where I am doing it wrong.
Here is the URL of Web Services
Here is what I am doing
RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
Request.Method.GET,
"https://api.github.com/repos/crashlytics/secureudid/issues",
null,
new MyListner(),
new MyErrorListner()
);
requestQueue.add(jsonObjectRequest);
}
class MyListner implements Response.Listener<JSONObject>
{
#Override
public void onResponse(JSONObject response) {
Gson gson = new Gson();
Results results = gson.fromJson(response.toString(), Results.class);
for(Test t : results.getmResults())
{
Log.e("Tag", t.toString());
}
}
}
class MyErrorListner implements Response.ErrorListener
{
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error", error.getMessage());
}
}
The other classes are given below
public class Results {
private ArrayList<Test> mResults;
public void setResults(ArrayList<Test> results)
{
mResults = results;
}
public ArrayList<Test> getmResults()
{
return mResults;
}
}
public class Test {
#SerializedName("title")
private String mTitle;
#SerializedName("user")
private User mUser;
#SerializedName("created_at")
private String mCreatedAt;
#SerializedName("body")
private String mBody;
#SerializedName("updated_at")
private String mUpdatedAt;
public String getmBody() {
return mBody;
}
public void setmBody(String mBody) {
this.mBody = mBody;
}
public String getmUpdatedAt() {
return mUpdatedAt;
}
public void setmUpdatedAt(String mUpdatedAt) {
this.mUpdatedAt = mUpdatedAt;
}
public String getmCreatedAt() {
return mCreatedAt;
}
public void setmCreatedAt(String mCreatedAt) {
this.mCreatedAt = mCreatedAt;
}
public User getmUser() {
return mUser;
}
public void setmUser(User mUser) {
this.mUser = mUser;
}
public String getmTitle() {
return mTitle;
}
public void setmTitle(String mTitle) {
this.mTitle = mTitle;
}
#Override
public String toString() {
return mTitle + " " + mBody + " " + mCreatedAt + " " + mUpdatedAt + " " + mUser.getmLogin() + " ";
}
}
public class User {
#SerializedName("login")
private String mLogin;
public String getmLogin() {
return mLogin;
}
public void setmLogin(String mLogin) {
this.mLogin = mLogin;
}
}
Here is the error what I am getting
org.json.JSONException: Value [{"url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/28","repository_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid","labels_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/28\/labels{\/name}","comments_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/28\/comments","events_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/28\/events","html_url":"https:\/\/github.com\/crashlytics\/secureudid\/pull\/28","id":222258999,"number":28,"title":"Fix broken headings in Markdown files","user":{"login":"bryant1410","id":3905501,"avatar_url":"https:\/\/avatars3.githubusercontent.com\/u\/3905501?v=4","gravatar_id":"","url":"https:\/\/api.github.com\/users\/bryant1410","html_url":"https:\/\/github.com\/bryant1410","followers_url":"https:\/\/api.github.com\/users\/bryant1410\/followers","following_url":"https:\/\/api.github.com\/users\/bryant1410\/following{\/other_user}","gists_url":"https:\/\/api.github.com\/users\/bryant1410\/gists{\/gist_id}","starred_url":"https:\/\/api.github.com\/users\/bryant1410\/starred{\/owner}{\/repo}","subscriptions_url":"https:\/\/api.github.com\/users\/bryant1410\/subscriptions","organizations_url":"https:\/\/api.github.com\/users\/bryant1410\/orgs","repos_url":"https:\/\/api.github.com\/users\/bryant1410\/repos","events_url":"https:\/\/api.github.com\/users\/bryant1410\/events{\/privacy}","received_events_url":"https:\/\/api.github.com\/users\/bryant1410\/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2017-04-17T23:26:47Z","updated_at":"2017-04-17T23:26:47Z","closed_at":null,"author_association":"NONE","pull_request":{"url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/pulls\/28","html_url":"https:\/\/github.com\/crashlytics\/secureudid\/pull\/28","diff_url":"https:\/\/github.com\/crashlytics\/secureudid\/pull\/28.diff","patch_url":"https:\/\/github.com\/crashlytics\/secureudid\/pull\/28.patch"},"body":"GitHub changed the way Markdown headings are parsed, so this change fixes it.\n\nSee [bryant1410\/readmesfix](https:\/\/github.com\/bryant1410\/readmesfix) for more information.\n\nTackles bryant1410\/readmesfix#1\n"},{"url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/13","repository_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid","labels_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/13\/labels{\/name}","comments_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/13\/comments","events_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/13\/events","html_url":"https:\/\/github.com\/crashlytics\/secureudid\/issues\/13","id":3923240,"number":13,"title":"Not working with ARC","user":{"login":"SaschaMoellering","id":1321549,"avatar_url":"https:\/\/avatars0.githubusercontent.com\/u\/1321549?v=4","gravatar_id":"","url":"https:\/\/api.github.com\/users\/SaschaMoellering","html_url":"https:\/\/github.com\/SaschaMoellering","followers_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/followers","following_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/following{\/other_user}","gists_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/gists{\/gist_id}","starred_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/starred{\/owner}{\/repo}","subscriptions_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/subscriptions","organizations_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/orgs","repos_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/repos","events_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/events{\/privacy}","received_events_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":10,"created_at":"20
You are trying to parse an array of object (from your webservices) to an object containing a property mResults which is an array of object (Test);
Instead of using Results class during parsing you need to directly use an ArrayList of Test:
Results results = gson.fromJson(response.toString(), Results.class);
should be
ArrayList<Test> results = gson.fromJson(response.toString(), new TypeToken<ArrayList<Test>>(){}.getType());
As ArrayList is a generic it's not possible to use ArrayList<Test>.class to get a representation of the data type, we must use TypeToken. What is TypeToken?
TypeToken represents a generic type T. Java doesn't yet provide a way to
represent generic types, so this class does. Forces clients to create
a subclass of this class which enables retrieval the type information
even at runtime.
getType returns the type of the class used to build TypeToken and so we can use it in gson fromJson() parsing method.
--
Second problem:
Your are using JsonObjectRequest but server response is a Json array so you need to use JsonArrayRequest and so update MyListner to use JSONArray instead of JSONObject.
BUT
As your are parsing server response manually you can use StringRequest and so avoid parsing step of Volley.
StringRequest jsonObjectRequest = new StringRequest(
Request.Method.GET,
"https://api.github.com/repos/crashlytics/secureudid/issues",
new MyListner(),
new MyErrorListner()
);
and MyListner is now directly using String:
class MyListner implements Response.Listener<String> {
#Override
public void onResponse(String response) {
Gson gson = new Gson();
ArrayList<Test> results = gson.fromJson(response, new TypeToken<ArrayList<Test>>() {}.getType());
for (Test t : results) {
Log.e("Tag", t.toString());
}
}
}
Related
This is my 1st java project.
I m using a 3rd party Flight API in Java.
Actually the issue is, if the data received only has 1 record, I get data in Object format and if data received has more than 1 record, I get data in Array format. Now the issue is, I created a POJO class in which I defined it as Array but when i get data in Object format, It gives error :
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1
public class MlFlightGetFlightAvailibilityResponse {
private MlAirlineList[] AirlineList;
public MlAirlineList[] getAirlineList() {
return AirlineList;
}
public void setAirlineList(MlAirlineList[] AirlineList) {
this.AirlineList = AirlineList;
}
#Override
public String toString() {
return "ClassPojo [AirlineList = " + AirlineList + "]";
}
}
public class MlAirlineList {
private String AirlineCode;
private String AirlineName;
public MlAirlineList(String AirlineCode, String AirlineName) {
this.AirlineCode = AirlineCode;
this.AirlineName = AirlineName;
}
public String getAirlineCode() {
return AirlineCode;
}
public void setAirlineCode(String AirlineCode) {
this.AirlineCode = AirlineCode;
}
public String getAirlineName() {
return AirlineName;
}
public void setAirlineName(String AirlineName) {
this.AirlineName = AirlineName;
}
#Override
public String toString() {
return "ClassPojo [AirlineCode = " + AirlineCode + ", AirlineName = " + AirlineName + "]";
}
}
Below is the for loop in which i get error
Map<String, String> mlFlightAirline = new HashMap<>(); // Unique Flight Airline List
Gson gson = new Gson();
MlFlightResponse mlflights = gson.fromJson(mlResponse, MlFlightResponse.class); // mlResponse is JSON response
public class MlFlightResponse {
private MlFlightGetFlightAvailibilityResponse GetFlightAvailibilityResponse;
public MlFlightGetFlightAvailibilityResponse getGetFlightAvailibilityResponse() {
return GetFlightAvailibilityResponse;
}
public void setGetFlightAvailibilityResponse(MlFlightGetFlightAvailibilityResponse GetFlightAvailibilityResponse) {
this.GetFlightAvailibilityResponse = GetFlightAvailibilityResponse;
}
#Override
public String toString() {
return "ClassPojo [GetFlightAvailibilityResponse = " + GetFlightAvailibilityResponse + "]";
}
}
for (MlAirlineList airline : mlflights.getGetFlightAvailibilityResponse().getAirlineList()) {
mlFlightAirline.put(airline.getAirlineCode(), airline.getAirlineName());
}
In Above code, MlAirlineList sometimes comes as Array and sometimes has Object based on number of records available.
Object Data Format:
{
"AirlineList": {
"AirlineCode":"test",
"AirlineName":"test"
}
}
{
"AirlineList": [{
"AirlineCode":"test",
"AirlineName":"test"
},
{
"AirlineCode":"test",
"AirlineName":"test"
}]
}
Please guide me in right direction.
Thanks
From what I can see you have an Array of Arrays in JSON response you are trying to process.
Try
for (MlAirlineList airline : mlflights.getGetFlightAvailibilityResponse().getAirlineList()) {
mlFlightAirline.put(airline[0], airline[1]);
}
You can put manual check for this for hot-fix.If response start with "{" and ends with "}" then you can add [ and ] into the response in start and end part .this will surely work
How to convert given json response
{
"name" : "John",
"surname" : "Doe",
"location" : {
"name" : "Paris",
"desc" : "Welcome to Paris"
}
}
into
class Person
{
String name;
String surname;
Location location; // new Location(String name, String desc)
}
It's all about nested Location class that is inside Person class
Use #Expose or #SerializedName annotation like
class Person
{
#SerializedName("name")
String name;
#SerializedName("surname")
String surname;
#SerializedName("location")
Location location; // new Location(String name, String desc)
}
and Location class like
class Location
{
#SerializedName("name")
String name;
#SerializedName("desc")
String desc;
}
Add getter and setter method for accessing data
Use a combination of Gson + Retrofit.
First of all use the annotation #SerializedName("yourFieldName") that Retrofit provides in the fields of your model class.
Init your Gson configuration with a RuntimeTypeAdapterFactory:
RuntimeTypeAdapterFactory<Person> itemFactory = RuntimeTypeAdapterFactory
.of(Person.class) // The field that defines the type
.registerSubtype(Location.class, "location")
.registerSubtype(YourSubclass.class) // if the flag equals the class name, you can skip the second parameter.
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(itemFactory)
.create();
Then you init Retrofit:
Retrofit.Builder builder = new Retrofit.Builder();
builder.baseUrl(BASE_URL);
builder.addConverterFactory(GsonConverterFactory.create(gson));
Retrofit retrofit = builder.build();
First get an API and get its JSON output by Advance REST Client which is a Chrome Extension. Now put that output to JSON to POJO converter
and you'll get your POJO Classes. Paste them to your project. Make an interface`
/**
* Get Data
*
* #param body Holds the JSON payloads
* #return Formatted data
*/
#POST("JobSpotAPI/getUserInterviewSchedule")
Call<POJOClass> getData(#Body JsonObject body);
and setup a Client
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
Create a Recycler view setup its adapter and all. Just add a few new methods like-
public void updateAnswers(List<Item> items) {
mItems = items;
notifyDataSetChanged();
}
private Item getItem(int adapterPosition) {
return mItems.get(adapterPosition);
}
Setup Utility class to call the interface.
public class ApiUtils {
public static final String BASE_URL = "https://base_url/";
public static Interface_name methodName() {
return RetrofitClient.getClient(BASE_URL).create(Interface_name.class);
}}
Declare the Interface in your Activity
Interface_name obj = ApiUtils.methodName();
If you have some payloads then attach them to you request. Before that you need a JSON string to pass to API request. To make a JSON Payload.
private JsonObject makeJsonObjectPayload() {
JsonObject requestBean = new JsonObject();
requestBean.addProperty("key", value);
requestBean.addProperty("key", value);
requestBean.addProperty("key", value);
requestBean.addProperty("key", value);
return requestBean;
Pass the API request
obj.getData(makeJsonObjectPayload()).enqueue(new Callback<POJOClass>() {
#Override
public void onResponse(Call<POJOClass> call, Response<POJOClass> response) {
if(response.isSuccessful()) {
mAdapter.updateAnswers(response.body().getItems());
Log.d("MainActivity", "posts loaded from API");
}else {
int statusCode = response.code();
// handle request errors depending on status code
}
}
#Override
public void onFailure(Call<UserDataPOJOClass> call, Throwable t) {
//showErrorMessage();
Log.d("API ERROR",""+t.getMessage());
Log.d("MainActivity", "error loading from API");
}
});
I'm trying to deserialize a JSON which containes a String and a list of objects in my Spring web application.
JSON
[
{
"jsonrpc":"2.0",
"result":[
{
"event":{
"id":"27809810",
"name":"Spezia v Trapani",
"countryCode":"IT",
"timezone":"Europe/London",
"openDate":"2016-05-28T16:30:00.000Z"
},
"marketCount":13
},
{
"event":{
"id":"27811083",
"name":"Torino U19 v Atalanta U19",
"countryCode":"IT",
"timezone":"Europe/London",
"openDate":"2016-05-29T16:15:00.000Z"
},
"marketCount":18
},
...
]
My classes are:
ListEventsResponse class
public class ListEventsResponse {
private String jsonrpc;
private List<ListEventsResult> result;
public ListEventsResponse() { }
public String getJsonrpc() {
return jsonrpc;
}
public void setJsonrpc(String jsonrpc) {
this.jsonrpc = jsonrpc;
}
public List<ListEventsResult> getResult() {
return result;
}
public void setResult(List<ListEventsResult> result) {
this.result = result;
}
}
ListEventsResult class
public class ListEventsResult {
private Event event;
private int marketCount;
public ListEventsResult() { }
public Event getEvent() {
return event;
}
public void setEvent(Event event) {
this.event = event;
}
public int getMarketCount() {
return marketCount;
}
public void setMarketCount(int marketCount) {
this.marketCount = marketCount;
}
}
I have also Event class, composed by 5 String (id, name, etc.).
Controller
[...]
ListEventsResponse listEvents = new Gson().fromJson(response.toString(), ListEventsResponse.class);
List<ListEventsResult> eventsList = listEvents.getResult();
return new ModelAndView("page", "eventsList", eventsList);
My .jsp page
[...]
<c:forEach items="${eventsList}" var="listEventsResult">
Match: <c:out value="${listEventsResult.name}"/>
</c:forEach>
[...]
My code runs and doesn't give any error, but no match is shown on my page, in fact listEvents doesn't contains any object.
I can't understand how to deserialize properly the list of objects, so my question is: which logic is behind the deserialization of a json which contains a list of objects?
I post my code just to explain better my problem.
As you have a Json Array as response , you need to deserialize like below
Gson gson = new Gson();
Type type = new TypeToken<List<ListEventsResponse>>(){}.getType();
List<ListEventsResponse> events = (List<ListEventsResponse>) gson.fromJson(response.toString(), type);
I want to interact with a RESTful webservice that responds only in JSON.
Any successful response from the server has this syntax:
{
"code": int code,
"data": object or list of objects
}
while on error response:
{
"code": int code,
"error": string,
"details": string
}
So I made two classes in my Android project like this (for GSON reflection):
public class ErrorEntity {
private String details;
private String error;
private int code;
public ErrorEntity() {
// Stub constructor
}
public String getDetails() {
return details;
}
public String getError() {
return error;
}
public int getCode() {
return code;
}
}
For a successful response I made a generic because I don't want to parse JSON data on overridden parseNetworkResponse:
public class SuccessfulEntity<T> {
private T data;
private int code;
public SuccessfulEntity() {
// Stub content
}
public T getData() {
return data;
}
public int getCode() {
return code;
}
}
Now, because my RESTful server requires some custom headers, I need to make a Request subclass, but I don't know from which class I need to inherit.
I saw this question: Send POST request with JSON data using Volley and though to do something like that.
Basically, I want to make a new class (VolleyRestClient) which has GET, POST, DELETE methods and API routings, and with this class make all requests I need to do.
Methods of this class need to make a new custom request and parse new objects response like SuccessfulEntity and ErrorEntity, and then parsing data in service/thread that make the VolleyRestClient call.
How can I do that?
After a long fight with generics and type erasure, I finally did it.
So I'm posting this for whoever has the same issue like me and needs a solution without freaking out.
My ErrorEntity and my SuccessfulEntity are still the same, but I created a new interface called RepositoryListener, like this:
public interface RepositoryListener {
public abstract void onErrorResponse(int code, String details);
public abstract void onSuccessfulResponse(int code, Object obj);
public abstract void onSuccessfulResponse2(int code, List<Object> obj);
}
Then I made a class, VolleyRestClient, like this:
public class VolleyRestClient extends RestClient {
private final DefaultRetryPolicy mRetryPolicy;
private final RequestQueue mQueue;
private final Gson gson = new Gson();
public VolleyRestClient(Context context) {
// Default retry policy
mRetryPolicy = new DefaultRetryPolicy(2000, 3, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
mQueue = Volley.newRequestQueue(context);
}
public RequestQueue getQueue() {
// Method to push requests for image download
return mQueue;
}
#Override
public void GET(boolean obj, boolean needAuth, String url, Type type,
RepositoryListener listener) {
// Choose which listener to construct
Response.Listener<myResponse> mListener = obj ?
// This uses objects
makeSuccessfulListener(listener, type) :
// This uses list of objects
makeSuccessfulListener2(listener, type);
myRequest mRequest =
new myRequest(Request.Method.GET, needAuth, url,
mListener, makeErrorListener(listener));
mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}
#Override
public void POST(boolean needAuth, String url, String body, Type type, RepositoryListener listener) {
myRequest mRequest = new myRequest(Request.Method.POST, needAuth, url, body,
makeSuccessfulListener(listener, type), makeErrorListener(listener));
mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}
#Override
public void DELETE(boolean needAuth, String url, Type type, RepositoryListener listener) {
myRequest mRequest =
new myRequest(Request.Method.DELETE, needAuth, url,
makeSuccessfulListener(listener, type), makeErrorListener(listener));
mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}
private Response.Listener<myRequest> makeSuccessfulListener
(final RepositoryListener listener, final Type type) {
// TODO: test this method and implement lists
if (listener == null) {
return null;
} else {
return new Response.Listener<myRequest>() {
#Override
public void onResponse(myRequest response) {
SuccessfulEntity<Object> obj = gson.fromJson(response.getBody(), type);
listener.onSuccessfulResponse(response.getCode(), obj.getData());
}
};
}
}
private Response.Listener<myRequest> makeSuccessfulListener2
(final RepositoryListener listener, final Type type) {
// TODO: test lists
if (listener == null) {
return null;
} else {
return new Response.Listener<myRequest>() {
#Override
public void onResponse(myReqyest response) {
SuccessfulEntity<List<Object>> obj = gson.fromJson(response.getBody(), type);
listener.onSuccessfulResponse2(response.getCode(), obj.getData());
}
};
}
}
private Response.ErrorListener makeErrorListener(final RepositoryListener listener) {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try {
String jError = new String(error.networkResponse.data);
ErrorEntity mError = gson.fromJson(jError, ErrorEntity.class);
// Invoke listener closure
listener.onErrorResponse(error.networkResponse.statusCode, mError.getDetails());
} catch (Exception e) {
listener.onErrorResponse(404, e.getMessage());
}
}
};
}
}
This is very dependant by my needs, but I'll explain the general concept.
So I have a custom request, as explained in my question, and I want to parse it to the correct data type.
To be more specific, I could have a JSONArray data only on GET requests (paginated elements, etc...) so I need to find a way to distinguish between this two cases (of course, I know in which cases I'll get a List or an Object).
We cannot simply create POJO from Json within a generic class using its type (because Java Type Erasure), so we need object type upfront.
But what we can do is:
in our custom request, on parseNetworkResponse, do something like that:
#Override
protected Response<myResponse> parseNetworkResponse(NetworkResponse response) {
try {
// Using server charset
myResponse mResponse = new myResponse();
mResponse.setCode(response.statusCode);
mResponse.setBody(new String(response.data,
HttpHeaderParser.parseCharset(response.headers)));
// Return new response
return Response.success(mResponse, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
// Normally use 'utf-8'
return Response.error(new ParseError(e));
}
}
In other words, copy the raw string response body onto a new object myResponse;
Response body will be eventually parsed in VolleyRestClient with the appropriate type passed as a GET/DELETE/POST argument;
makeSuccessfulListener and makeSuccessfulListener2 construct a Response.Listener from a RepositoryListener, which has 3 methods to override: onSuccessfulResponse for objects data, onSuccessfulResponse2 for list of objects data, onErrorResponse for 4XX/5XX errors;
Our data object/list will be parsed to more generics type (List and Object) and then passed to our custom listener RepositoryListener.
A full example for this approach:
public void getNewLogin(String nickname, String password,
final TextView author, final TextView title, final TextView text) {
String json =
(new StringBuilder()
.append("{ \"nickname\": \"")
.append(nickname)
.append("\", \"password\": \"")
.append(password)
.append("\" }")).toString();
mRest.POST(false, "http://192.168.0.104:8000/api/session", json,
new TypeToken<SuccessfulEntity<Login>>(){}.getType(),
new RepositoryListener() {
#Override
public void onSuccessfulResponse2(int code, List<Object> obj) {
// Nothing happens here
}
#Override
public void onSuccessfulResponse(int code, Object obj) {
UserSession mInstance = UserSession.getInstance(null);
Login newLogin = (Login) obj;
title.setText(newLogin.getToken());
mInstance.setToken(newLogin.getToken());
Log.i("onSuccessfulResponse", mInstance.getToken());
Log.i("onSuccessfulResponse", mInstance.getmAuthorizationToken());
if (newLogin.getUser() != null) {
author.setText(newLogin.getUser().getNickname());
text.setText(newLogin.getUser().getUniversity());
}
}
#Override
public void onErrorResponse(int code, String error) {
Log.i("onErrorResponse", error);
}
});
mRest is a VolleyRestClient object, which performs a POST request to that address with Type constructed by Gson TypeToken (remember, our body is a SuccessfulEntity).
Since we'll have an Object data for sure, we'll just override onSuccessfulResponse, cast data object to the same type T of SuccessfulEntity used in TypeToken, and do our dirty work.
I don't know if I was clear, this approach works, if some of you needs some clarification, just ask :)
I have an android project in which I use a class to send http requests using the Volley library.
It is called WebServicesAdapter. I used a callback in it to return a value to the called activity but it prevents the new activity from starting because of some problems in the context.
How can I return a string without using a callback?
Below is my code. successcallback is the callback when I want to return a string instead.
public class WebServiceAdapter {
private static String BASE_URI = "http://192.168.42.94/getvoize/index.php";
private RequestQueue rQueue;
public String responseString;
public String status;
Context context;
public WebServiceAdapter(Context context){
this.context = context;
status = "new";
rQueue = Volley.newRequestQueue(context);
}
private WebServiceInterface wsi;
public void sendGetRequest(String page,Map<String,String> map, WebServiceInterface i){
wsi = i;
String query = "";
if(!map.isEmpty()){
for (Map.Entry<String, String> entry : map.entrySet())
{
query =query + entry.getKey()+"="+entry.getValue()+'&';
}
}
if(query.length() != 0)
query = query.substring(0,query.length()-1);
StringRequest sRequest = new StringRequest(Request.Method.GET,BASE_URI+page+"?"+query,
new Response.Listener<String>() {
#Override
public void onResponse(String response){
wsi.successCallback(response,context);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error){
wsi.errorCallback("failed",context);
}
});
rQueue.add(sRequest);
}
private Map<String,String> parameter;
private Map<String,String> headers;
public void sendPostRequest(String page,Map<String,String> body,Map<String,String> header,WebServiceInterface i){
wsi = i;
parameter = body;
headers = header;
Log.d("place", "Inpost");
StringRequest myReq = new StringRequest(Request.Method.POST,
BASE_URI+page,
new Response.Listener<String>() {
#Override
public void onResponse(String response){
wsi.successCallback(response, context);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error){
wsi.errorCallback("Failed", context);
}
}
) {
#Override
protected Map<String,String> getParams(){
Map<String,String> params = parameter;
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> params = headers;
return params;
}
};
rQueue.add(myReq);
}
You have not posted activity code where you are trying to start new activity. It would be helpful if you can share that piece here along with error logs if any.
In case you are trying to launch an activity from callback in the calling Activity, remember to do it in Main Thread (assuming the web servie is called from thread other than main thread).
Other input worth mentioning is - from your callback to activity, context is not required to be passed back. It would be readily available there in activity.
you can use below code:
runOnUiThread(new Runnable() {
public void run() {
//startActivity code here.
}
});
Define your callback interface (I assume you already have this and WebServiceInterface is the callback interface).
Your Activity should implement this interface.
Add a parameter WebServiceInterface to the WebServiceAdapter constructor. The constructor should store this in a private member variable.
When your Activity creates an instance of WebServiceAdapter, it should pass this as the WebServiceInterface parameter.
WHen you want to call back the Activity, just make your calls on the stored private member variable.