How I use these query in retrofit network call and display it in category wise result
https://api.themoviedb.org/3/genre/{genre_id}/movies
Perhaps this could help:
interface class
public interface TheApiInterface{
#GET("url/bits/until/{path_variable}/then/more/url")
Call<TheThingResponse> getTheThing(#Path("path_variable") String var);
}
Activity or whatever:
public class ThePlaceYoureCallingItFrom {
//set up the api interface and http client
public TheApiInterface getApi(){
String endpoint = "https://api.root.site/api/";
//set up retrofit object
return new Retrofit.Builder().baseUrl(endpoint)
//add chosen converter factory for pojo serialization
.addConverterFactory(GsonConverterFactory.create())
//add the OKHTTP client
.client(new OkHttpClient.Builder().build())
//now gimme
.build().create(TheApiInterface.class);
}
public void callGetTheThing(){
//create call
Call<TheThingResponse> call = getApi().getTheThing("somePathVar");
//set callback
ThingResponseCallback callback = new ThingResponseCallback(this, THING_RESPONSE_INTENT_FILTER);
//fire
call.enqueue(callback);
}
}
the callback:
public class ThingResponseCallback implements Callback<TheThingResponse>{
#Override
public void onResponse(Call<TheThingResponse> call, Response<TheThingResponse> response) {
if (response.isSuccessful() && response.body() != null) {
Log.i(TAG, "onResponse: success: theResponseFieldIWant1: " + response.theResponseFieldIWant1;);
} else {
Log.i(TAG, "onResponse: something went wrong with the response object " +response.body());
}
}
#Override
public void onFailure(Call<TheThingResponse> call, Throwable t) {
Log.i(TAG, "onFailure: to: " + call.request().url() + " req " + call.request());
}
}
the response pojo:
public class TheThingResponse{
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse1")
public String theResponseFieldIWant1;
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse2")
public String theResponseFieldIWant2;
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse3")
public String theResponseFieldIWant3;
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse4")
public String theResponseFieldIWant4;
}
the JSON you're receiving would look like this:
{
"theJsonKeyOfTheFieldReturnedInServerResponse1": "the value I wanted 1",
"theJsonKeyOfTheFieldReturnedInServerResponse2": "the value I wanted 2",
"theJsonKeyOfTheFieldReturnedInServerResponse3": "the value I wanted 3",
"theJsonKeyOfTheFieldReturnedInServerResponse4": "the value I wanted 4"
}
but you can build more complex POJOs for more complex JSON.
I've found it useful to make my POJOs all share a Serializable parent class, to make them easy to move about in the Callback, but you could also use a ContentProvider in here quite readily and insert some rows into a DB or something like that if you want to have a more permanent storage.
But bear in mind this is all async- if you want synchronous Retrofit calls, you can use call.execute()
At least in the "retrofit" library, it works like this
#GET("/url/{id}")
suspend fun getNews(
#Path("id") searchById:String
):Response<News>
Related
I've tried making a retrofit call to an API endpoint, but it's returning a 400 error, however my curl request is working perfectly fine. I can't seem to spot the error, could someone double check my work to see where I made a mistake?
The curl call that works:
curl --request POST https://connect.squareupsandbox.com/v2/payments \
--header "Content-Type: application/json" \
--header "Authorization: Bearer accesstoken112233" \
--header "Accept: application/json" \
--data '{
"idempotency_key": "ab2a118d-53e2-47c6-88e2-8c48cb09bf9b",
"amount_money": {
"amount": 100,
"currency": "USD"},
"source_id": "cnon:CBASEITjGLBON1y5od2lsdxSPxQ"}'
My Retrofit call:
public interface IMakePayment {
#Headers({
"Accept: application/json",
"Content-Type: application/json",
"Authorization: Bearer accesstoken112233"
})
#POST(".")
Call<Void> listRepos(#Body DataDto dataDto);
}
DataDto class:
public class DataDto {
private String idempotency_key;
private String amount_money;
private String source_id;
public DataDto(String idempotency_key, String amount_money, String source_id) {
this.idempotency_key = idempotency_key;
this.amount_money = amount_money;
this.source_id = source_id;
}
}
And lastly making the retrofit call:
DataDto dataDto = new DataDto("ab2a118d-53e2-47c6-88e2-8c48cb09bf9b", "{\"amount\": 100, \"currency\": \"USD\"}", "cnon:CBASEITjGLBON1y5od2lsdxSPxQ");
RetrofitInterfaces.IMakePayment service = RetrofitClientInstance.getRetrofitInstance().create(RetrofitInterfaces.IMakePayment.class);
Call<Void> call = service.listRepos(dataDto);
call.enqueue(new Callback<Void>() {
#Override
public void onResponse(#NonNull Call<Void> call, #NonNull Response<Void> response) {
Log.d(TAG, "onResponse: " + response.toString());
}
#Override
public void onFailure(#NonNull Call<Void> call, #NonNull Throwable t) {
Log.d(TAG, "onFailure: Error: " + t);
}
});
Retrofit Instance:
public class RetrofitClientInstance {
private static Retrofit retrofit;
private static final String BASE_URL = "https://connect.squareupsandbox.com/v2/payments/";
public static Retrofit getRetrofitInstance() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
Edit 1: Changing to second parameter to JSON Object
JSONObject jsonObject = new JSONObject();
try{
jsonObject.put("amount", 100);
jsonObject.put("currency", "USD");
}catch (Exception e){
Log.d(TAG, "onCreate: " + e);
}
DataDto dataDto = new DataDto("ab2a118d-53e2-47c6-88e2-8c48cb09bf9b", jsonObject, "cnon:CBASEITjGLBON1y5od2lsdxSPxQ");
First of all, let's see what 400 means
The HyperText Transfer Protocol (HTTP) 400 Bad Request response status
code indicates that the server cannot or will not process the request
due to something that is perceived to be a client error (e.g.,
malformed request syntax, invalid request message framing, or
deceptive request routing).
Now we are sure, the problem stands in our request (not server fault), most probably it is because you are trying to convert JSON in request (do not do this explicitly GSON will convert automatically)
Use interceptor to verify your outgoing network requests (Tell the result here)
you use #POST(".") which does not make sense, please understand BASE_URL is your server URL NOT MORE
The problem could be translating this post request
So a possible solution
Change base URL into "https://connect.squareupsandbox.com/"
Replace #POST(".") with #POST("v2/payments/")
PS. #NaveenNiraula mentioned right thing even though it did not help you, please follow his instruction, it is the correct way parsing data using GSON (make sure you include it and configure it correctly) converter
EDIT
I make it work (I eliminated 400 error code that is what you want as long as question title is concerned) partially which means I detect why 400 error was occurred and fixed it but unfortunately, I stuck the UNAUTHORIZED issue. The problem was relating to converting json and data type
data class DataDTO(
val idempotency_key: String,
val source_id: String,
val amount_money: MoneyAmount
)
data class MoneyAmount(
val amount: Int,
val currency: String
)
I gist all code here you can refer
You need two DTO classes as below:
public class Amount_money
{
private String amount;
private String currency;
public String getAmount ()
{
return amount;
}
public void setAmount (String amount)
{
this.amount = amount;
}
public String getCurrency ()
{
return currency;
}
public void setCurrency (String currency)
{
this.currency = currency;
}
#Override
public String toString()
{
return "ClassPojo [amount = "+amount+", currency = "+currency+"]";
}
}
And
public class DataDto
{
private String idempotency_key;
private Amount_money amount_money;
private String source_id;
public String getIdempotency_key ()
{
return idempotency_key;
}
public void setIdempotency_key (String idempotency_key)
{
this.idempotency_key = idempotency_key;
}
public Amount_money getAmount_money ()
{
return amount_money;
}
public void setAmount_money (Amount_money amount_money)
{
this.amount_money = amount_money;
}
public String getSource_id ()
{
return source_id;
}
public void setSource_id (String source_id)
{
this.source_id = source_id;
}
#Override
public String toString()
{
return "ClassPojo [idempotency_key = "+idempotency_key+", amount_money = "+amount_money+", source_id = "+source_id+"]";
}
}
You need to create object for each like under :
Amount_money am = new Amount_money();
am.setAmount("100");
am.setCurrency("USD");
DataDto dto = new DataDto();
dto.setIdempotency_key("your key");
dto.setsource_id("your id");
dto.setAmount_money(am);
RetrofitInterfaces.IMakePayment service = RetrofitClientInstance.getRetrofitInstance().create(RetrofitInterfaces.IMakePayment.class);
Call<Void> call = service.listRepos(dataDto);
// yo get the point follow along
Most likely the passed JSON structure is not serialized in the same format.
"amount_money": {
"amount": 100,
"currency": "USD"},
I would at first use for private String amount_money; a real DTO having the amount and currency fields. This should give progress. I'm not 100% sure how the underscore mapping of attributes looks like, but this is the next step.
Add logging to be able to see the passed data. A quick search reveals this tutorial: https://futurestud.io/tutorials/retrofit-2-log-requests-and-responses. When seeing the transmitted data it should be easy to compare the expected and sent data.
Please check your base url.
In your curl you have https://connect.squareupsandbox.com/v2/payments
But in the code you have
private static final String BASE_URL = "https://connect.squareupsandbox.com/v2/payments/";
There is extra / (slash) in the end. I've seen cases where it was the issue. Could be your problem :)
I got such a very strange problem. I already created weather application which using this API. Problem is that, when i am calling "CONDITION" object,than i am getting a null pointer exception.But when i am calling another object,than everything is fine! Its weird. During 2 weeks this API worked fine,but starting from yesterday, not. Can anyone explain me,why it is like that, and what i have to do. Because application is already finished, and i am making the another one, and i don't want to rewriting this application just because of that problem.
I put my response in another application, to check maybe the problem was in my application,not in the API. Here is the code..
API CLASS:
public interface WeatherAPI {
#GET("/v1/current.json?key=fe1c9cd3fd2d4b189c010010172505")
Call<Weather> getForecastWeather(
#Query("q") String cityName
// #Query("days")Integer days
);
}
CONTROLLER CLASS:
public class Controller {
static final String BASE_WEATHER_URL = "https://api.apixu.com/";
public static WeatherAPI getApi(){
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_WEATHER_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
WeatherAPI weatherAPI = retrofit.create(WeatherAPI.class);
return weatherAPI;
}
}
MAIN ACTIVITY CLASS:
mWeatherAPI = Controller.getApi();
mWeatherAPI.getForecastWeather("Paris").enqueue(new Callback<Weather>() {
#Override
public void onResponse(Call<Weather> call, Response<Weather> response) {
String description = response.body().getCurrent().getCondition().getIcon();
Log.e("TAG", "description: " + description);
}
#Override
public void onFailure(Call<Weather> call, Throwable t) {
Log.e("TAG", "onFailure: " + t.getMessage());
}
});
Yes, you need to add OkHttpClient to your Retrofit:
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
Retrofit retrofit = Retrofit.Builder().baseUrl(yourBaseUrlString)
.addConverterFactory(GsonConverterFactory.create())
.retrofitBuilder.client(okHttpClientBuilder.build()).build();
Check the json Object whether u created or not.
I'm trying to get a json list from a web service.
This is the json string return by server :
[{"categoryName":"Política"},{"categoryName":"Economía"},{"categoryName":"Cultura"},{"categoryName":"Deportes"}
The problem is converting in to the POJO. The special characters (í) it's appear like "Pol�tica".
This is the retrofit call function :
#GET("categories")
public Call<List<CategoryPojo>> getCategorias(#Query("sitename") String site)
this is the callback function:
Call<List<CategoryPojo>> call = restservice.getApiService().getCategorias(medio);
try {
call.enqueue(new Callback<List<CategoryPojo>>() {
#Override
public void onResponse(Call<List<CategoryPojo>> call, Response<List<CategoryPojo>> response) {
List<CategoryPojo> categories = response.body();
if (listener != null)
listener.onDataLoaded(categories);
}
#Override
public void onFailure(Call<List<CategoryPojo>> call, Throwable throwable) {
Log.e("Retrofit Error", throwable.getMessage());
}
});
this is the POJO:
public class CategoryPojo implements Serializable{
public CategoryPojo() { }
#SerializedName("categoryName")
private String name;
public String getName()
{
return this.name;
}
}
The result of the request to the Web services, (output in browser) is :
[{"categoryName":"Política"},{"categoryName":"Economía"},{"categoryName":"Cultura"},{"categoryName":"Deportes"},{"categoryName":"Salud"},{"categoryName":"Ciencia y Tecnología"},{"categoryName":"Medio Ambiente"},{"categoryName":"Medios"},{"categoryName":"Militar e Inteligencia"},{"categoryName":"Sociedad"}]
So, the return json has a good encoding...i think that maybe is about the way retrofit read the response.
I'm using retrofit-2.0.2, gson-2.6.1, converter-gson-2.0.2, okhttp-3.2.0.
Any help? please
You should check Content-type in the response headers. Look for the charset value and try to change that on the backend side to application/josn;charset=UTF-8. That worked for me.
I am trying to convert this simple response that looks like this
{
"field_one": "bearer",
"field_two": "fgh",
"field_three": 0
}
I am using latest version of Retrofit 2.0.0-beta1. I never used Retrofit before. There are many tutorials and example of old version of Retrofit. I tried different techniques that works with older versions but thats not working with latest one. Due to lack of documentation of latest version of Retrofit I could not find solution.
I want to use latest version.
Here is POJO
public class Auth {
#SerializedName("field_one")
#Expose
private String fieldOne;
#SerializedName("field_two")
#Expose
private String fieldTwo;
#SerializedName("field_three")
#Expose
private Integer fieldThree;
// setter and getter etc. etc.
}
Here is Interface that I am using
interface Authorization {
#Headers("Authorization: This is some header")
#GET("api/v1/mytoken")
Call<Auth> getToken();
}
This is the way I am calling service
OkHttpClient client = new OkHttpClient();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://myendpoint.com/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
Authorization serviceAuthorization = retrofit.create(Authorization.class);
serviceAuthorization.getToken().enqueue(new Callback<Auth>() {
#Override
public void onResponse(Response<Auth> response) {
Log.d("Response", ">>> "+ response.toString());
}
#Override
public void onFailure(Throwable t) {
Log.d("fail", ">>> "+ t.getMessage());
}
});
I am unable to get output. It just print this
Response: >>> retrofit.Response#2567e2c3
I want to get data in Auth Object that I will use later.
Please suggest me best solution
Thanks!
I guess that you are not seeing you are expecting to see your object printed out on this line --
Log.d("Response", ">>> "+ response.toString());
That is going to call the toString method on the response. If you want to call it on your deserialized object, call the body() method first --
if(response.isSuccess()) {
Log.d("Response", ">>> "+ response.body().toString());
} else {
Log.d("Response", "Error - " + response.code())
}
I want to observer changes from server in my android app.
So I'm using this interface for open stream with server.
public interface Service {
#GET("/n/{id}/streaming")
void streamThreads(#Path("name_space_id") String Id, #QueryMap Map<String, String> options,#Query("exclude_types") String type, Callback<Object> callback);
}
and this is my method where I can get response in my activity
server.streamThreads(accountInfo.getId(), map, "thread", new Callback<Object>() {
#Override
public void success(Object o, Response response) {
String json = (String) o;
Log.i(TAG,json);
}
#Override
public void failure(RetrofitError error) {
Response r = error.getResponse();
if (r != null)
Log.e(TAG, "error: " + r.getReason());
}
});
So I tested method in web browser and life stream works.
But response comes in my mobile app every 30 minutes. I'm using one activity and call method onCreate().
Thanks
Retrofit provides an #Streaming annotation.
The unread byteStream can then be obtained from the raw OkHttp ResponseBody.