I have a post api to get some details. I am passing the parameters like this
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService github = retrofit.create(GitHubService.class);
Map<String, String> params;
Params.setAppContext(getApplicationContext());
params = Params.postCommuteParams(AppUtil.getAuthToken(MainActivity.this), android.os.Build.VERSION.RELEASE, "");
Log.d("retrofit param", ""+params.toString());
Call<CommuteResultVO> call1 = github.callCommute(params);
call1.enqueue(new Callback<CommuteResultVO>() {
#Override
public void onResponse(Response<CommuteResultVO> response, Retrofit retrofit) {
int statusCode = response.code();
CommuteResultVO user = response.body();
Log.d("retrofit", ""+statusCode+" );
}
#Override
public void onFailure(Throwable t) {
// Log error here since request failed
Log.d("retrofit", "failed");
}
});
}
The log for retrofit param gives all the params.
Log.d("retrofit param", ""+params.toString());
The params are working as this api call is completely working with volley.
This is how I have written the post call in GitHubService class
#FormUrlEncoded
#POST("/commutes/availability?")
Call<CommuteResultVO> callCommute(#FieldMap Map<String, String> parameters);
But I am getting a statusCode of 404 in the response
Related
I use Retrofit2 to call api, when I do apiTest("http://xxx.xx.xx.xxx:xxxx/", "T001", "Futek10911-01"), the response.code is 999 but it returns correct value in Postman. Where's the problem?
private void apiTest(String url, String machId, String check) throws JSONException {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
MyAPIService myAPIService = retrofit.create(MyAPIService.class);
JSONObject jsonObject = new JSONObject();
jsonObject.put("MACHID", machId);
jsonObject.put("CHECK", check);
Call<GetHostTime> call = myAPIService.getHostTime("sRequest", jsonObject);
call.enqueue(new Callback<GetHostTime>() {
#Override
public void onResponse(Call<GetHostTime> call, Response<GetHostTime> response) {
if(response.isSuccessful()){
Log.d("response ", "isSuccessful");
}else {
Log.d("response code ", response.code() + "");
}
}
#Override
public void onFailure(Call<GetHostTime> call, Throwable t) {
Log.d("Failure", t.getMessage());
}
});
public interface MyAPIService {
#POST("TcLeaseParkAPI/api/ParkingAPI/GetHostTime")
#FormUrlEncoded
Call<GetHostTime> getHostTime(#Field("MACHID") String key, #Field("CHECK") JSONObject jsonObject);
}
Comparing your Postman request and your code. It is clear I feel you are sending the request in wrong manner.
So we modify your Retrofit request as follows
public interface MyAPIService {
#POST("TcLeaseParkAPI/api/ParkingAPI/GetHostTime")
#FormUrlEncoded
Call<GetHostTime> getHostTime(#Field("sRequest") JSONObject jsonObject);
And then your request Call as follows
Call<GetHostTime> call = myAPIService.getHostTime(jsonObject);
Now your JSONObject will go in the key sRequest
I am plugging Retrofit into my android app.
Here is how I build retrofit, notice the interceptor for the logging and headers.
public void buildRetrofit(String token){
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addNetworkInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.header("api-version", "1")
.method(chain.request().method(), chain.request().body())
.build();
return chain.proceed(newRequest);
}
});
httpClient.addInterceptor(logging);
Retrofit.Builder buidler = new Retrofit.Builder()
.baseUrl("XXX_HIDDEN_FORSTACKOVERFLOW")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build());
retroFit = buidler.build();
}
I make the call like so
OrderApi orderApi = mainActivity.retroFit.create(OrderApi.class);
Call<Order> call = orderApi.getOpenOrder();
call.enqueue(new Callback<Order>() {
#Override
public void onResponse(Call<Order> call, Response<Order> response) {
Order a = response.body();
int b = 1;
}
#Override
public void onFailure(Call<Order> call, Throwable t) {
}
});
And here is how the actual request tag
public interface OrderApi {
#POST("/HIDDEN")
Call<Order> getOpenOrder();
}
Lastly, here is the order class
public class Order {
private String orderId;
private OrderStatus orderStatus;
public String getOrderId(){
return orderId;
}
public OrderStatus getOrderStatus() {
return orderStatus;
}
}
I get a response of 400. I have no idea why, and It works in postman etc. Something to note is that the response contains a lot more properties than just the ones in the class. I just want a proof on concept, but that shouldn't break things right?
.................
Managed to fix it. Had to send an empty body request as it was a post but I wasn't posting anything. API is dumb.
See here to send empty request Send empty body in POST request in Retrofit
I am using Postman to hit server GET call with url. and adding headers like below in headers sections in postman so when run in postman it works and send data in body but In android using Retrofit not working with 401 error.
X-APIClient: {"apiClientId":"testing-account-cli","apiToken":"$2y$10$C/quaRQUsrWa30hjQJuckOXbW9kIZ.W3G1TlLMYg6lr/XDUes7SM."}
X-Header-Request: {"deviceId":"ffffffff-daac-6513-4eca-0c41298e00df"}
And It works on Postman. But In Android with Retrofit, it's not working 401 error.
1)
#GET("user-list")
Call<User> getUsers(#HeaderMap Map<String, String> headers);
2)
public static Map<String,String> addCustomHeaders()
{
headers = new HashMap<>();
headers.put("X-APIClient",
"\"apiClientId\":\"testing-account-cli\",\"apiToken\":\"$2y$10$C/quaRQUsrWa30hjQJuckOXbW9kIZ.W3G1TlLMYg6lr/XDUes7SM.");
headers.put("X-Header-Request", "\"deviceId\":\"ffffffff-daac-6513-4eca-0c41298e00df")
;
return headers;
}
3) Calling GET using below fails always
Call<User> call = api.getUsers(RetrofitClient.addCustomHeaders());
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
Log.i(TAG, "GET User Success." + response.body().toString());
}
#Override
public void onFailure(Call<User> call, Throwable t) {
Log.i(TAG, "GET Failed Users." + t.getMessage());
}
});
Please Help whats wrong. As its always throwing 401 with authentication false and authorization false.
Try function below, I separated headers.
public static Map<String,String> addCustomHeaders()
{
HashMap<String, String> headers = new HashMap<>();
headers.put("apiClientId" ,"testing-account-cli");
headers.put("apiToken", "$2y$10$C/quaRQUsrWa30hjQJuckOXbW9kIZ.W3G1TlLMYg6lr/XDUes7SM.");
headers.put("deviceId","ffffffff-daac-6513-4eca-0c41298e00df");
return headers;
}
Use interceptor for header
public class HeaderInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
request = request.newBuilder()
.header("apiClientId", "testing-account-cli")
.header("apiToken","$2y$10$C/quaRQUsrWa30hjQJuckOXbW9kIZ.W3G1TlLMYg6lr/XDUes7SM.")
.header("deviceId","ffffffff-daac-6513-4eca-0c41298e00df")
.build()
Response response = chain.proceed(request);
return response;
}
//add this class into retrofit class like
.addInterceptor(httpLoggingInterceptor)
.addInterceptor(new HeaderInterceptor())
In my application I want to create a Login/Register page.
In the login page I send the Username, Password, Token from client to Server.
I should get Username and Password from USER, and get Token from HEADER of Request.
For connect client to server I use Retorfit 2.2.0 library.
Code from the Interface class :
#POST("User/Authenticate")
Call<LoginResponse> getLoginResponse(#Header("Token") String token, #Body LoginDatum loginDatum);
Code within the Activity :
public void getLogin(String username, String password) {
final LoginDatum loginDatum = new LoginDatum();
loginDatum.setUsername(username);
loginDatum.setPassword(password);
InterfaceApi api = ApiClient.getClient().create(InterfaceApi.class);
Call<LoginResponse> call = api.getLoginResponse(sendToken, loginDatum);
Log.e("tokenTAG", "Token : " + sendToken);
call.enqueue(new Callback<LoginResponse>() {
#Override
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
LoginResponse loginResponse = response.body();
String token = response.headers().get("Token");
if (token != null) {
sendToken = token;
Log.e("tokenTAG", "Token : " + sendToken);
}
if (loginResponse.getStatusCode() == 200) {
Toasty.success(context, context.getResources().getString(R.string.welcome) + " " +
loginResponse.getData().getName(), Toast.LENGTH_LONG, true).show();
} else {
Toasty.error(context, loginResponse.getStatusMessage() + "", Toast.LENGTH_LONG, true).show();
}
loadProgress.get(0).setVisibility(View.GONE);
loginBtn.setVisibility(View.VISIBLE);
btnShadow.setVisibility(View.VISIBLE);
}
#Override
public void onFailure(Call<LoginResponse> call, Throwable t) {
loadProgress.get(0).setVisibility(View.GONE);
loginBtn.setVisibility(View.VISIBLE);
btnShadow.setVisibility(View.VISIBLE);
Toasty.error(context, context.getResources().getString(R.string.failRequest),
Toast.LENGTH_LONG, true).show();
}
});
}
And show me this in LogCat :
tokenTAG: Token : null
tokenTAG: Token : MKGKFPOVRMU4MRK0STNDO20RA2MPEWT7Y1N2WUM5QLIXJX2TEOM9APGUTYJMD8R42WFVESD8GRXCTCINA2LZKU7JV2I7KA2R4N5W
But when I want to send the token with this code : Call<LoginResponse> call = api.getLoginResponse(sendToken, loginDatum); it shows me null.
I have use this line : Call<LoginResponse> call = api.getLoginResponse(sendToken, loginDatum); to generate the request callBack, although this line Token is not NUll.
How can I fix it?
if you use Retrifit get onNetwork request,in order to add Header to your requese,you must be write an Intercepter.
just replace getClient menthod with this one
public static Retrofit getClient(final Context context) {
if (retrofit == null) {
Log.d("AuthTokenTest", "getClient: null");
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
dispatcher = new Dispatcher();
httpClient.dispatcher(dispatcher);
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Log.d("INTERCEPTOR", original.url().toString());
//System.out.print(original.toString());
Request request;
user=User.getLoggedInUserInstance(context);
String authToken="";
if(user!=null)
authToken=user.getAuthToken();
Log.d("AuthTokenTest", "intercept: authtoken:"+authToken);
request = original.newBuilder()
.header("X-AUTH-TOKEN", authToken)
.header("x-requested-with", "XMLHttpRequest")
.method(original.method(), original.body())
.build();
okhttp3.Response response = chain.proceed(request);
Log.d("INTERCEPTOR-", "response_code: "+response.code());
// Log.d("INTERCEPTOR", response.body().string());
return response;
}
});
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
if(BuildConfig.DEBUG){
//print the logs in this case
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
}else{
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
}
httpClient.addInterceptor(loggingInterceptor);
OkHttpClient client = httpClient.build();
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.TRANSIENT)
.setLenient()
.create();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
let me know if this solution works or not
I am using retrofit2 to logout in App but everytime it gives error406
: Not Acceptable : User is not logged in. . i am using retrofit custom
header authentication . Here is my Code :
logout code
public void logout()
{
Log.v("checkTokenbefore",Constants.token);
OkHttpClient httpClient1 = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Log.v("checkLogin",Constants.token+Constants.username+Constants.password) ;
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Accept-Language","application/json").addHeader("content-type", "application/x-www-form-urlencoded")
.addHeader("API_KEY", "a5XSE8XCdsY6hAoCNojYBQ")
.addHeader("X-CSRF-Token",Constants.token)
;
Request request = requestBuilder.method(original.method(),original.body()).build();
return chain.proceed(request);
}
}).build();
Retrofit retrofit1 = new Retrofit.Builder()
.baseUrl(Constants.API_BASE_URL)
.client(httpClient1)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface restAPI1 = retrofit1.create(ApiInterface.class);
Call<Logout> callLogout = restAPI1.userLogout(Constants.token,Constants.username,Constants.password);
callLogout.enqueue(new Callback<Logout>() {
#Override
public void onResponse(Call<Logout> call, retrofit2.Response<Logout> response) {
Log.v("responseLogout",response.code()+"code"+response.errorBody().toString()+response.message()) ;
}
#Override
public void onFailure(Call<Logout> call, Throwable t) {
}
});
}
While Following is the code for login which works fine :
public void loginQuestin(){
//checkValidation ();
/*
ApiInterface apiService =
ApiClient.create(ApiInterface.class) ;*/
ApiInterface restAPI = retrofit.create(ApiInterface.class);
Call<UserAgain> call = restAPI.userLogin(mEmailAddress.getText().toString().trim(),
mPassword.getText().toString().trim());
call.enqueue(new Callback<UserAgain>() {
#Override
public void onResponse(Call<UserAgain> call, Response<UserAgain> response) {
Log.v("check",response.code()+"login"+response.body().getToken()) ;
//response.body().getU
Constants.username = mEmailAddress.getText().toString().trim() ;
Constants.password = mPassword.getText().toString().trim() ;
if (response.code()==200) {
Log.v("checkAgain",response.code()+"login") ;
Constants.token = response.body().getToken() ;
startActivity(new Intent(LoginActivity.this, NavigationDrawerActivity.class));
}
}
#Override
public void onFailure(Call<UserAgain> call, Throwable t) {
Log.v("check","failed");
t.printStackTrace();
}
});
}
//API/Http client for login api call
public class ApiClient {
public static OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder() .addHeader("Accept-Language","application/json")
.addHeader("content-type", "application/x-www-form-urlencoded").addHeader("API_KEY", "a5XSE8XCdsY6hAoCNojYBQ")
;
Request request = requestBuilder.build();
return chain.proceed(request);
}
}).build();
public static Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.API_BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
public static ApiInterface restAPI = retrofit.create(ApiInterface.class);
}
API Interface class
#POST("token")
Call<Token> getToken();
#FormUrlEncoded
#POST("login")
Call<UserAgain> userLogin(#Field("username") String param1, #Field("password") String param2);
#FormUrlEncoded
#POST("logout")
Call<Logout> userLogout(#Field("username") String param1 , #Field("password") String param2);
Login APi works fine give a response code of 200 OK . The major issue is encountered when working with added dynamic customn header on logout api (client xsrf token )
Reference :
https://futurestud.io/tutorials/retrofit-add-custom-request-header
api formats :
User Authentication/Login
Purpose: - User Login Rest URL: - /api/v1/people/login
Method:-POST Headers: Accept-Language: application/json API_KEY:
a5XSE8XCdsY6hAoCNojYBQ Content-Type: application/x-www-form-urlencoded
X-CSRF-Token:
User Logout
Purpose: - User Logout Rest URL: - /api/v1/people/logout
Method:-POST Headers: Accept-Language: application/json API_KEY:
a5XSE8XCdsY6hAoCNojYBQ Content-Type: application/x-www-form-urlencoded
X-CSRF-Token: Parameters in body: username: e.g
service#test.com password: e.g. 123456
Use Interceptors for adding dynamic Header.
httpClient.addInterceptor((Interceptor.Chain chain) -> {
Request originalRequest = chain.request();
set OAuth token
Request.Builder newRequest = originalRequest.newBuilder();
newRequest.header("Authorization", accessToken).method(originalRequest.method(), originalRequest.body());
originalRequest = newRequest.build();
chain.proceed(originalRequest);
repeat request with new token
Response response = chain.proceed(originalRequest); //perform request, here original request will be executed
if (response.code() == 401) {
//if unauthorized
//perform all 401 in sync blocks
}
return chain.proceed(newRequest.build());
});