Java : Android : Retrofit 2 response code is 200, response.body is null
Java : Android : Retrofit 2 response code is 200, response.body is null
I am trying to build an Android App that implements a Collaborative Filtering Algorithm using Retrofit 2,Realm and The Movie Database API.
When making my Retrofit callback, onResponse returns a successful status code (200), but from logging I get that my response.body().getResults returns null. I'm in this pickle now and I can't get it to work.My ApiService seem to be working fine and I make other retrofit callbacks to get directors,movies by title,movies by release date.Anyways, here is some code snippets that might be helpful.
APIService.java
package com.yannis.thesis.movierecommendationapp.api;
import com.yannis.thesis.movierecommendationapp.models.DirectorResponse;
import com.yannis.thesis.movierecommendationapp.models.GenreResponse;
import com.yannis.thesis.movierecommendationapp.models.Movie;
import com.yannis.thesis.movierecommendationapp.models.MovieResponse;
import com.yannis.thesis.movierecommendationapp.models.PrimaryMovieInfo;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface APIService {
@POST("/list")
Call<Movie> loadMovie();
@GET("movie/top_rated")
Call<MovieResponse> getTopRatedMovies(@Query("api_key") String apiKey);
@GET("movie/popular")
Call<MovieResponse> getPopularMovies(@Query("api_key") String apiKey);
@GET("movie/{id}")
Call<MovieResponse> getMovieDetails(@Path("id") int id, @Query("api_key") String apiKey);
@GET("search/movie")
Call<MovieResponse> getMovieByTitle(@Query("query") String title, @Query("api_key") String apiKey);
}
MovieResponse.java
package com.yannis.thesis.movierecommendationapp.models;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class MovieResponse {
@SerializedName("page")
private Integer page;
@SerializedName("results")
private List<Movie> results;
@SerializedName("total_results")
private Integer totalResults;
@SerializedName("total_pages")
private Integer totalPages;
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public List<Movie> getResults() {
return results;
}
public void setResults(List<Movie> results) {
this.results = results;
}
public Integer getTotalResults() {
return totalResults;
}
public void setTotalResults(Integer totalResults) {
this.totalResults = totalResults;
}
public Integer getTotalPages() {
return totalPages;
}
public void setTotalPages(Integer totalPages) {
this.totalPages = totalPages;
}
}
MovieRecommendationApp.java
package com.yannis.thesis.movierecommendationapp;
import android.app.Application;
import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.luseen.logger.LogType;
import com.luseen.logger.Logger;
import com.weiwangcn.betterspinner.library.BetterSpinner;
import com.yannis.thesis.movierecommendationapp.activities.BaseActivity;
import com.yannis.thesis.movierecommendationapp.activities.MainActivity;
import com.yannis.thesis.movierecommendationapp.api.APIService;
import com.yannis.thesis.movierecommendationapp.models.DirectorResponse;
import com.yannis.thesis.movierecommendationapp.models.DirectorResult;
import com.yannis.thesis.movierecommendationapp.models.Genre;
import com.yannis.thesis.movierecommendationapp.models.GenreResponse;
import com.yannis.thesis.movierecommendationapp.models.MainPagerEnum;
import com.yannis.thesis.movierecommendationapp.models.Movie;
import com.yannis.thesis.movierecommendationapp.models.MovieResponse;
import com.yannis.thesis.movierecommendationapp.models.MovieRecommendedForUser;
import com.yannis.thesis.movierecommendationapp.models.Recommendation;
import com.yannis.thesis.movierecommendationapp.models.User;
import com.yannis.thesis.movierecommendationapp.models.UserRatesMovie;
import com.yannis.thesis.movierecommendationapp.MovieRecommendationApp;
import com.yannis.thesis.movierecommendationapp.R;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmQuery;
import io.realm.RealmResults;
import io.realm.Sort;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MovieRecommendationApp extends Application {
private static MovieRecommendationApp instance;
public BaseActivity lastActivity;
String API_BASE_URL = "http://api.themoviedb.org/3/";
private final static String API_KEY = "******************";
private static Retrofit retrofitinstance;
private String loggedInUserId;
private Realm realm;
final Double SIMILARITY_PILLOW = 0.5;
final Double PREDICTION_PILLOW = 3.0;
private APIService client;
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(
GsonConverterFactory.create()
);
Retrofit retrofit =
builder
.client(
httpClient.build()
)
.build();
retrofit2.Call<MovieResponse> call;
@Override
public void onCreate() {
super.onCreate();
instance = this;
Realm.init(this);
RealmConfiguration config = new RealmConfiguration.Builder()
.name("myrealmDB.realm")
.deleteRealmIfMigrationNeeded()
.build();
Realm.setDefaultConfiguration(config);
new Logger.Builder()
.isLoggable(BuildConfig.DEBUG)
.logType(LogType.WARN)
.tag("Iamerror")
.build();
realm = Realm.getDefaultInstance();
MovieRecommendationAlgorithm();
}
public static MovieRecommendationApp getInstance() {
return instance;
}
public static Retrofit getRetrofitInstance() {
return retrofitinstance;
}
public static String getApiKey() {
return API_KEY;
}
public void MovieRecommendationAlgorithm() {
prediction("activeUserId","637",neighbours);
}
public void prediction(String activeUserId, String notYetRatedMovieId,ArrayList<String> neightbours) {
Double activeAVG = avgRating(activeUserId);
Double A = 0.0;
Double B = 0.0;
for (int i = 0; i < neightbours.size(); i++) {
avgRating(neightbours.get(i));
A = A + similarity(activeUserId, neightbours.get(i)) * (getUser_i_MovieRating(neightbours.get(i), notYetRatedMovieId) - avgRating(neightbours.get(i)));
B = B + similarity(activeUserId, neightbours.get(i));
}
final Double prediction = activeAVG + A / B;
if (prediction < PREDICTION_PILLOW) {
return;
}
int movieId = Integer.parseInt(notYetRatedMovieId);
client = retrofit.create(APIService.class);
call = client.getMovieDetails(movieId, MovieRecommendationApp.getApiKey());
call.enqueue(new retrofit2.Callback<MovieResponse>() {
@Override
public void onResponse(retrofit2.Call<MovieResponse> call, retrofit2.Response<MovieResponse> response) {
int statusCode = response.code();
if (response.isSuccessful() == false) {
Logger.w("unsuccessful w status", String.valueOf(statusCode));
} else {
//problem is in this spot
Logger.w( " reponse body is " + response.body().getResults());
}
// Logger.e("Number of movies received: " + movies.size());
}
@Override
public void onFailure(retrofit2.Call<MovieResponse> call, Throwable t) {
}
});
}
}
I double checked the API call using Postman - calling https://api.themoviedb.org/3/movie/637?api_key=*********&language=en-US
got me the desired JSON Body.
Thank you for you time and help.
https://api.themoviedb.org/3/movie/637?api_key=*********&language=en-US
url
HttpLoggingInterceptor shows this : OkHttp: <-- 200 OK api.themoviedb.org/3/movie/…
– sobek
Jul 2 at 5:00
2 Answers
2
I don't know if this will be helpfull, but here: if (response.isSuccessful() == false)
It's a quite strange compare a boolean method isSuccessful() with false, the method already return a boolean.
if (response.isSuccessful() == false)
Nah, made the change to !response.isSuccessful() , the errror persists
– sobek
Jul 3 at 21:51
After searching at the movie database api forum , I found this [https://www.themoviedb.org/talk/5667650ec3a36836970002bc][1]
in which it is stated that "The only way we currently support is via query parameters." and there is a big possibility for my problem to be related with the fact that I am using a @Path parameter and not a @Query parameter.
So now the million dollar question is how to convert the
@GET("movie/{id}")
Call<MovieResponse> getMovieDetails(@Path("id") int id, @Query("api_key") String apiKey);
to a Call using the @Query annotation.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
log the
urlyou are requesting. wrong url could be a problem.– Ali Zeynali
Jul 2 at 4:37