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.
Related
I need to get json data response based on SECRET CODE with POST method, would you please solve my issue, thanks in advance.
I have been facing with many problems with this POST method of Secret Code to get the JSON Response
public class MainActivity extends AppCompatActivity {
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listViewHeroes);
getQuestions();
}
private void getQuestions() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) //Here we are using the GsonConverterFactory to directly convert json data to object
.build();
ApiInterface api = retrofit.create(ApiInterface.class);
RequestModel requestModel = new RequestModel();
requestModel.setSecretCode("341977082");
Call<List<ModelObjects>> call = api.getQuestions();
call.enqueue(new Callback<List<ModelObjects>>() {
#Override
public void onResponse(Call<List<ModelObjects>> call, Response<List<ModelObjects>> response) {
List<ModelObjects> questionsList = response.body();
String[] questions = new String[questionsList.size()];
for (int i = 0; i < questionsList.size(); i++) {
questions[i] = questionsList.get(i).getQues_No();
}
listView.setAdapter(new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, questions));
}
#Override
public void onFailure(Call<List<ModelObjects>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});}}
Here is the interface and where I am passing the URL that contains parent and extension
public interface ApiInterface {
String BASE_URL = "";
#POST("QuestionsList")
Call<List<ModelObjects>> getQuestions();}
Here is the response Model
public class ModelObjects {
#SerializedName("Ques_No")
private String Ques_No;
public ModelObjects(String ques_No) {
Ques_No = ques_No;
}
public String getQues_No() {
return Ques_No;
}
public void setQues_No(String ques_No) {
Ques_No = ques_No;
}}
Here is the Request Model
public class RequestModel {
private String SecretCode;
public RequestModel(String secretCode) {
SecretCode = secretCode;
}
public RequestModel() {
}
public String getSecretCode() {
return SecretCode;
}
public void setSecretCode(String secretCode) {
SecretCode = secretCode;
}}
Here you have defined RequestModel but you are not passing it to the api call. Post request should have body.
So specify #Body while defining the api call as below.
#POST("QuestionsList")
Call<List<ModelObjects>> getQuestions(#Body RequestModel model);
Then while calling the getQuestion() pass the model.
RequestModel requestModel = new RequestModel();
requestModel.setSecretCode("341977082");
Call<List<ModelObjects>> call = api.getQuestions(requestModel);
Update :
update your ModelObject as below.
public class ModelObjects {
#SerializedName("Ques_No")
String Ques_No;
#SerializedName("Question")
String Ques;
#SerializedName("Answer")
String answer;
//same for other params as well
}
What can i see it, you are creating object of RequestModel class, but you are not passing it anywhere. If you want to send the secretCode along with the post network call, then you'll have to pass this requestModel instance to the call.
public interface ApiInterface {
String BASE_URL = "";
#POST("QuestionsList")
Call<List<ModelObjects>> getQuestions(#Body RequestModel requestModel);
}
then you can call this method and can pass this requestModel Object by
Call<List<ModelObjects>> call = api.getQuestions(requestModel);
If you want to access the first object you can do it by
List<ModelObjects> questionsList = response.body();
ModelObject obj = questionList.get(0);
String question = obj.getQues_No();
This question is going to be the first question.
I am developing application which having Parse Platform. To fetch data I am calling ParseCloud.callFunctionInBackground function.
I have registered the Parse and its sub class into the Application class like below :
public class App extends Application {
#Override
public void onCreate(){
super.onCreate();
Parse.setLogLevel(Parse.LOG_LEVEL_VERBOSE);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.networkInterceptors().add(httpLoggingInterceptor);
ParseObject.registerSubclass(ParseMessage.class);
Parse.initialize(new Parse.Configuration.Builder(this)
.applicationId("KEY")
.server("URL")
.build());
}
}
I have below model class which extends ParseObject :
#ParseClassName("ParseMessage")
public class ParseMessage extends ParseObject {
// Ensure that your subclass has a public default constructor
public ParseMessage() {
super();
}
public ParsePhoto getPhotos() {
return (ParsePhoto) getParseObject("photos");
}
public void setPhotos(ParsePhoto value) {
put("photos", value);
}
public String getCaption() {
return getString("caption");
}
public void setCaption(String value) {
put("caption", value);
}
}
When I calling this below method from my Fragment :
HashMap<String, Object> params = new HashMap<String, Object>();
ParseCloud.callFunctionInBackground("MY_METHOD", params, new FunctionCallback<ArrayList<ParseMessage>>() {
public void done(ArrayList<ParseMessage> mapObject, ParseException e) {
if (e == null) {
ParseMessage object = mapObject.get(i);
}
} else {
}
}
});
But I am getting below exception :
java.lang.ClassCastException: com.parse.ParseObject cannot be cast to
com.example.ParseMessage
I already searched lots of thins from Google and Stackoverflow, but I did not get any solutions of it. Can anyone help me into this as I already spend a lot of time on this. Below response which I am getting from Parse :
The info you have provided is not very concrete, but from the debugger screen, it looks like you are trying to convert ParsePhoto into ParseMessage. ParsePhoto is subclass of ParseObject, and I believe this is causing the issue.
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());
}
}
}
I'm studying Volley library and in particular I'm dealing with JSONObject requests. In several tutorials I can find examples like this:
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET,
url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// ...
}
}
, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// ...
}
});
but now I'm wondering if there is a way to bind a custom class to request object or result object.
I mean: I'd like to map the key-value result to some strong-typed custom object in my app domain. Is this possible or should I implement this feature by myself?
I guess it would help you.
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Method.POST,url,your_json_object,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// On Success
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// On Failure
}
});
MyApplication.getInstance().addToRequestQueue(jsObjRequest, tag);
Pass your your_json_object instead of mine.
Done
You can use Gson library like this:
https://gist.github.com/ficusk/5474673
Supposing your goal is to GET a Name object, where Name is defined as
public class Name{
private String firstName;
private String middleName;
private String lastName;
//constructor, getter, setter
}
then you could use Gson to convert the JSONObject to Name
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET,
url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Gson gson = new Gson();
Name name = gson.fromJson(response.toString(),Name.class);
//use Name.
}
}
, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// ...
}
});
#Lissf's answer is a good way to avoid boilerplate.
However, I would recommend checking out Retrofit which can reduce this down to a single line:
#GET ("/name")
getName(Callback<Name> nameCallback);
You might want to check out RxAndroid as well.
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 :)