Java: Android: Retrofit - using Call but, Response{code = 401,message=unauthorized} - java

trying to use Retrofit to access stuff, with themoviedatabase API, but i'm getting a crash, without any thrown exception or error message... I'm new to Retrofit, but i searched some documentation, and this is what i have(i'm using the Retrofit 2.0):
String movieToSearch = "fight";
String ENDPOINT = "https://api.themoviedb.org/3";
String API_KEY = "&api_key=------------------------------";
Retrofit adapter = new Retrofit.Builder()
.baseUrl(ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.build();
TMDBAPI apiService = adapter.create(TMDBAPI.class);
String query = movieToSearch + API_KEY;
Call<List<Movie>> call = apiService.getMovieList(query);
call.enqueue(new Callback<List<Movie>>() {
#Override
public void onResponse(Response<List<Movie>> response, Retrofit retrofit) {
List<Movie> movieList = (response.body());
}
#Override
public void onFailure(Throwable t) {
}
});
What am i doing worng here? :/
[EDIT] i added a / to the end point, and changed the method in the interface to this:
#GET("search/movie")
Call<List<Movie>> getMovieList( #Query("query") String query);
the problem now is, the response has body = null, in the rawResponse, it has a message saying =
Response{protocol=http/1.1, code=401, message=Unauthorized, url=https://api.themoviedb.org/3/search/movie?query=fight%26api_key%-----
do i have to set up a client?

Ok, I can see your problem, the search should be do like this:
http://api.themoviedb.org/3/search/movie?api_key=###&query=iron sky
So, the problem is how are you forming the URL.

I Figured what i was doing wrong, the result off the request i am making, gives more objects in the json... Just create an object with said fields, and with a List.

Related

why is my retrofit call is returning an unsuccessful response?

so basically am using retrofit to get data from an api called calorieNinja and for some reason i keep getting an unsuccessful response
here is the retrofit code :
retrofit = new Retrofit.Builder().baseUrl("https://api.calorieninjas.com/v1/")
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiCalorieNinjas apiCalorieNinjas = retrofit.create(ApiCalorieNinjas.class);
Call<MealCalories> call = apiCalorieNinjas.getMeal("nutrition?query= 5 eggs");
call.enqueue(new Callback<MealCalories>() {
#Override
public void onResponse(Call<MealCalories> call, Response<MealCalories> response) {
if(!response.isSuccessful()){
Toast.makeText(getContext(),"Not Found",Toast.LENGTH_SHORT).show();
return;
}
mealEaten = response.body();
Meal meal1 = new Meal(mealEaten.getName(),mealEaten.getCalories(),mealEaten.getProtein_g(),mealEaten.getCarbohydrates_total_g());
mealViewModel.insertMeal(meal1);
}
#Override
public void onFailure(Call<MealCalories> call, Throwable t) {
}
});
}
});
btw am using 2 different types of meal objects because one is responsible of getting the data from the api and one is used as an entity for Room databse and they dont have the same parameters so instead of just adding #Ignore i decided to use two different objects while i try fixing this problem.
and here is the interface of it :
public interface ApiCalorieNinjas {
#Headers("X-Api-Key: PiQfBb0CZy2GfOZWjWyj6Tg==EdGjoESjqxQh1q4M")
#GET("{meal}")
public Call<MealCalories> getMeal(#Path("meal") String meal);
the api key isnt real!
if additional code is needed please let me know!
Try to add an interceptor so you can see all calls logs (headers, body, URLs, etc...) and see what it's the error that the API is sending.
Add OkHtpp to your grade dependencies:
implementation "com.squareup.okhttp3:okhttp:5.0.0-alpha.2"
implementation "com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2"
And after that, when you create your Retrofit instance, add the interceptor, should look something like this:
val httpClient = OkHttpClient.Builder()
val interceptor = HttpLoggingInterceptor()
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
httpClient.addInterceptor(interceptor)
httpClient.addInterceptor(Interceptor { chain: Interceptor.Chain ->
val original: Request = chain.request()
val request: Request = original.newBuilder()
.header("Content-Type", "application/json")
.method(original.method, original.body)
.build()
chain.proceed(request)
})
val okHttpClient = httpClient.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://api.calorieninjas.com/v1/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()

Unable to create converter for my class in Android Retrofit

I am trying to develop clent-server application with Retrofit. My application sends to server json with a string "image" and responses a json with a string with field "name".
My API:
public interface API {
#FormUrlEncoded
#POST("/api/classification/imagenet")
Call<GestureJson> getName(#Body ImageJson json);
}
ImageJson:
public class ImageJson {
public String imageString;
}
NameJson:
public class NameJson {
public int gestureNumber;
}
When user pressed on button in Main Activity MyVoid is called (url is already known):
public void MyVoid() {
String requestUrl = url;
Retrofit retrofit = new Retrofit.Builder()
.addCallAdapterFactory(GsonConverterFactory.create())
.baseUrl(requestUrl)
.build();
API api = retrofit.create(API.class);
ImageJson json = new ImageJson();
json.imageString = image_uri.toString();
Call<GestureJson> call = api.getName(json);
call.enqueue(new Callback<GestureJson>() {
#Override
public void onResponse(Call<GestureJson> call, Response<GestureJson> response) {
if (response.isSuccessful()) {
status = RESPONSE_SUCCESS;
} else {
status = RESPONSE_FAIL;
}
}
#Override
public void onFailure(Call<GestureJson> call, Throwable t) {
}
});
I have three problems:
1) I don't know what's the difference between Retrofit and Retrofit2. What is better to use?
2) .addCallAdapterFactory(GsonConverterFactory.create()) underlined how wrong (in Retorfit and Retrofit2).
3) I can compile application if i delete .addCallAdapterFactory(GsonConverterFactory.create()). But I have a problem:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.opencvproject, PID: 17742
java.lang.IllegalArgumentException: Unable to create converter for class com.example.opencvproject.GestureJson
for method API.getGesture
Retrofit2 is better because Retrofit outdated (last release was on 2014 https://github.com/square/retrofit/releases/tag/parent-1.6.0). Number 2 in name is just a library version.
GsonConverterFactory may be underlined because you did't add dependency com.squareup.retrofit2:converter-gson
If you delete addCallAdapterFactory(GsonConverterFactory.create()) then Retrofit would't know how to deserialize json to objects. GsonConverterFactory use Gson libarary (https://github.com/google/gson) under the hood to deserialize server json responses.

Why isn't my post retrofit request working?

I have an app that should upload the following parameters
and here I have my code
#POST("task")
Call<ResponsetTask> API_Task(#Header("Authorization") String key, #Body RequestBody body);
[3
and
private void Analizar() {
File file=new File(path);
RequestBody requestBody =RequestBody.create(MediaType.parse("image/jpg"),file);
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
builder.addFormDataPart("message", Constantes.MESSAGE);
builder.addFormDataPart("filecomment", Constantes.FILECOMMENT);
builder.addFormDataPart("api_token", Constantes.api_token);
builder.addFormDataPart("user_id", Integer.toString(Constantes.id));
builder.addFormDataPart("image","image.jpg",requestBody);
MultipartBody body = builder.build();
Call<ResponsetTask>call=conexion2.API_Task(Constantes.AUTH,body);
call.enqueue(new Callback<ResponsetTask>() {
#Override
public void onResponse(Call<ResponsetTask> call, Response<ResponsetTask> response) {
if(response.isSuccessful()){
Constantes.api_task=response.body().getTaskId();
}
}
#Override
public void onFailure(Call<ResponsetTask> call, Throwable t) {
}
});
}
The problem is that the post does not work and does not tell me why I have a breakpoint in my code the BodyRequest is built but when it comes to the call it simply jumps to the end that is to say the onResponse () and the onFailure () skip the code seems work and the app does not hang or give Exception
I appreciate any help friends
This issue is that you are trying to pass data with multipart, Its an easy fix
Add this library
implementation "com.squareup.retrofit2:converter-scalars:$retrofit_version"
and this convertor factory
.addConverterFactory(ScalarsConverterFactory.create()) in your retrofit builder
.sample code is given below
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();

Send a Post with url parameter with Retrofit 2

I want to send a POST with Retrofit 2. The url has some parameters:
#Headers({
"Accept: application/x-www-form-urlencoded;",
"User-Agent: my-app"
})
#FormUrlEncoded
#POST("server/directory/location.type")
`public Call<POJOStringValue> dataWithUr(#Path("arg1") String arg1, #Path("arg2"), String arg2);
The url looks like this
www.website.com/server/directory/location.type?arg1=value1&arg2=value2
I was requested to use a POST request. The values (value1 and value2) are dynamic at runtime. I started the project with Xamarin using HttpClient and now I'm rewriting it in Java native. In C# all I had to do was to concact the strings and send the resulting string in a single Post.
I tried to use #Path and the error was :
"server/directory/location.type" does not contain "{arg1}". (parameter #1)
Then, I tried to use #Query and the error was:
java.lang.IllegalArgumentException: Form-encoded method must contain at least one #Field.
Finally I tried with #Field the request never gets any response (I sette the connection timeout to 5 seconds)
Please help me, or tell me if I have to don't have any other choice but to use a GET request.
((EDIT))
Here is my code for the setup of the client:
private static void setupClient(){
final OkHttpClient client = new okhttp3.OkHttpClient.Builder()
.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
.retryOnConnectionFailure(false)
.build();
//define retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(iXUtils.getUrl_())
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
this.client_ = retrofit.create(RequestInterface.class);
}
The get() method:
public static RequestInterface get(){
return this.client_;
}
Here is how I call it:
public String callFunctionDB(String arg1, String arg2){
setupClient();
Call<POJOStringValue> call = get().dataWithUrlString(arg1, arg2);
try {
POJOStringValue response = call.execute().body();
String value = response.getValue();
int test = 0;
} catch (IOException e) {
String value = "it failded";
e.printStackTrace();
}
return "test";
}
I put the test=0 to be able to put a breaking point, it never gets there. Plus I called the method "callFunctionDB" in a doInbackground to avoid the android.os.NetworkOnMainThreadException.
Retrofit requires you to have at least one form parameter if you request form encoding. You have answered your own question -- you are using query parameters instead of POST fields, so that annotation is not necessary. Remove the #FormUrlEncoded annotation, and change your parameters to #Query annotations.

retrofit wont return response message (android)

this is my code:
the interface :
public interface LoginAPI {
#GET("LoginCheck/{username}/{password}/{status}")
Call<List<Login>> LoginCheck(#Path("username") String username, #Path("password") String password, #Path("status") String status);
}
the class:
public class Login {
String username;
String password;
String status;
}
the main activity :
private void LoginCheck() {
String baseUrl = "http:192.168.169.3:8889/WebService_Indekost/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
LoginAPI api = retrofit.create(LoginAPI.class);
Call<List<Login>> result = api.LoginCheck("username", "password", "status");
result.enqueue(new Callback<List<Login>>() {
#Override
public void onResponse(Call<List<Login>> call, Response<List<Login>> response) {
Log.d("test",response.message());
}
#Override
public void onFailure(Call<List<Login>> call, Throwable t) {
Log.d("Fail", "Fail");
}
});
}
when i try to run it, it shows fail instead of the message. note that the response should be in json format. what am i doing wrong here?
As you commented your error Its saying Expected BEGIN_ARRAY but was BEGIN_OBJECT means exactly You tried to treat it as an Array which starts with brackets like
[ .. data
]
But you are not getting a JSON Array, you are getting an Object. So Try changing the API call Call<List<Login>> into Call<Login>. That may work.
Because you use List<Login> to parse the response, so the response should be a JSON array, like following:
[
{"username":"...","password":"...", "status":"..."},
{"username":"...","password":"...", "status":"..."},
{"username":"...","password":"...", "status":"..."}
]
if the server return result is like following:
{"username":"...","password":"...", "status":"..."}
then you should use Call<Login> replace Call<List<Login>> to parse the response, or, you let server to change its response format to correspond client, it depends what you really want.

Categories