This is declaration of my POST request:
#POST("/api/geo/getLoc")
public void getFriendsLocation(#Field("Id") int Id, #Field("Number") String Number, #Field("FriendNumber") String FriendNumber, Callback<JsonElement> response);
This is how i try to send and handle this request:
String ENDPOINT = "http://52.88.**.***";
FriendModel ff = new FriendModel();
ff.setFriendNumber("380935275259");
ff.setId(516);
ff.setNumber("380936831127");
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ENDPOINT)
.build();
WayfAPI api = adapter.create(WayfAPI.class);
api.getFriendsLocation(ff.getId(), ff.getNumber(), ff.getFriendNumber(), new Callback<JsonElement>() {
#Override
public void success(JsonElement jsonElement, Response response) {
String strObj = jsonElement.toString();
}
#Override
public void failure(RetrofitError error) {
}
});
Error:
retrofit.RetrofitError: WayfAPI.getFriendsLocation: #Field parameters can only be used with form encoding. (parameter #1)
What's wrong with my request ?
I guess you forget #FormUrlEncoded annotation in your method declaration. It should be like this:
#FormUrlEncoded
#POST("/api/geo/getLoc")
public void getFriendsLocation(#Field("Id") int Id, #Field("Number") String Number, #Field("FriendNumber") String FriendNumber, Callback<JsonElement> response);
Related
So I have this POST request made to the server and based on an argument the server will return error message within the errorBody() of Retrofit. I am trying to handle that Plain Text error returned by the server and then display it to the user within my Android application which uses Java. Below is my current attempt but this is giving me this error in Logcat:
#Url cannot be used with #POST URL (parameter #1)
Here is 400 response from the server:
Interface:
public interface ChangePickLocationClient
{
#GET
Call<ResponseBody> checkItem(#Url String url, #Header("Authorization") String authToken);
#GET
Call<String> getStringError(#Url String url, #Header("Authorization") String authToken);
#POST("Pick/ChangePickLocationAcceptChange")
Call<String> changePickLocationPOST(#Url String url, #Header("Authorization") String authToken, #Body
ChangePickLocationPostModel changePickLocationPostModel);
}
Implementation:
private static final String BASE_URL = "http://00.00.00.1234/api/";
Gson mGson = new Gson();
Retrofit retrofit = new Retrofit.Builder().client(new OkHttpClient())
.baseUrl(BASE_URL).addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(mGson))
.build();
ChangePickLocationClient ChangePickLocationClient =
retrofitPOST.create(ChangePickLocationClient.class);
String itemNumber = itemNumberValue.getText().toString();
newPickLocationValue.setText(newPickLocationValue.getText().toString().toUpperCase());
String newPickLocation = newPickLocationValue.getText().toString();
String token = globalClass.getActiveToken();
final ChangePickLocationClient mChangePickLocationInterface =
retrofit.create(ChangePickLocationClient.class);
Call<String> mCallErrorPOST = mChangePickLocationInterface.changePickLocationPOST
(postUrl, "Bearer " + globalClass.getActiveToken(),
changePickLocationPostModel);
call.enqueue(new Callback<ChangePickLocationPostModel>()
{
#Override
public void onResponse(Call<ChangePickLocationPostModel> call,
Response<ChangePickLocationPostModel> response)
{
String mPlainTextResponse = null;
try {
if(response.errorBody() != null)
{
mPlainTextResponse = response.errorBody().string();
}
} catch (IOException e)
{
e.printStackTrace();
}
Toast.makeText(ChangePickLocation.this, mPlainTextResponse
,Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<ChangePickLocationPostModel> call, Throwable t)
{
Toast.makeText(ChangePickLocation.this, "Unknown server error!"
,Toast.LENGTH_SHORT).show();
}
});
When the response is 400, the second call being made needs to be a clone() call. This is because the Call cannot be used more than once as stated in the documentation.
use this:
call.clone().enqueue(new Callback<ChangePickLocationPostModel>()
instead of
call.enqueue(new Callback<ChangePickLocationPostModel>()
I need to execute post request with retrofit but i have a problem which i can't understand very well. Before trying with code i tested api call with Postman and request look like this:
Here is my android code:
public class API {
private static <T> T builder(Class<T> endpoint) {
return new Retrofit.Builder()
.baseUrl(Utils.API_BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(endpoint);
}
public static AllRequests request() {
return builder(AllRequests.class);
}
}
EDIT request:
#POST("api/android-feedback")
#Headers({"Content-Type: application/x-www-form-urlencoded", "Authorization: F##3FA##Rad!#%!2s"})
Call<String> sendFeedback(#Body FeedbackBody body);
FeedbackBody:
public class FeedbackBody{
private final String email;
private final String feedback;
public FeedbackBody(String email, String feedback){
this.email = email;
this.feedback = feedback;
}
}
And finally i construct the request and wait for response, the problem is that i receive message in onFail method
private void sendFeedbackRequest(){
API.request().sendFeedback(new FeedbackBody("testmeil#meil.com", "test feedback").enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
goToMainActivity();
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Toast.makeText(SplashScreenActivity.this, R.string.try_again_later, Toast.LENGTH_SHORT).show();
}
});
EDIT:
Still not working.. i think i figure it out where can be the problem, because server side wait for simple POST request without Json formatting, i think Retrofit use JSON formatting by default, and if i send POST request and format Body parameters with JSON the server will fail to parse my request, is there any chance to send simple POST request like at POSTMAN without formatting with JSON ?
Php api wait request to be send like this:
$_POST['feedback'] = 'blabla';
$_POST['email'] = 'blabla..';
and if he receive Json format request can't parse it and because of that i receive fail response.
First you need to create request( POJO Class)
public class FeedbackRequest {
public String email;
public String feedback;
}
when you call sendFeedbackRequest() pass the FeedbackRequest like below"
FeedbackRequest req = new FeedbackRequest();
req.email= "email";
req.feedback= "feedback"
sendFeedbackRequest(req)
after that your sendFeedbackRequest() should be like this
private void sendFeedbackRequest(FeedbackRequest request){
API.request().sendFeedback(request).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
goToMainActivity();
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Toast.makeText(SplashScreenActivity.this, R.string.try_again_later, Toast.LENGTH_SHORT).show();
}
});
And your retrofit request should be like this,
#FormUrlEncoded
#POST("api/android-feedback")
#Headers({"Content-Type: application/json", "Authorization: F31daaw313415"})
Call<String> sendFeedback(#Body FeedbackRequest request);
Now it should work. feel free to ask anything.
You are using a Gson converter factory. It might be easier to create a single object that represents your body, and use that instead of all individual parameters. That way, you should be able to simple follow along with the examples on the Retrofit website.enter link description here
There are also many site that let you generate your Plain Old Java Objects for you, like this one:
E.g. your Api call:
#POST("api/android-feedback")
Call<String> sendFeedback(#Body FeedbackBody feedback);
And your FeedbackBody class:
public class FeedbackBody{
private final String email;
private final String feedback;
public FeedbackBody(String email, String feedback){
this.email = email;
this.feedback = feedback;
}
}
Java:
#POST("/api/android-feedback")
Call<String> sendFeedback(#Body FeedbackBody feedback);
Kotlin:
#POST("/api/android-feedback")
fun sendFeedback(#Body feedback: FeedbackBody): Call<String>
Also, probably you forgot leading slash in the endpoint.
val formBody: RequestBody = FormBody.Builder()
.add("username", LoginRequest.username)
.add("password", LoginRequest.password)
.add("grant_type",LoginRequest.grant_type)
.add("client_id", LoginRequest.client_id)
.add("client_secret", LoginRequest.client_secret)
.add("cleartext", LoginRequest.cleartext)
.build()
#POST(EndPoints.GENERATE_TOKEN_URL)
#Headers("Content-Type: application/x-www-form-urlencoded")
suspend fun getLogin(
#Body formBody: RequestBody
): LoginResponse
I got the following response from my server: status code 201 Created.
There is no actual response (returned object, etc.), so there is not need to create a POJO class.
So, I don't know how I should handle this status code without creating a POJO class. Is there any option to make write the code without using a POJO class?
Retrofit API has Response class that can encapsulate your response.
As long as you don't want to bother with the response data you can implement your service as:
interface CustomService {
#GET("whatever")
Call<Response<Void>> getAll();
// Or using RxJava:
#GET("whatever")
Single<Response<Void>> getRxAll();
}
Then implement your callback:
private Callback<Response<Void>> responseHandler = new Callback<Response<Void>>() {
#Override
public void onResponse(Call<Response<Void>> call, Response<Response<Void>> response) {
final int code = response.code();
// TODO: Do whatever you want with the response code.
}
#Override
public void onFailure(Call<Response<Void>> call, Throwable t) {
// TODO: Handle failure.
}
}
Or reactive consumer:
private Consumer<Response<Void>> responseRxHandler = new Consumer<Response<Void>>() {
#Override
public void accept(Response<Void> response) throws Exception {
final int responseCode = response.code();
// TODO: Do whatever you want with the response code.
}
};
Debugging result:
You can try the following code.
Can get the response without a POJO class by getting using ResponseBody format and then you can parse it normally like ordinary JSON parsing.
Api Call:
Call<ResponseBody> call = service.callLogin(AppConstants.mApiKey, model_obj);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response.code() == 201)
{
JSONObject jobjresponse = null;
try {
jobjresponse = new JSONObject(mResponse.body().string());
String status = jobjresponse.getString("status");
JSONObject result = jobjresponse.getJSONObject("results");
String msg = result.getString(“msg”);
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
Retrofit Interface class:
public interface RetrofitInterface {
#Headers({"Content-Type: application/json", "Cache-Control: max-age=640000"})
#POST("v1/auth/")
public Call<ResponseBody> callLogin(#Query("key") String key, #Body LoginModel body);
public static final Retrofit retrofit = new Retrofit.Builder()
.baseUrl(“base url”)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
Sample Response:
{ "status":"true", "result":{"msg”:”created successfully”} }
I'm trying to access ticket data via skyscanner api and pass it to my view, but I cannot accomplish that, because I get 415 error code I'm using retrofit2 and adding header programmatically. My interface looks like this:
public interface GetFlightDetails {
#POST("apiservices/pricing/v1.0/")
Call<TicketData> getFlightList(#Query("apiKey") String apiKey,
#Query("country") String country,
#Query("currency") String currency,
#Query("locale") String locale,
#Query("originPlace") String originPlace,
#Query("destinationPlace") String destinationPlace,
#Query("outboundPartialDate")String outboundPartialDate,
#Query("inboundPartialDate") String inboundPartialDate,
#Query("locationschema") String locationschema,
#Query("cabinclass") String cabinclass,
#Query("adults") int adults,
#Query("children") int children,
#Query("infants") int infants,
#Query("groupPricing") boolean groupPricing) ;
}
and in my activity, when I'm ready to make a request I have the following code:
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.create();
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
//adding logging
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
httpClient.interceptors().add(logging);
//headers
httpClient.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request original = chain.request();
//adding header info
Request request = original.newBuilder()
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Accept", "application/json")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient.build())
.build();
GetFlightDetails api = retrofit.create(GetFlightDetails.class);
Call<TicketData> mresponse = api
.getFlightList(API_KEY, country, currency, locale, from, to,
departDate.substring(0,10), returnDate.substring(0,10),
locationSchema, cabinClass, adult, children, infants, false);
mresponse.enqueue(new Callback<TicketData>()
{
#Override
public void onResponse(Call<TicketData> call, Response <TicketData> response) {
if (!response.isSuccessful()){
Log.d("UnSuccess", response.raw().toString());
return;
}
else {
progress.cancel(); //cancel progress dialog
Log.d("Success", response.raw().toString());
TicketData ticketData = response.body();
RecyclerAdapter adapter = new RecyclerAdapter(getApplicationContext(), ticketData);
mRecyclerView.setAdapter(adapter);
}
}
#Override
public void onFailure(Call<TicketData> call, Throwable t){
progress.setMessage("Retrofit Error Occured");
}
});
and in my log file I see the following error:
com.example.ex D/OkHttp: --> POST http://partners.api.skyscanner.net/apiservices/pricing/v1.0/?apiKey=xxxxxxxx&country=US¤cy=USD&locale=en-us&originPlace=SFO&destinationPlace=LAX&outboundPartialDate=2016-10-24&inboundPartialDate=2016-10-31&locationschema=iata&cabinclass=Economy&adults=1&children=0&infants=0&groupPricing=false http/1.1 (0-byte body)
com.example.ex D/OkHttp: <-- 415 Unsupported Media Type http://partners.api.skyscanner.net/apiservices/pricing/v1.0/?apiKey=xxxxxxxx&country=US¤cy=USD&locale=en-us&originPlace=SFO&destinationPlace=LAX&outboundPartialDate=2016-10-24&inboundPartialDate=2016-10-31&locationschema=iata&cabinclass=Economy&adults=1&children=0&infants=0&groupPricing=false (403ms, 0-byte body)
com.example.ex D/UnSuccess: Response{protocol=http/1.1, code=415, message=Unsupported Media Type, url=http://partners.api.skyscanner.net/apiservices/pricing/v1.0/?apiKey=xxxxxxxx&country=US¤cy=USD&locale=en-us&originPlace=SFO&destinationPlace=LAX&outboundPartialDate=2016-10-24&inboundPartialDate=2016-10-31&locationschema=iata&cabinclass=Economy&adults=1&children=0&infants=0&groupPricing=false}
I'm not sure why it occurs, because I've tried to add headers in my interface.
Skyscanner docs reference 1 and reference 2
Thanks!
Please refer same type of example : Check your parameter type which filed is query string and which field is #Field and etc.,
public static final String TRAVEL_API = "http://business.skyscanner.net/";
public interface TravelApiInterface {
#FormUrlEncoded
#Headers("Content-Type:application/x-www-form-urlencoded; charset=UTF-8")
#POST("/apiservices/pricing/v1.0/")
void getTravelApi(
#Field("country") String country,
#Field("currency") String currency,
#Field("locale") String locale,
#Field("locationSchema") String locationSchema,
#Field("apikey") String apikey,
#Field("grouppricing") String grouppricing,
#Field("originplace") String originplace,
#Field("destinationplace") String destinationplace,
#Field("outbounddate") String outbounddate,
#Field("inbounddate") String inbounddate,
#Field("adults") int adults,
#Field("children") int children,
#Field("infants") int infants,
#Field("cabinclass") String cabinclass, Callback<Object> response);
}
TravelApiInterface currencyRequestInterfaceService;
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(Url.TRAVEL_API)
.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addQueryParam(getString(R.string.api_key_title), getString(R.string.api_key_value));
}
})
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
currencyRequestInterfaceService = adapter.create(TravelApiInterface.class);
====================
sample request
requestConversion("UK", "GBP", "en-GB", "iata", "xxxxxxxx","on", "EDI", "LHR",
"2016-10-04", "2016-10-11", 1, 0, 0, "Economy", new Callback<Object>() {
#Override
public void success(Object o, Response response) {
}
#Override
public void failure(RetrofitError error) {
}
});
In strings.xml
<string name="api_key_title">apikey</string>
<string name="api_key_value">xxxxxxx</string>
We need to give Content-Type for this problem and need to pass as model class
#Headers("Content-Type:application/json")
#POST("saveAddressByFE")
Call<ChangeAddressModel> updateAddress(#Body AddressModel addressModel );
Retrofit response
private void getUpdateAddress(AddressModel addressModel) {
UploadService service = APIClient.getClient(CommonSettings.MY_RECORDING_SERVER_URL).create(UploadService.class);
Call<ChangeAddressModel> call = service.updateAddress(addressModel);
call.enqueue(new Callback<ChangeAddressModel>() {
#Override
public void onResponse(Call<ChangeAddressModel> call, Response<ChangeAddressModel> response) {
if (response.body().getMessage().equalsIgnoreCase("success")) {
Toast.makeText(InsuranceAgentDetailsActivity.this, "Submitted Successfully", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ChangeAddressModel> call, Throwable t) {
t.printStackTrace();
Toast.makeText(InsuranceAgentDetailsActivity.this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
});
}
Model class
public class ChangeAddressModel {
#SerializedName("message")
#Expose
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
the data we are going to send model class(AddressModel addressModel)
public class AddressModel {
private String addressType,address,custId;
public AddressModel(String addressType, String address, String custId) {
this.addressType = addressType;
this.address = address;
this.custId = custId;
}
public String getAddressType() {
return addressType;
}
public void setAddressType(String addressType) {
this.addressType = addressType;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCustId() {
return custId;
}
public void setCustId(String custId) {
this.custId = custId;
}
}
Can you anyone help me giving good example on how to use retrofit for posting large data from my local DB to mysql server.
Currently I am using async-http API and strangely there is always memory error coming up. I am looking for better API that wont give memory error while uploading huge text of data.
This is my setup:
List<TextDetails> unTextList = dbvalue.getTextData();
for (TextDetails td : unTextList)
{
String textID = td.getSerialNumber();
String textSMS = td.getText();
String textAddress = td.getFulladdress();
String textDate = td.getFulldate();
String textException = td.getExceptiontext();
textDetailsBackUpDataOnline(textID , textSMS, textAddress, textDate, textException);
}
private void textDetailsBackUpDataOnline(final String textID ,
String textSMS, String textAddress, String textDate, String textException)
{
final String uploadWebsite = url_backup_text_details;
RequestParams requestParams = new RequestParams();
requestParams.put("textSMS", textSMS);
requestParams.put("textAddress", textAddress);
requestParams.put("textDate", textDate);
requestParams.put("textException", textException);
Text_HttpClient.post(uploadWebsite, requestParams, new AsyncHttpResponseHandler()
{
#Override
public void onSuccess(int statusCode, org.apache.http.Header[] headers, byte[] responseBody)
{
Log.e("textID", "= how many times");
}
#Override
public void onFailure(int statusCode, org.apache.http.Header[] headers, byte[] errorResponse, Throwable e)
{
e.printStackTrace(System.out);
}
});
}
Text_HttpClient class has the following:
public class Text_HttpClient
{
private static AsyncHttpClient client = new AsyncHttpClient();
public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler)
{
client.get(url, params, responseHandler);
}
public static void post(String url, RequestParams requestParams, AsyncHttpResponseHandler responseHandler)
{
client.post(url, requestParams, responseHandler);
}
}
1) Write service interface:
public interface ArticleGetListService {
#FormUrlEncoded // Request will have "application/x-www-form-urlencoded" MIME type
#POST("/api/Article/ArticleGetList")
public void getArticleList(#Field("LanguageCode") String languageCode,
#Field("CategoryId") String categoryId,
#Field("Token") String token,
Callback<ArticleViewPojo> response); //POJO: The json retrieved from the server is added to this class.
}
Here my Rest service requires 3 Parameters, change it as your need.
2) Write POJO for converting JSON returned from Rest Api into java class object so you can use data.
Just copy your JSON into this site, choose JSON source type, annotation as Gson. It will generate POJO for your JSON automatically.
3)On your Main Activity
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(baseUrl)
.build();
ArticleGetListService articleGetListService = restAdapter.create(ArticleGetListService.class);
Callback<ArticleViewPojo> callback = new Callback<ArticleViewPojo>() {
#Override
public void success(ArticleViewPojo model, Response response) {
//use model which is data returned to you
}
#Override
public void failure(RetrofitError error) {
//handle error
}
};
//START REST CALL
articleGetListService.getArticleList(languageCode, categoryId, token, callback);
//above parameters are those written in service interface at 1
//Whole Url is baseUrl+ArticleGetListService in above example