I am using the retrofit. But I don't understand how to send a request without a body and I can't find anything about this in the internet... Please, write an example of the request without the body (with an url and header only)
Everything is explained in details in the retrofit docs.
In the very first example you have GET call without any body - just to fetch a list of github repos.
public interface GitHubService {
#GET("users/{user}/repos")
Call<List<Repo>> listRepos(#Path("user") String user);
}
Just for understanding:
For GET method use:
public interface GitHubService {
#GET("users/{user}/repos")
Call<List<Repo>> listRepos(#Path("user") String user);
}
For POST method use:
public interface GitHubService {
#POST("users/user/repos")
Call<List<Repo>> listRepos(#Field("user") String user, ......<your_parametres>);
}
If you still have any doubt, please comment.
Related
I use interface for #Get in retrofit API request, instead of creating #Get functions for each call I want to send a parameter to the #Get function, How can I do that? Like below example
interface SomeApiService(catId: String) {
#GET(EN_PRODUCTLIST+catId)
fun getProductByCatId():
Deferred<SomeProduct>
}
object SomeApi {
val retrofitService : SomeApiService by lazy { retrofit.create(SomeApiService::class.java) }
}
than when I call SomeApi(catId).getProductByCatId(), it will return that specific product by catId.
how to do that?
you would have to do this
#GET("EN_PRODUCTLIST{catId}")
fun getProductByCatId(#Path(catId) catId:String):Deferred<SomeProduct>
the #Path puts the parameter into the url path of the request.
Please read through the documentation again https://square.github.io/retrofit/
I want to send GET Request to get data for my application but the website only has POST Request to get the JSON raw file. It said I need to put the api as HEADER but usually in retrofit I just pass it as a parameter. What is the problem here?
For post request in Retrofit try code like this:
#FormUrlEncoded
#POST("CUSTOM_URL")
Call<ResponseBody> customMethodName(
#Header("custom_header") String customHeader,
#Field("custmom_field_as_body") int customFieldAsBody
);
I think you have forgotten to add the annotation top of request.
Declare you APIs like this :
#GET("users/{user}/repos")
Call<List<Repo>> listRepos(#Path("user") String user);
or
#GET("users/repos")
Call<List<Repo>> listRepos();
then call this like :
Call< List<Repo> > call = movieApiService.listRepos(API_KEY);
call.enqueue(new Callback< List<Repo> >() {
#Override
public void onResponse(Call< List<Repo> > call, Response< List<Repo> > response) {
List<Repo> data = response.body();
Log.d(TAG, "Number of data received: " + data.size());
}
For more info try this link https://android.jlelse.eu/consuming-rest-api-using-retrofit-library-in-android-ed47aef01ecb
Have made a thorough searching to this particular problem but while implementing answers under each question I encountered, am still getting the same output:
End of input at line 1 column 1 path $
I perfomed my Request on PostMan and I got expected output:
Here is the Screenshot of the Postman Request
Interfaces
#POST(Constant.API_REQUEST)
Observable<ServerResponse> postToWinnersList(#Body ServerRequest serverRequest);
ApiClient
public class ApiClient {
public static Retrofit retrofit;
private static OkHttpClient.Builder okHttpClientBuilder;
private static HttpLoggingInterceptor loggingInterceptor;
public static Retrofit getApiClient(){
if (retrofit == null){
// create instance of Httpclient
okHttpClientBuilder = new OkHttpClient.Builder();
loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
if(BuildConfig.DEBUG){
okHttpClientBuilder.addInterceptor(loggingInterceptor);
}
// instance of retrofit
retrofit = new Retrofit.Builder().baseUrl(Constant.BASE_URL).
addCallAdapterFactory(RxJava2CallAdapterFactory.create()).
addConverterFactory(GsonConverterFactory.create())
.client(okHttpClientBuilder.build())
.build();
}
return retrofit;
}
}
Retrofit/RxJava Request Code:
Observable<ServerResponse> response = apiInterface.postToWinnersList(serverRequest);
response.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribeWith(new DisposableObserver<ServerResponse>() {
#Override
public void onNext(ServerResponse serverResponse) {
AVLoadingIndicatorView1.setVisibility(View.GONE);
txtSubmitWinner.setVisibility(View.VISIBLE);
}
#Override
public void onError(Throwable e) {
AVLoadingIndicatorView1.setVisibility(View.GONE);
txtSubmitWinner.setVisibility(View.VISIBLE);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
#Override
public void onComplete() {
showShortMsg(getString(R.string.submit_success));
}
});
Kindly help, thanks in Advance.
You can get this error when you are expecting an object in the response, but the API doesn't return anything other than result codes (200,...). Options:
- Check that the API really returns a ServerResponse.
- If you don't really need it to return anything, use Observable<Response<Void>> instead of Observable<ServerResponse>
You only get that error when something is wrong with your json response, Check again to make sure both the error response and correct response are well formatted.
Enter wrong credentials using postman and see what the output looks like.
Not sure but I think in Constant.API_REQUEST you are not appending "/".Let me know if it is right.
ex.#POST("index.php") // wrong
#POST("/index.php") //correct way
This error happens when an answer is void.
To correct this error make sure that in the return of the request there will be void.
Eg.
Interface whit kotlin
#POST("endPoint/")
fun relatarProblema(#Body serverRequest: ServerRequest ): Call<Void>
Don't forget to override the return type in the api call.
example whit Kotlin
call.enqueue (object: Callback <Void> {
override fun onResponse(call: Call<Void>, response: Response<Void>) {
}
override fun onFailure(call: Call<Void>, t: Throwable) {
}
})
When I used Coroutines what helped was to basically not return anything from the method:
#GET
#Headers("X-Requested-With:XMLHttpRequest")
suspend fun methodCall(
#Url url: String
)
I was getting the same exception yesterday and figured out that I was using a LogOutResponse data class as the expected response for the API, but then I got to know that the API doesn't return any JSON response corresponding to that data class, in fact, it didn't return anything in the body and only returned result code (200,300,400, etc). So I changed my implementation from:
#POST("logout")
suspend fun logout(): LogOutResponse
to
#POST("logout")
suspend fun logout(): Response<Unit>
Earlier retrofit tried to parse a JSON response at line 1 when there was no JSON there, that's why it threw that exception.
After the changes, the code worked fine as Response is a default retrofit class and Unit type inside it is of void type meaning we don't expect anything in return (no JSON body in response).
I want to make a PUT request using Retrofit to this url:
http://server.com/user/login
Would this be a correct implementation?
public interface UserService {
#PUT("user/login")
Call<User> login(#Body User user);
}
or since I have /login after I send User object as a body login should be #Path {login} ?
On Android, I initially implemented a Retrofit interface like this:
#DELETE(USER_API_BASE_URL + "/{id}")
public void deleteUser(#Path("id") String id, Callback<User> callback);
The server returns 204 NO CONTENT upon a successful deletion. This was causing the callback to trigger failure, with retrofit.RetrofitError: End of input at character 0 of, as it was expecting a User object back with the response.
I then rewrote it like this, using Void instead of User:
#DELETE(USER_API_BASE_URL + "/{id}")
public void deleteUser(#Path("id") String id, Callback<Void> callback); <-- VOID
But I am getting the same error from the callback.
What is the proper way to fix this? Thank you.
Retrofit 2.x no longer has a ResponseCallback as mentioned in the other answer. You want to use a Response<Void> type.
The RxJava declaration:
#PUT Observable<Response<Void>> foo();
The standard declaration:
#PUT Call<Response<Void>> bar();
The solution was pointed out by Jake Wharton in the comments. Use ResponseCallback.
EDIT: this response is no longer valid for Retrofit < 2.
This is the kotlin way for the implementation to deal with HTTP 204 and no content.
#DELETE(USER_API_BASE_URL + "/{id}")
suspend fun deleteuser(#HeaderMap headers: Map<String, String>,
#Path("id") id: String)
: Response<Void>