Cannot get the API request to work with the API key. Have already tested it with a different API that doesn't use an API Key, which has worked. Makes me think that I'm not adding the API Key properly.
Tested it on postman using the authentication tab which works well.
How can I send the key Access-Key and value 9xxxxxxxxxxxxx3 using retrofit2?
code
When you call R.string.api_key, you don't get the String value, you only get its id, which is represented as a number. To get the value you need to have context and call context.getString(R.string.api_key). In our case, it is better to take it out from string.xml and place it in some class.
For example
object Constants {
const val BASE_URL = "http://test.com/"
}
and then inside the retrofit
return Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
but if you want to get the value from string.xml you need to change getInstance() method from example add Context.
You can send Headers like as:
public interface APIService {
//Login
#FormUrlEncoded
#POST("loginAction")
Call<LoginModel> loginMI(
#Field("username") String username,
#Field("pwd") String pwd,
#Header("api_key") String api_key,
#Header("secret_key") String secret_key
);
}
call the above API and pass the required Field and Headers.
Related
A sample request to an API is this
https://api.example.com/api/3.0/song/{song_id}.json?apikey={your_api_key}
So, in my activity
//retrofit
final Retrofit retrofit = new Retrofit.Builder()
.baseUrl(C.BASE_URL_DETAIL) // "https://api.example.com/api/3.0/song/"
.addConverterFactory(GsonConverterFactory.create())
.build();
SongInterface request = retrofit.create(SongInterface.class);
//call
Call<SongObject> call =request.getDetails(C.MY_API_KEY);
My interface for song id = 10973
#GET("10973.json?")
Call<SongObject> getDetails(
#Query("apikey") String key
);
It works just fine and i receive the data as expected. However, I can't figure out how to call another song with another id and reuse the code. Can I somehow add the ID as a Query parameter? (the API doesn't seem to be set up to allow this). How can I dynamically update the String to the interface inside the #GET. My attempts to accomplish this have all ended with errors.
Hey there yes right it is absolutely correct way so send "GET" request and like you asked to get a data with respective id here is how you can achieve it
#GET("{songId}.json?")
Call<SongObject> getDetails(
#Path("songId") String songId,
#Query("apikey") String key
);
After this you can call it simply you did it.
LIKE THIS
Call<SongObject> call = request.getDetails(YOUR_SONG_ID,C.MY_API_KEY);
This day is the first time for me to use dotNet web API for my project.
This is the code of my controller
public IEnumerable<Waybill> Get(string id_wb) {
List<Waybill> lstWaybill = new List<Waybill>();
lstWaybill = objway.GetWaybill(id_wb).ToList();
return lstWaybill;
}
That API can work well if I'm call using this link :
http://localhost:56127/api/waybill/?id_wb=00000093
but I don't know how to call that link from my android app (I'm using retrofit)
#GET("Waybill/{id_wb}/id_wb")
Call<Waybill> getWaybillData(#Path("id_wb") String id_wb);
There are 3 options.
First one is to use Retrofit's #Query annotation.
#GET("Waybill/")
Call<Waybill> getWaybillData(#Query("id_wb") String id_wb);
The second one is to #Path annotation
#GET("Waybill/?id_wb={id_wb}") // notice the difference in your code and my code
Call<Waybill> getWaybillData(#Path("id_wb") String id_wb);
The third option is to use #Url annotation. With this option, you need to prepare fully qualified URL before calling/using getWaybillData() method in your activity or fragment. Keep in mind that #Url method overrides base URL set in Retrofit client.
#GET // notice the difference in your code and my code
Call<Waybill> getWaybillData(#Url String completeUrl);
If you follow 3rd option you need to prepare full URL in your activity like below.
String url = "http://<server_ip_address>:56127/api/waybill/?id_wb=00000093";
YourInterface api = ...
Call<Waybill> call = api.getWaybillData(url);
call.enqueue({/* implementation */});
I see a difference in the sample URL you mentioned and usage in Retrofit API interface.
In sample URL waybill is small and in API interface it is Waybill. Please ensure that you're using the right URL.
I have a web-service method called change. I send UpdateStatusRequest objects to this web-service which defined as below:
public class UpdateStatusRequest {
private String Status;
public UpdateStatusRequest(String status) {
Status = status;
}
public String getStatus() {
return Status;
}
}
When I use below API deceleration:
#POST("StatusUpdate")
Call<Status> change(#Query("Status") String status);
and then calling statusApi.change(request.getStatus()), it works well. It will call http://server-url/StatusUpdate?Status=Ready, when I pass Ready as status.
But using below declaration
#POST("StatusUpdate")
Call<Status> change(#Body UpdateStatusRequest status);
and then calling statusApi.change(request), it will call http://server-url/StatusUpdate and sends Status in request body. This will lead to 404 status code with error prompt Not Found.
I want to know what's wrong with my second call (since I supposed #Body acts like several #Query parameters which bundled together in the same object)?
In Retrofit,
#Body doesn't same as #Query.
#Body – Sends Java objects as request body.
#Query- Query parameter appended to the URL.null values are ignored.
But #Field is almost similar to #Body tag.
#Field – Send data as form-urlencoded. The #Field parameter works only with a POST.
For Example:
#POST("StatusUpdate")
Call<Status> change(#Field("Status") String Status);
But in your case, Your server is expecting the params to be passed in
the URL(#Query).
Hope this explanation help.
#Body doesn't act like several #Query parameters. These are two different ways of sending data in a request.
The differences are pretty much already described in your question. With #Query,it will append the URL with the query params you pass, as in http://server-url/StatusUpdate?Status=Ready. Instead, if you use #Body, the params will be added to the body request, so your URL will have no params, as in http://server-url/StatusUpdate, and your body request will be Status=Ready.
Based on the results you got, your server is expecting the params to be passed in the URL(#Query).
I'm using Twitter end point API to follow another user. The API is:
https://api.twitter.com/1.1/friendships/create.json?follow=&screen_name=&user_id=
with Authorization header passed as:
#Headers("Authorization: OAuth oauth_consumer_key=DC0sePOBbQ8bYdC8Smg,oauth_signature_method=HMAC-SHA1,oauth_timestamp=1502774524,oauth_nonce=175308858,oauth_version=1.0,oauth_token=712057165-iQB4b4Q0hsNmHsAxiW4X5UF5xVB6JmKOPhxnW,oauth_signature=X0GExH5DBVgVv49jkO3LwfX8%3D")
#POST()
#FormUrlEncoded
Call<ResponseBody> followUser(#Url String url, #Field("follow") boolean follow, #Field("screen_name") String screenName, #Field("user_id") String userId);
in Retrofit API call from Android. This works fine. But the Auth header has to be generated dynamically for every logged in user. How to achieve that?
You can use #Header annotation in parameter list. Please check the official documentation.
Replaces the header with the value of its target.
#GET("/")
Call<ResponseBody> foo(#Header("Accept-Language") String lang);
Header parameters may be null which will omit them from the request.
Passing a List or array will result in a header for each non-null
item.
Note: Headers do not overwrite each other. All headers with the same
name will be included in the request.
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)
}
}
}