How to add Authorization header with Retrofit2 + RxJava - android

I want to perform request using Retrofit2 and RxJava
public static Observable<Post> getPostsAround(Location location, int offset, int limit) {
if(api==null) {
new RestService(); //initialize API in constructor
}
return api.getPostsAround(location.getLatitude(),location.getLongitude(),offset,limit)
.flatMapIterable(posts -> posts); //transform Observable<List<Post>> to Observable<Post> which emits posts onNext
}
I tried #Headers("Authorization: code) annotation, but I don't know how to change "code" in runtime.

I have found an answer:
A request Header can be updated dynamically using the #Header annotation. A corresponding parameter must be provided to the #Header. If the value is null, the header will be omitted. Otherwise, toString will be called on the value, and the result used.
#GET("user")
Call<User> getUser(#Header("Authorization") String authorization)

Related

How to perform delete api in retrofit

Here is the url for the code for which delete operation is required
URL-http://something.com/Api/remove_player.php
These are the Parameters for request params - user_id, id
How to use delete API for these params?
This is the Interface class in which there is usage of #Path -
public interface ApiDeleteInterface {
#DELETE("/Api/remove_player.php")
Call<Response> getResponse(#Path("user_id") int user_id
,#Path("id") int id
);
}
#DELETE annotation is used for detlete api. What shoul we use in response inside call?
Is this the correct way to make interface ?Should the code use path or any other annotation?
There is DELETE PLAYER API which has url and params below
URL - http://something.com/Api/remove_player.php
Parameters - user_id, id.
How to make delete API using retrofit?
Use #Query instead of #Path to set url parameters.
public interface ApiDeleteInterface {
#DELETE("/Api/remove_player.php")
Call<Response> getResponse(#Query("user_id") int user_id, #Query("id") int id);
}
The resulting url would look like: /Api/remove_player.php?user_id=1&id=2
#Path is a named replacement for a value in the URL. If you want to use #Path, your URL would need to update to something like:
public interface ApiDeleteInterface {
#DELETE("/Api/user_id/{user_id}/id/{id}/remove_player.php")
Call<Response> getResponse(#Path("user_id") int user_id, #Path("id") int id);
}
check out the docs
https://square.github.io/retrofit/2.x/retrofit/index.html?retrofit2/http/Query.html
https://square.github.io/retrofit/2.x/retrofit/index.html?retrofit2/http/Path.html

Retrofit best practice for PATCHing single fields

What is the most common and appropriate way to update single fields of a JSON resource with a PATCH request in Retrofit?
I see 3 ways of doing it:
Using #Body to send the full object, while leaving fields that are not supposed to be updated as null, so GSON will drop them:
#PATCH("posts/{id}")
Call<Post> patchPost(#Path("id") int id, #Body Post post);
Using #FormUrlEncoded and only pass the fields that are supposed to be updated, for example with a #FieldMap.
#FormUrlEncoded
#PATCH("posts/{id}")
Call<Post> patchPost(#Path("id") int id, #FieldMap Map<String, String> fields);
Defining a custom model class that only contains fields that are supposed to be updated, so we don't have to set anything to null.
#PATCH("posts/{id}")
Call<Post> patchPost(#Path("id") int id, #Body PostUpdate postUpdate);
Am I missing other ways? Which one is the most commonly used?
I generally use JSON with RequestBody(Okhttp). JSON object includes just relevant fields. And then I convert it RequestBody. It's like below:
#PATCH(RestConstants.POST_EMPTY)
Call<EmptyResponseModel> postEmpty(#Body RequestBody body);
MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json.toString()));

Add an array as request parameter with Retrofit 2

I'm looking for way to add an int array (e.g [0,1,3,5]) as parameter in a GET request with retrofit 2. Then, the generated url should be like this : http://server/service?array=[0,1,3,5]
How to do this ?
Just add it as a query param
#GET("http://server/service")
Observable<Void> getSomething(#Query("array") List<Integer> array);
You can also use int[], or Integer... as a last param;
You need to name your query param with an array syntax like so:
#GET("http://server/service")
Observable<Void> getSomething(#Query("array[]") List<Integer> array);
The syntax itself will vary by the backend technology being used, however not including the brackets "[]" will normally be interpreted as a single value.
For example, using array=1&array=2 will generally be interpreted by backends as only array=1 or array=2 instead of array=[1,2].
I have finally founded a solution by using Arrays.toString(int []) method and by removing spaces in this result because Arrays.toString return "[0, 1, 3, 5]". And my request method looks like this
#GET("http://server/service")
Observable<Void> getSomething(#Query("array") String array);
I faced a similar problem and had to do a couple of things to reach the acceptable form (as asked in the question).
Converted an ArrayList to String
arrayList.toString().replace(" ", "")
In RetroFit method, I changed the Query param which accepts the ArrayList above to as follows:
#Query(value = "cities", encoded = true)
This ensures that the brackets and commas are not URL encoded.
Using toString didn't work for me.
Instead, TextUtils.join(",", ids) does the trick.
Don't forget to mark the Query with encoded = true.
Well this did the trick for me
Step 1 :
In StateServce.kt
#GET("states/v1")
fun getStatesByCoordinates(#Query("coordinates", encoded = true) coordinates: String) : Call<ApiResponse<List<State>>>
Step 2
While calling from repository
val mCoordinate : List<Double> = [22.333, 22.22]
mStateService?.getStatesByCoordinates(mCoordinate.toString().replace(" ", ""))!!
Use Iterable to encapsulate the integer list, or use a two-dimensional integer array.
How to define:
public interface ServerService {
#GET("service")
Call<Result> method1(#Query("array") Iterable<List<Integer>> array);
#GET("service")
Call<Result> method2(#Query("array") Integer[][] array);
}
How to use:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://server/")
.addConverterFactory(GsonConverterFactory.create())
.build();
ServerService service = retrofit.create(ServerService.class);
// Use the first method.
List<Integer> data1 = Arrays.asList(0,1,3,5);
Iterable array1 = Arrays.asList(data1);
Call<Result> method1Call = service.method1(array1);
// Use the second method.
Integer[] data2 = new Integer[]{0,1,3,5};
Integer[][] array2 = new Integer[][]{data2};
Call<Result> method2Call = service.method2(array2);
// Execute enqueue() or execute() of method1Call or method2Call.
Please refer to the code ParameterHandler.java of Retrofit2 for the reason why the way can solve the problem.
You can pass the value as below
In Repository
getApiResponse(arrayOf(0,1,3,5).contentToString())` In Kotlin.
#GET("http://server/service")
suspend fun getApiResponse(#Query("array") array: String): Response
It will work.

How to add Endpoints dynamically in Retrofit2.0

How to pass endpoints in annotations(ex:#GET("dynamic value"))dynamically.
We tried passing values as static and it was doing good but when i pass the values dynamically it is showing the below error
Attribute value must be constant.
It seems that you want to do somthing like this:
#GET("users/list?country={country}")
Call<List<Repo>> listRepos(#Path("country") String country);
where you give the country code when you call the function
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Try this :
#Documented
#Target(METHOD)
#Retention(RUNTIME)
public #interface GET {
//new
int Endpoints () default 1; (or use enum)
String value() default "";
}

about Retrofit get and post methods parameters

I read retrofit is good for client server communication.
In this I have some doubts.
#GET("/group/{id}/users")
List<User> groupList(#Path("id") int groupId);
In get method what is group, id, users, and what is groupList(#Path("id") int groupId). What will it do exactly?
When you build a new adapter for your interface with Retrofit you specify some server as endpoint. Let's say your endpoint is http://www.example.com. After that, when you execute groupList method, Retrofit will send a GET request to the http://www.example.com/group/{id}/users, where {id} placeholder will be replaced with a value you provided with groupId parameter during method call. So, this default parameter of GET annotation is just a path that should be appended to the server name and the value for placeholder is provided at the runtime.
/group/{id}/users this your GET request url (BASE_URL + Your GET url) where your id will be replaced with groupId passed in your groupList(#Path("id") int groupId); method.
Now your final request GET URL will be
BASE_URL + /group/{your groupId passed in method}/users
finally response from server will be parsed to List<User> and returned.

Categories

Resources