This is my interface:
public interface ApiInterface {
#GET("solicitation/all")
Call<SolicitationResponse> getAllNews(#Query("X-Authorization") String apiKey);
#POST("solicitation/create ")
Call<Solicitation> createSolicitation(#Body Solicitation solicitation);
}
And this is the MainActivity code to create a new solicitation:
Solicitation solicitation = new Solicitation("xx", "list", "31", "32", "description goes here", "file goes here", "userid goes here", "203120312");
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<Solicitation> call = apiService.createSolicitation(solicitation);
call.enqueue(new Callback<Solicitation>() {
#Override
public void onResponse(Call<Solicitation> call, Response<Solicitation> response) {
Log.d("Response::", "Success!");
}
#Override
public void onFailure(Call<Solicitation> call, Throwable t) {
Log.e("Response::", "Fail!!");
}
});
The problem is, as you've seen above on the query I use an api key. #Query("X-Authorization").
It seems I can't do the same to the #Body.
Is there a way to insert the api key there like in the query?
just add the Query separate by comma
Call<Solicitation> createSolicitation(#Query("X-Authorization") String apiKey, #Body Solicitation solicitation);
or in header
Call<Solicitation> createSolicitation(#Header("X-Authorization") String apiKey, #Body Solicitation solicitation);
or you need an interceptor to insert the header
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.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()
.header("X-Authorization", "YOUR AUTH KEY"); // <-- this is the important line
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
usage
Call<Solicitation> call = apiService.createSolicitation("YOUR API KEY",solicitation);
Related
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 working on a project which will retrieve and send data to server through django api. I am facing problem to POST data through the api. My codes are given below. Executing this code give 401 Error in response in android studio but the api works fine in postman or web browser. TIA for the help.
Class to set retrofit instance:
public class ApiClient {
public static final String BASE_URL = "https://myapilink.com/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
final OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", "auth-value"); // <-- this is the important line
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", "Basic YWRtaW46MTIzNA=="); // <-- this is the important line
Request request = requestBuilder.build();
return chain.proceed(request);
}
})
.build();
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.client(okHttpClient)
.build();
}
return retrofit;
}
Retrofit interface:
public interface ApiInterface {
#Headers("Content-Type: application/json")
#POST("/api/auth/login/")
Call<LoginModel> getLoginResponseWithRetrofit(#Body LoginBody loginBody);
}
LoginBody model:
public class LoginBody {
String email;
String password;
public LoginBody(String email, String password){
this.email=email;
this.password=password;
}
}
Main api calling method:
public void postDataWithRetrofit(String email, String password){
//modelFromIDProvider.add(InternalDataProvider.getInstance().getAgentDataModelList());
int selectedPosition,id;
LoginBody loginBody = new LoginBody(email, password);
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<LoginModel> call;
Map<String, String> formData = new HashMap<>();
formData.put("email", email);
formData.put("password", password);
Log.d(TAG,"formdata "+formData.toString());
//call = apiService.getLoginResponseWithRetrofit(email, password);
call = apiService.getLoginResponseWithRetrofit(loginBody);
call.enqueue(new Callback<LoginModel>() {
#Override
public void onResponse(Call<LoginModel> call, Response<LoginModel> response) {
Log.d(TAG,"isSuccessful "+response.isSuccessful()+" code "+response.code());
Log.d(TAG,"Data from response : "+response.body());
if(!response.isSuccessful()) {
dialog.dismiss();
return;
}
LoginModel responseModel = response.body();
InternalDataProvider.getInstance().setLoginDataModel(responseModel);
Log.d(TAG,"Data from response : "+response.body());
}
#Override
public void onFailure(Call<LoginModel> call, Throwable t) {
if(call.isCanceled()){
Log.d(TAG," call cancelled "+t.toString());
return;
}
Log.d(TAG," inside onFailure "+t.toString());
}
});
}
I have a problem in using retrofit. I have a API https://raakar.ir/addProject and want to send some information. API works fine in postman. I want to make post request. I think, I do every think correctly. But when I run the app, It crash.
I used these libraries:
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
and these are my interface of retrofit :
public interface APIInterface {
#Multipart
#POST("addProject")
Call<AddProjectResponse> post(
#Header("token") String token,
#Field("name") String name,
#Field("amount") String amount,
#Field("description") String description,
#Field("category") String category,
#Field("deadline") String deadline,
#Field("projectFile")Bitmap bitmap
);
}
------------------------------------------------------------------------------------------------------------------------------------
Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl("https://raakar.ir/")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
APIinterface retroInterface = retrofit.create(APIinterface.class);
Call<AddProjectResponse> call = retroInterface.post(token,
"طراحی راکار",
"50000000",
"خالی است",
"برنامه نویسی",
"5",
null);
call.enqueue(new Callback<AddProjectResponse>() {
#Override
public void onResponse(Call<AddProjectResponse> call, Response<AddProjectResponse> response) {
Log.d("Resposne:", response.toString());
}
#Override
public void onFailure(Call<AddProjectResponse> call, Throwable t) {
Log.d("Respone:", "Error");
}
});
PLEASE HELP me!
i thing if you are not post any image and other file like video etc then you can not used #Multipart and also pass in post method paremater make one pojo class for that and only pass your object like below that...sample code
MyEventRequestModel myEventListRequestModel = new MyEventRequestModel(); // define your pojo class object
myEventListRequestModel.setDate(mDate);
Call<MyEventResponseModel> call = apiInterface.getAllEvent(myEventListRequestModel);
and header will be set on retrofit intialized..
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.writeTimeout(60, TimeUnit.SECONDS);
client.connectTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(interceptor);
client.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (context == null) {
request = request
.newBuilder()
.build();
} else {
request = request
.newBuilder()
.addHeader("Authorization", "Bearer " + AppSetting.getStringSharedPref(context, Constants.USER_KEY_TOKEN, "")) // hear define your header.
.build();
}
return chain.proceed(request);
}
});
If You use #Multipart than use #Part not #Field
public interface APIInterface {
#Multipart
#POST("addProject")
Call<AddProjectResponse> post(
#Part ("token") String token,
#Part ("name") String name,
#Part ("amount") String amount,
#Part ("description") String description,
#Part ("category") String category,
#Part ("deadline") String deadline,
#Part MultipartBody.Part img
);
}
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());
});