i have included the retrofit dependency in my project but still i m getting error on response object.
here is my code:
public void jsontesting() {
RestAdapter restAdapter = (RestAdapter) new RestAdapter.Builder().setEndpoint("http://app-development.in/doctor_app_cms/doctor_rest/v1/doctors_listing?id=10").build();
final LatlngAPI get = restAdapter.create(LatlngAPI.class);
get.get_doctor(new retrofit.Callback<CustomeAdapter>()) {
#Override
public void success(CustomeAdapter res, Response response) {
if (!res.getError()) {
// dismiss_dialog();
} else {
/*Toast.makeText(LoginActivity.this, R.string.retrofit_error,
Toast.LENGTH_SHORT).show();*/
}
}
#Override
public void failure(RetrofitError error) {
// dismiss_dialog();
Log.d("Error", error.toString());
/*Toast.makeText(LoginActivity.this, R.string.retrofit_error,
Toast.LENGTH_SHORT).show();*/
}
});
}
I have solved my error. The problem was I am importing wrong response.
Related
I sent request with postman its working, but volley doesn't work. I always get error! I searched stackoverflow volley returns error when response is empty but i added CustomJsonObjectRequest still the issue remains.
Error message
Volley org.json.JSONException: End of input at character 0 of
CustomJsonObjectRequest
public class CustomJsonObjectRequest extends JsonObjectRequest {
public CustomJsonObjectRequest(int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
super(method, url, jsonRequest, listener, errorListener);
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
if (response.data.length == 0) {
byte[] responseData = "{}".getBytes("UTF8");
response = new NetworkResponse(response.statusCode, responseData, response.headers, response.notModified);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return super.parseNetworkResponse(response);
}
}
Volley request
EcoElement ecoElement = ecoElementArrayList.get(position);
Map<String, String> params = new HashMap<String, String>();
params.put("Id", ecoElement.getId().toString());
params.put("Checked", ecoElement.getChecked().toString());
JSONObject ObjParams = new JSONObject(params);
try {
CustomJsonObjectRequest getRequest = new CustomJsonObjectRequest(Request.Method.PUT, "https://ourwebsite.sslbeta.de/api/gardenapi/updateecoelements", ObjParams,
response -> {
Toast.makeText(getContext(), ""+response, Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
},
error -> {
Toast.makeText(getContext(), ""+error.toString(), Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
);
RequestQueueSingleton.getInstance(getContext()).addToRequestQueue(getRequest);
} catch (Exception e) {
Toast.makeText(getContext(), e.toString(), Toast.LENGTH_LONG).show();
}
Finally i was able to fix the issues after hours of searching. There were two reasons to this, first is that api was returning null/empty so CustomJsonObjectRequest fixed that, and then another issue is that i forgot to add authentication headers. that was a silly mistake i know!
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("Authorization", "Bearer "+access_token);
return headers;
}
};
Here is the solution, just create this method and pass your value.
private void CustomJsonObjectRequest() {
String tag_string_req = "req__details";
StringRequest strReq = new StringRequest(Request.Method.POST, <API URL>, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
getPerspective().showErrorLogs(TAG, "Response Invest : " + response);
try {
// Parse your response here
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("Id", <ID VALUE HERE>);
params.put("Checked", <TRUE or FALSE>);
return params;
}
};
strReq.setRetryPolicy(new RetryPolicy() {
#Override
public void retry(VolleyError arg0) throws VolleyError {
}
#Override
public int getCurrentTimeout() {
return 0;
}
#Override
public int getCurrentRetryCount() {
return 0;
}
});
strReq.setShouldCache(false);
addToRequestQueue(strReq, tag_string_req);
}
Both ID and Checked must have String type.And create below methods in MainActivity:
private RequestQueue mRequestQueue;
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
By This code, I am not able to get the error response as if I use same email id twice then I am getting the error response in postman but in my application, I am not getting the error response
So can you please help me to get out of this
My Interface
public interface SignupAPI {
#FormUrlEncoded
#POST("users")
Call<ResponseBody> createUser(
#Field("email") String email,
#Field("password") String password,
#Field("role") String role
);
}
My Java Code
public class SignupClient {
private static final String BASE_URL = "http://74.207.233.160/api/v1/";
private static SignupClient mInstance;
private Retrofit retrofit;
private SignupClient(){
retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
}
public static synchronized SignupClient getmInstance(){
if (mInstance == null){
mInstance = new SignupClient();
}
return mInstance;
}
public SignupAPI getApi(){
return retrofit.create(SignupAPI.class);
}
}
My Activity
Call<ResponseBody> call = SignupClient.getmInstance().getApi().createUser(email, password,role);
call.enqueue(new Callback<ResponseBody>()
{
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response)
{
if (response.isSuccessful()){
progressBar.setVisibility(View.GONE);
Toast.makeText(SignupActivity.this, "Account Sucessfully Created", Toast.LENGTH_SHORT).show();
}else {
try {
progressBar.setVisibility(View.GONE);
JSONObject jsonError = new
JSONObject(response.errorBody().string());
Toast.makeText(SignupActivity.this, jsonError.getString("errors"),Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
progressBar.setVisibility(View.GONE);
e.printStackTrace();
} catch (IOException e) {
progressBar.setVisibility(View.GONE);
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(SignupActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
make error pojo class..
public class Errors{
#SerializedName("email")
private List<String> email;
public void setEmail(List<String> email){
this.email = email;
}
public List<String> getEmail(){
return email;
}
}
make changes into response body class..
public class ResponseBody {
#SerializedName("errors")
private Errors errors;
public void setErrors(Errors errors){
this.errors = errors;
}
public Errors getErrors(){
return errors;
}
}
then after used into api response like
Errors errors=response.body().getErrors();
In my app, I want to use Retrofit2 to connect to the server and get some data.
For this, I've written the code as shown below but it doesn't show the data. And for some reason, no (detailed) error is outputted.
private void getDetailData(String auctionID, final String jwtToken) {
showLoading(true);
Call<DetailResponse> call = apis.getDetainAuctions(auctionID, jwtToken, agent);
call.enqueue(new Callback<DetailResponse>() {
#Override
public void onResponse(Call<DetailResponse> call, final Response<DetailResponse> response) {
Log.e("detailLog", "OK");
Log.e("detailLog", response.message() + " --- " + response.errorBody());
if (response.isSuccessful()) {
}
}
#Override
public void onFailure(Call<DetailResponse> call, Throwable t) {
Log.e("detailLog", "Err : " + t.getMessage());
}
});
}
Logcat error:
E/detailLog: --- okhttp3.ResponseBody$1#cbf85bc
What does the error mean?
I am trying to create REST apis to perform write operations using Firebase Server SDK and Jersey.
Here is what I am trying to do:
Initializing Firebase SDK
Getting idToken from Client and Validating idToken
Performing some write operations on few Firebase nodes
Sending api Response
I want to return Response only if Firebase write operation succeeds or fails.
That happens inside of Firebase Listeners. However, I try to return value from Listeners, I get error becuase Firebase listeners have void return type.
How can I return response from the listener?
Here is my code.
MyEndpoint.java
#Path("/restapi")
//BaseEndpoint does Authentication operations
public class MyEndpoint extends BaseEndpoint {
public void Authenticate(String token, AuthenticationListener authenticationResultListener) {
super.Authenticate(token, authenticationResultListener);
}
#POST
#Produces("application/json")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response createCommunity(#FormParam("idToken") String idToken) {
Authenticate(idToken, new AuthenticationListener() {
#Override
public void onAuthenticationSuccess() {
// The app only has access as defined in the Security Rules
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("/mysamplenode");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
String res = dataSnapshot.getKey();
//I will do some write operations on Firebase here
//If they complete successfuly only then I want to return api response
return Response.status(200).entity().build();
}
#Override
public void onCancelled(DatabaseError arg0) {
System.out.println("DatabaseError-------------" + arg0);
return Response.status(500).entity("DatabaseError").build();
}
});
}
#Override
public void onAuthenticationFailure() {
return Response.status(403).entity("Forbidden").build();
}
});
}
}
BaseEndpoint.java
public class BaseEndpoint {
public static String uid;
public void Authenticate(String token, AuthenticationListener authenticationResultListener) {
// idToken comes from the client app
FirebaseAuth.getInstance().verifyIdToken(token).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception arg0) {
System.out.println("Uid exp= " + arg0);
authenticationResultListener.onAuthenticationFailure();
}
}).addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
uid = decodedToken.getUid();
System.out.println("Uid= " + uid);
authenticationResultListener.onAuthenticationSuccess();
}
});
}
}
So I'm guessing the Firebase SDK is asynchronous in nature. In which case, if you're using Jersey 2.x, you can use the asynchronous server support. You can just call AsyncResponse.resume(Response) in your callbacks. For example
#POST
#Produces("application/json")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void createCommunity(#FormParam("idToken") String idToken,
#Suspended final AsyncResponse response) {
Authenticate(idToken, new AuthenticationListener() {
#Override
public void onAuthenticationSuccess() {
DatabaseReference ref = FirebaseDatabase.getInstance()
.getReference("/mysamplenode");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
String res = dataSnapshot.getKey();
response.resume(Response.status(200).entity().build());
}
#Override
public void onCancelled(DatabaseError arg0) {
response.resume(Response.status(500).entity("DatabaseError").build());
}
});
}
#Override
public void onAuthenticationFailure() {
response.resume(Response.status(403).entity("Forbidden").build());
}
});
}
If you're using Jersey 1.x, there's not really an async option. You just need to block flow with a CountDownLatch, assign a local Response in the callbacks, and count down.
#POST
#Produces("application/json")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void createCommunity(#FormParam("idToken") String idToken) {
Response response;
CountDownLatch latch = new CountDownLatch(1);
Authenticate(idToken, new AuthenticationListener() {
#Override
public void onAuthenticationSuccess() {
DatabaseReference ref = FirebaseDatabase.getInstance()
.getReference("/mysamplenode");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
String res = dataSnapshot.getKey();
response = Response.status(200).entity().build();
latch.countDown();
}
#Override
public void onCancelled(DatabaseError arg0) {
response = Response.status(500).entity("DatabaseError").build();
latch.countDown();
}
});
}
#Override
public void onAuthenticationFailure() {
response = Response.status(403).entity("Forbidden").build();
latch.countDown();
}
});
latch.await();
return response;
}
I might be a little late in answering this question, but after trying the Firebase server SDK out I found that you can create a Task available in the SDK to wait for a response synchronously. The snippet below might help you out:
public class BaseEndpoint {
public static String uid;
public void Authenticate(String token, AuthenticationListener authenticationResultListener) {
// idToken comes from the client app
FirebaseToken firebaseToken = null;
try {
Task<FirebaseToken> authTask = FirebaseAuth.getInstance().verifyIdToken(token);
Tasks.await(authTask);
firebaseToken = authTask.getResult();
} catch (Exception e) {
authenticationResultListener.onAuthenticationFailure();
}
uid = firebaseToken.getUid();
System.out.println("Uid= " + uid);
authenticationResultListener.onAuthenticationSuccess();
}
}
I need execute a Volley request and wait for the response to parse it and return it, but have no idea on how to achieve this. Can someone help?
What I have now is this:
public String getLink() {
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
shortenURL = response.getString("url");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
});
queue.add(jsObjRequest);
return shortenURL;
}
A reusable Factory method design pattern solution:
To return or get Volley response from another method, you need to write a Callback functionality, which is all easy using Interfaces
This simple solution is taken from my MVC architecture for Android apps developed with complete reusability and separation of concern concept.
Supposing JSONObject is your response from server
Step 1)
Create an Interface ServerCallback
package xx.xx.xx.utils;
import org.json.JSONObject;
public interface ServerCallback{
void onSuccess(JSONObject result);
}
Step 2) Supposing yours Volley server request method is in Controller or any other shared 'context' class do this in yours any Activity
Controller controller = new Controller();
controller.youFunctionForVolleyRequest(email, password, this, loginUrl, new ServerCallback() {
#Override
public void onSuccess(JSONObject response) {
// do stuff here
}
}
);
3) In your Controller class, call ServerCallback function in inResponse() which will execute yours code in Activity only on the response from the server- mission accomplished!
public void youFunctionForVolleyRequest(final String email , final String password ,final Context context , final String URL, final ServerCallback callback)
{
HashMap<String, String> params = new HashMap<String, String>();
params.put("email", email);
params.put("password", password);
Log.e("sending json",params.toString());
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
URL, new JSONObject(params), new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response) {
callback.onSuccess(response); // call call back function here
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//VolleyLog.d("Volley error json object ", "Error: " + error.getMessage());
}
}){
#Override
public String getBodyContentType()
{
return "application/json";
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq);
}
You should probably not return the link in your method.
Volley is doing asynchronous tasks, it means that you can't know when the answer will arrive from your webservice, it could be 10sec or 10min.
If you need the string in your function you should probably create a method and call it when you have the result.
Here is an example:
I guess this is what you have
public void getTheLinkAndCallDoSomething(){
String link = getLink();
doSomethingWithTheLink(link);
}
This would work if getLink() answers in a synchronous way. Volley is not in this case.
And this is what you can do with Volley:
public void getTheLinkAndCallDoSomething(){
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET,
url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
shortenURL = response.getString("url");
doSomethingWithTheLink(shortenURL);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
});
queue.add(jsObjRequest);
}
In this case, you call the WS to get your url. And as soon as the result is known, you call doSomethingWithTheLink()
Whatever, if you really do want to be synchronous you can look at this post : Wait for result of Async Volley request and return it
Also, be aware that waiting for an answer could freeze your app UI and I guess that is not what you want.
you cannot return anydata in your getLink() method.
Use your code as
String shortenURL = ""; // activity global variable
public void getLink() {
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
shortenURL = response.getString("url");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
});
queue.add(jsObjRequest);
}
You can also see more info at
http://arnab.ch/blog/2013/08/asynchronous-http-requests-in-android-using-volley/
You can do this using the future concept
RequestFuture<JSONObject> jsonObjectRequestFuture = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(ServiceUrl.BFF_BASE_URL + path, (JSONObject) postBody, jsonObjectRequestFuture, jsonObjectRequestFuture);
requestQueue.add(request);
JSONObject jsonObject = jsonObjectRequestFuture.get(30, TimeUnit.SECONDS);