I'm currently trying to make an ApiInterface. I'm trying to manipulate API URL by using query. So far the URL I'm using is
https://api.themoviedb.org/3/search/movie?api_key={apiKey}&language=en-US&query={query}
The url above I'm trying to change the "query" So I created this interface:
#GET("3/search/movie?api_key=${BuildConfig.MOVIE_TOKEN}&language=en-US&")
fun getMovies(
#Query("query") query: String
): Call<SearchMovieResponse>
And it works well, but what if the case of the URL is this:
https://api.themoviedb.org/3/movie/{id}?api_key=7fad718afb38c7fe3fbe9da94e0d54e6
Where I'm trying to manipulate the {id}. Is the interface like this?
#GET("3/movie/{id}?api_key=${BuildConfig.MOVIE_TOKEN}")
fun getMovieById(
#Query("id") id: String
):Call<SearchDetailMovieResponse>
Please help me understand how to utilize the annotations to modify the API urls
To use the #Query properly in the case of the following URL:
https://api.themoviedb.org/3/movie/{id}?api_key=7fad718afb38c7fe3fbe9da94e0d54e6
You would need to write your interface as such
#GET("3/movie/{id}")
fun getMovieById(
#Path("id") id: String,
#Query("api_key") apiKey: String = BuildConfig.MOVIE_TOKEN
):Call<SearchDetailMovieResponse>
For more information refer to the documentation.
You can use #Path annotation for this.
#GET("3/movie/{id}?api_key=${BuildConfig.MOVIE_TOKEN}")
fun getMovieById(
#Path("id") id: String
):Call<SearchDetailMovieResponse>
Additional Info:
If you have parameter in middle of url and want to give dynamic value then use #Path annotation as you have id in middle of url.
e-g https://test-api/3/profile. 3 is param in middle of url in that case we use #Path
If you don't have parameter in middle of url and want to pass parameters at end of url with key value pair then better to use #Query
e-g https://test-api/profile?user_id=3 user_id is key value parameter in that case we use #Query.
Note: I am sharing as far as I understood.
Related
I use Retrofit for most of my calls but in one of the cases, I have the full path provided in arguments. My URL is like this http://www.example.com/android.json. This URL is provided in full so I have to path it at runtime. I implement endpoint as suggested here
https://medium.com/#kevintcoughlin/dynamic-endpoints-with-retrofit-a1f4229f4a8d
but in the #GET I need to be able to put #GET(""). This does not work as I get an error saying I should provide at least one "/".
If I add the slash the URL becomes http://www.example.com/android.json/ and it does not work, the server returns forbidden. I also tried creating a custom GET interface similar to here https://github.com/square/retrofit/issues/458 but with GET and without providing a value method in the interface. Then I get another error saying value is missing.
Basically I need to be able to provide an empty or null value but retrofit does not allow that. How could I solve this problem? For now I am doing the JSON request manually but is there a way I could use retrofit for this case? I need to pass the full URL there is no way I can do endpoint http://www.example.com and #GET("/android.json").
Thanks
You can use #GET(".") to indicate that your url is the same as the base url.
#GET(".")
Observable<Result> getData(#Query("param") String parameter);
I've tried this approach, however didn't work for me.
Workaround for this issue is:
//Retrofit interface
public interface TestResourceClient {
#GET
Observable<Something> getSomething(#Url String anEmptyString);
}
//client call
Retrofit.Builder().baseUrl("absolute URL").build()
.create(TestResourceClient.class).getSomething("");
The downside of this solution is that you have to supply empty string in getSomething("") method call.
I face the same problem with Retrofit 2. Using #GET, #GET("") and #GET(".") not solved my problem.
According to the official document you can the same baseUrl and #GET argument.
Endpoint values may be a full URL.
Values that have a host replace the host of baseUrl and values also with a scheme replace the scheme of baseUrl.
Base URL: http://example.com/
Endpoint: https://github.com/square/retrofit/
Result: https://github.com/square/retrofit/
So in my case:
interface MyAPI {
#GET("http://www.omdbapi.com/")
suspend fun getMovies(
#Query("apikey") apikey: String,
#Query("s") s: String
): Response<MoviesResponse>
companion object {
operator fun invoke(): MyAPI {
return Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://www.omdbapi.com/")
.build()
.create(MyAPI::class.java)
}
}
}
I have this below URL
URL TO CALL
In the interface I have as
#GET("storage/presigned-url?bucketName=files&key=payment-receipt/{fileName}&httpVerb=2&contentType=image/jpeg")
suspend fun fileUploadPathCheque(#Path("fileName") name: String): Response<String>
I want to replace the file name with some value
I am calling the function as
Api.fileUploadPathCheque(UUID.randomUUID().toString().plus(".jpg"))
I get the following exception
ava.lang.IllegalArgumentException: URL query string "bucketName=files&key=payment-receipt/{fileName}&httpVerb=2&contentType=image/jpeg" must not have replace block. For dynamic query parameters use #Query.
What shoudl be correct way of doing this?
The exception is self-explanatory, You need to use a query parameter for key. Something like
#GET("storage/presigned-url?bucketName=files&httpVerb=2&contentType=image/jpeg")
suspend fun fileUploadPathCheque(#Query("key") name: String): Response<String>`
and then call it appending payment-receipt/ to your passing parameter:
Api.fileUploadPathCheque("payment-receipt/" + UUID.randomUUID().toString().plus(".jpg"))
This should work for you.
I am trying to make a request in my android project. The url is this one
"https://api.spoonacular.com/recipes/716429/information?includeNutrition=false"
I am using retrofit 2 but i can't figure out how to make it work.
Here is what i tried to do.
I get the id of a recipe and call this function passing the id.
fun applyQueryById(recipeId: Int): String{
val searchByIdQuery = "${recipeId}/information?includeNutrition=false&apiKey=${API_KEY}"
return searchByIdQuery
}
And the GET request is this one
#GET("/recipes/")
suspend fun getRecipeById(
#Query("id") searchById:String
):Response<PersonalizedRecipeResult>
I thinks that because the id is in the middle, making a raw string like i am doing is not a good idea. if anyone could suggest something different I'll appreciate
You are using #Query("id") which will ad the value as query.
From your example, I can see that you want to use #Path
You can use it like this
#GET("/recipes/{id}")
suspend fun getRecipeById(
#Path("id") searchById:String
):Response<PersonalizedRecipeResult>
by this way the searchById will be replaced with {id} in your example call
Link: "www.example.com/getnewcar/?car[color]={colorOfCar}&car[price]={priceOfCar}"
#GET(...)
fun getNewCar(
#Query("car[color]") color: String,
#Query("car[price]") price: String,
...
): Single<JSONApiObject>
I call this function like: b.getNewCar(carColor, carPrice)
URL query string ".." must not have replace block. For dynamic query parameters use #Query. What am I doing wrong? I looked at docs and they suggest using #Query. Can't find what's off tho.
#Query automatically generates the query part of the URL, so your #GET annotation should not include it.
Instead of #GET("www.example.com/getnewcar/?car[color]={colorOfCar}&car[price]={priceOfCar}") it should just be #GET("www.example.com/getnewcar/").
I use Retrofit for most of my calls but in one of the cases, I have the full path provided in arguments. My URL is like this http://www.example.com/android.json. This URL is provided in full so I have to path it at runtime. I implement endpoint as suggested here
https://medium.com/#kevintcoughlin/dynamic-endpoints-with-retrofit-a1f4229f4a8d
but in the #GET I need to be able to put #GET(""). This does not work as I get an error saying I should provide at least one "/".
If I add the slash the URL becomes http://www.example.com/android.json/ and it does not work, the server returns forbidden. I also tried creating a custom GET interface similar to here https://github.com/square/retrofit/issues/458 but with GET and without providing a value method in the interface. Then I get another error saying value is missing.
Basically I need to be able to provide an empty or null value but retrofit does not allow that. How could I solve this problem? For now I am doing the JSON request manually but is there a way I could use retrofit for this case? I need to pass the full URL there is no way I can do endpoint http://www.example.com and #GET("/android.json").
Thanks
You can use #GET(".") to indicate that your url is the same as the base url.
#GET(".")
Observable<Result> getData(#Query("param") String parameter);
I've tried this approach, however didn't work for me.
Workaround for this issue is:
//Retrofit interface
public interface TestResourceClient {
#GET
Observable<Something> getSomething(#Url String anEmptyString);
}
//client call
Retrofit.Builder().baseUrl("absolute URL").build()
.create(TestResourceClient.class).getSomething("");
The downside of this solution is that you have to supply empty string in getSomething("") method call.
I face the same problem with Retrofit 2. Using #GET, #GET("") and #GET(".") not solved my problem.
According to the official document you can the same baseUrl and #GET argument.
Endpoint values may be a full URL.
Values that have a host replace the host of baseUrl and values also with a scheme replace the scheme of baseUrl.
Base URL: http://example.com/
Endpoint: https://github.com/square/retrofit/
Result: https://github.com/square/retrofit/
So in my case:
interface MyAPI {
#GET("http://www.omdbapi.com/")
suspend fun getMovies(
#Query("apikey") apikey: String,
#Query("s") s: String
): Response<MoviesResponse>
companion object {
operator fun invoke(): MyAPI {
return Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://www.omdbapi.com/")
.build()
.create(MyAPI::class.java)
}
}
}