I´am using retrofit 2.0 to get GSON from Youtube API address:
Link (temporarily static) for Youtube Address
GSON from Youtube address
But when I try to get the videoID from response.body it doesn´t work!
My code:
public class Videos {
#com.google.gson.annotations.SerializedName("videoId") String mVideoId;
#com.google.gson.annotations.SerializedName("title") String mTitle;
public Videos(String videoId, String title ) {
this.mVideoId = videoId;
this.mTitle = title;
}
public String getmVideoId() {
return mVideoId;
}
public void setmVideoId(String mVideoId) {
this.mVideoId = mVideoId;
}
public String getmTitle() {
return mTitle;
}
public void setmTitle(String mTitle) {
this.mTitle = mTitle;
}
}
My interface:
public interface YoutubeApiURL {
#GET("youtube/v3/playlistItems")
Call<Videos> listVideos (
#Query("part") String part,
#Query("maxResults") String maxResults,
#Query("playlistId") String playlistId,
#Query("fields") String fields,
#Query("key") String key
);
}
And here my MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.btn_play);
youTubePlayerView = (YouTubePlayerView)findViewById(R.id.youtube_player_view);
btnListar = (Button)findViewById(R.id.btnListaGitHub);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.googleapis.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
YoutubeApiURL service = retrofit.create(YoutubeApiURL.class);
Call<Videos> videos = service.listVideos(
"snippet",
"50",
"PLbZ3V_t0ZLzylEoYuPtmT5uArAzMewz-m",
"items/snippet/resourceId/videoId",
"AIzaSyAH2YDhp_Yle3NhLeCuBqH654lUre4vDHw");
myURL = videos.request().url().toString();
Log.i("ListVideos", myURL);
videos.enqueue(new Callback<Videos>() {
#Override
public void onResponse(Call<Videos> call, Response<Videos> response) {
if (response.isSuccessful()) {
Log.i("ListVideos","Works!");
// Here some code to show de videoIds return
} else {
Log.i("ListVideos","Something wrong");
}
}
#Override
public void onFailure(Call<Videos> call, Throwable t) {
Log.i("ListVideos: ", t.getLocalizedMessage());
}
});
When I ran my code it shows to me that "Works!", but I tried in several ways to get the videoID with no success!
What I doing wrong?
You are making a model class wrong. try below
Videos
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class Videos {
#SerializedName("items")
#Expose
private List<Item> items = null;
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public Videos withItems(List<Item> items) {
this.items = items;
return this;
}
}
Snippet
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Snippet {
#SerializedName("resourceId")
#Expose
private ResourceId resourceId;
public ResourceId getResourceId() {
return resourceId;
}
public void setResourceId(ResourceId resourceId) {
this.resourceId = resourceId;
}
public Snippet withResourceId(ResourceId resourceId) {
this.resourceId = resourceId;
return this;
}
}
ResourceId
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class ResourceId {
#SerializedName("videoId")
#Expose
private String videoId;
public String getVideoId() {
return videoId;
}
public void setVideoId(String videoId) {
this.videoId = videoId;
}
public ResourceId withVideoId(String videoId) {
this.videoId = videoId;
return this;
}
}
Item
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Item {
#SerializedName("snippet")
#Expose
private Snippet snippet;
public Snippet getSnippet() {
return snippet;
}
public void setSnippet(Snippet snippet) {
this.snippet = snippet;
}
public Item withSnippet(Snippet snippet) {
this.snippet = snippet;
return this;
}
}
Now for get Video id use below code in success method
response.body().getItems().get(0).getSnippet().getResourceId().getVideoId();
Related
I am trying to parse response from server in Android studio.
But I am not getting all values in Arraylist.
I have created ItemData.java and ItemResponse.java
I am Calling Api using getItemData Method:
public void getItemData() {
Call<ItemDataResponse> call = service.getData(token, "200");
call.enqueue(new Callback<ItemDataResponse>() {
#Override
public void onResponse(#NonNull Call<ItemDataResponse> call, #NonNull Response<ItemDataResponse> response) {
Log.d("dataFromServer", response.body.toString());
}
#Override
public void onFailure(#NonNull Call<ItemDataResponse> call, #NonNull Throwable t) {
progressDoalog.dismiss();
Toast.makeText(LiveVehiclesActivity.this, "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
}
});
}
This is Json response:
{
"code":"1",
"items":[
{
"item_id":"200",
"speed":"2"
},
{
"item_id":"201",
"speed":"0"
}
]
}
ItemsResponse.java:
public class ItemDataResponse implements Serializable {
#SerializedName("code")
private String code;
#SerializedName("items")
#Expose
private List<ItemData> items;
public String getResponsecode() {
return responsecode;
}
public void setResponsecode(String responsecode) {
this.responsecode = responsecode;
}
public List<ItemData> getItems() {
return items;
}
public void setItems(List<ItemData> items) {
this.items = items;
}
}
ItemData.java
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class ItemData {
#SerializedName("item_id")
#Expose
private String itemId;
#SerializedName("speed")
#Expose
private String speed;
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getSpeed() {
return speed;
}
public void setSpeed(String speed) {
this.speed = speed;
}
}
After run in debug mode I am getting response like:
code:"1"
items=null
your should modify
class ItemData {
private String item_id;
private String speed;
public String getItem_id() {
return item_id;
}
public void setItem_id(String item_id) {
this.item_id = item_id;
}
public String getSpeed() {
return speed;
}
public void setSpeed(String speed) {
this.speed = speed;
}
}
The ItemData model does not seem to be consistent with the JSON response.
i.e
{
"item_id":"200",
"speed":"2"
}
should map to:
class ItemData implements Serializable {
#SerializedName("item_id")
private String itemId;
#SerializedName("speed")
private String speed;
// getters and setters
}
Use SerializedName attribute for the field contains "_". Here for item_id in your ItemData class getting problem in mapping.
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class ItemData {
#SerializedName("item_id")
#Expose
private String itemId;
#SerializedName("speed")
#Expose
private String speed;
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getSpeed() {
return speed;
}
public void setSpeed(String speed) {
this.speed = speed;
}
}
please change your ItemDataResponse class also
public class ItemDataResponse {
#SerializedName("code")
#Expose
private String code;
#SerializedName("items")
#Expose
private List<Item> items = null;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
}
Here's the code:
Request Interface class
import retrofit2.Call;
import retrofit2.http.GET;
public interface RequestInterface {
String BASE_URL = "https://newsapi.org/v2/";
#GET("top-headlines?sources=google-news&apiKey=3709c816cdcb4eb38b7e45c9829a37d7\n")
Call<NewsList> getJSON();
}
Ojbect class
public class News {
private Source source;
private String author;
private String title;
private String description;
private String url;
private String urlToImage;
private String publishedAt;
public class Source{
private String id;
private String name;
public Source(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
public News(Source source, String author, String title, String description, String url, String urlToImage, String publishedAt) {
this.source = source;
this.author = author;
this.title = title;
this.description = description;
this.url = url;
this.urlToImage = urlToImage;
this.publishedAt = publishedAt;
}
public Source getSource() {
return source;
}
public String getAuthor() {
return author;
}
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public String getUrl() {
return url;
}
public String getUrlToImage() {
return urlToImage;
}
public String getPublishedAt() {
return publishedAt;
}
public void setSource(Source source) {
this.source = source;
}
public void setAuthor(String author) {
this.author = author;
}
public void setTitle(String title) {
this.title = title;
}
public void setDescription(String description) {
this.description = description;
}
public void setUrl(String url) {
this.url = url;
}
public void setUrlToImage(String urlToImage) {
this.urlToImage = urlToImage;
}
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
}
Object list class
import java.util.ArrayList;
public class NewsList {
private ArrayList<News> news = new ArrayList<>();
public ArrayList<News> getNews() {
return news;
}
public void setNews(ArrayList<News> news) {
this.news = news;
}
}
Adapter class
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
private ArrayList<News> news;
private Context context;
public MyAdapter(Context context, ArrayList<News> news){
this.news = news;
this.context = context;
}
public News getItem(int i){
return news.get(i);
}
#NonNull
#Override
public MyAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.news_card, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyAdapter.ViewHolder viewHolder, int i) {
// viewHolder.article_source.setText(news.get(i).getSource());
viewHolder.article_author.setText(news.get(i).getAuthor());
viewHolder.article_title.setText(news.get(i).getTitle());
viewHolder.article_description.setText(news.get(i).getDescription());
viewHolder.article_url.setText(news.get(i).getUrl());
viewHolder.article_urlToImage.setText(news.get(i).getUrlToImage());
viewHolder.article_publishedAt.setText(news.get(i).getPublishedAt());
Picasso.with(context).load(news.get(i).getUrlToImage()).resize(120,60).into(viewHolder.article_image);
}
#Override
public int getItemCount() {
return news.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
ImageView article_image;
TextView article_source, article_author, article_title,
article_description, article_url, article_urlToImage,
article_publishedAt;
public ViewHolder (#NonNull View itemView) {
super(itemView);
article_image = (ImageView) itemView.findViewById(R.id.article_image);
article_source = (TextView) itemView.findViewById(R.id.article_source);
article_author = (TextView) itemView.findViewById(R.id.article_author);
article_title = (TextView) itemView.findViewById(R.id.article_title);
article_description = (TextView) itemView.findViewById(R.id.article_description);
article_url = (TextView) itemView.findViewById(R.id.article_url);
article_urlToImage = (TextView) itemView.findViewById(R.id.article_urlToImage);
article_publishedAt = (TextView) itemView.findViewById(R.id.article_publishedAt);
}
}
}
Main activity
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ArrayList<News> newsArrayList;
private MyAdapter myAdapter;
private Context context;
NewsList newsList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initviews();
}
private void initviews(){
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
loadJSON();
}
private void loadJSON(){
newsArrayList = new ArrayList<>();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(RequestInterface.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
RequestInterface requestInterface =retrofit.create(RequestInterface.class);
Call<NewsList> call = requestInterface.getJSON();
call.enqueue(new Callback<NewsList>() {
#Override
public void onResponse(Call<NewsList> call, Response<NewsList> response) {
// newsArrayList = response.body().getNews();
// Log.i(MainActivity.class.getSimpleName().toString(),"#########ArrayList: "+newsArrayList);
newsArrayList = new ArrayList<>((newsList.getNews()));
myAdapter = new MyAdapter(context, newsArrayList);
recyclerView.setAdapter(myAdapter);
}
#Override
public void onFailure(Call<NewsList> call, Throwable t) {
Log.d("Error", t.getMessage());
}
});
}
}
What am I doing wrong? I keep getting a null pointer exception in the line:
newsArrayList = new ArrayList<>((newsList.getNews()))
Error message:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.ArrayList com.example.dell.myapi.NewsList.getNews()' on a null object reference
at com.example.dell.myapi.MainActivity$1.onResponse(MainActivity.java:57)
You haven't initialized newsList and trying to fetch the data.
Try to assign the result to newsList and then try.
#Override
public void onResponse(Call<NewsList> call, Response<NewsList> response) {
Log.i(MainActivity.class.getSimpleName().toString(),"Response : "+response.body().toString());
newsList = response.body().getNews();// assign the value from response
newsArrayList = new ArrayList<>((newsList.getNews()));
myAdapter = new MyAdapter(context, newsArrayList);
recyclerView.setAdapter(myAdapter);
}
Try this you have pass wrong url at end (\n) remove and try as below
#GET("top-headlines?sources=google-news&apiKey=3709c816cdcb4eb38b7e45c9829a37d7")
change hear also
call.enqueue(new Callback<NewsList>() {
#Override
public void onResponse(Call<NewsList> call, Response<NewsList> response) {
newsArrayList = new ArrayList<>();
newsArrayList.add(response.body().getNews());
myAdapter = new MyAdapter(context, newsArrayList);
recyclerView.setAdapter(myAdapter);
}
#Override
public void onFailure(Call<NewsList> call, Throwable t) {
Log.d("Error", t.getMessage());
}
});
}
First your url isn't correct. Remove \n at the end of url.
Second your models isn't correct. For example NewsList.java doesn't have fields like articles. Use this link to create your models. Your NewsList.java must be like this
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class NewsList {
#SerializedName("status")
#Expose
private String status;
#SerializedName("totalResults")
#Expose
private Integer totalResults;
#SerializedName("articles")
#Expose
private List<News> articles = null;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Integer getTotalResults() {
return totalResults;
}
public void setTotalResults(Integer totalResults) {
this.totalResults = totalResults;
}
public List<News> getArticles() {
return articles;
}
public void setArticles(List<News> articles) {
this.articles = articles;
}
}
I am trying to retrieve Reddit information from a particular subreddit using Retrofit 2. I have followed many tutorials and videos and my code seems to be correct from my perspective but I only manage to have null objects in my model class. I have the permission for internet in the Manifest.
This is a link the JSON I am working with HERE
MainActivity
public class MainActivity extends AppCompatActivity
{
TextView mTextView;
Data mData;
private static final String TAG = "Battlestations";
#Override
protected void onCreate(Bundle savedInstanceState)
{
mTextView = (TextView) findViewById(R.id.test_view);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Call<Data> serviceCall = Service.getDesktopService().desks();
serviceCall.enqueue(new Callback<Data>()
{
#Override
public void onResponse(Call<Data> call, Response<Data> response)
{
Log.d("Reponce","return");
Log.i(TAG, "Response is " + mData.getChildren());
}
#Override
public void onFailure(Call<Data> call, Throwable t)
{
}
});
}
}
Api/Service Class
public class Service
{
private static final String BASE_URL = "https://www.reddit.com/r/";
private static DeskInterface mRetrofit;
public static DeskInterface getDesktopService()
{
if(mRetrofit == null)
{
Retrofit build = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
mRetrofit = build.create(DeskInterface.class);
}
return mRetrofit;
}
public interface DeskInterface
{
#GET("battlestations/hot/.json")
Call<Data> desks();
}
}
Data
public class Data
{
private List<Child> children = null;
public List<Child> getChildren()
{
return children;
}
public void setChildren(List<Child> children)
{
this.children = children;
}
}
Child
public class Child
{
private Data_ data;
public Data_ getData()
{
return data;
}
public void setData(Data_ data)
{
this.data = data;
}
}
Data_
public class Data_
{
private String subreddit;
private Integer score;
private String author;
private String subredditNamePrefixed;
private String url;
private String title;
public String getSubreddit()
{
return subreddit;
}
public void setSubreddit(String subreddit)
{
this.subreddit = subreddit;
}
public Integer getScore()
{
return score;
}
public void setScore(Integer score)
{
this.score = score;
}
public String getAuthor()
{
return author;
}
public void setAuthor(String author)
{
this.author = author;
}
public String getSubredditNamePrefixed()
{
return subredditNamePrefixed;
}
public void setSubredditNamePrefixed(String subredditNamePrefixed)
{
this.subredditNamePrefixed = subredditNamePrefixed;
}
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
}
You need to add mData = response.body() in onResponse() (also check response.isSuccessful() first)
The problem is that your Data does not correspond with Reddit JSON. Your Data class
public class Data {
private List<Child> children = null;
}
does not match with the given json, which is:
{
"kind":"listing",
"data":{
"modhash":"...",
"children":[...],
"after":"...",
"before":"..."
}
}
Retrofit automagically convert from json to java but only if the mapping is correct.
A correct Java class would be:
public class Subreddit {
String kind;
Data data;
}
public class Data{
String modhash;
List<Child> children;
String after;
String before;
}
and then modify desks method interface to
Call<Subreddit> desks();
You would have to go recursively for the entire depth of the JSON to get the right mapping.
But before you get to work, just replace your Retrofit interface:
public interface DeskInterface{
#GET("battlestations/hot/.json")
Call<Data> desks();
}
with:
public interface DeskInterface{
#GET("battlestations/hot/.json")
Call<JsonObject> desks();
}
and it should return something. If is still null, then further investigation is needed. If it returns a valid response(some json text) then copy/paste that subreddit to this website where it converts all the json to a valid Java class
I want to build a movie app that consumes a REST api using retrofit and displays images using Picasso and bring in Retrofit and show real movie posters as well as detail information for each movie.
i'm using The Movie Database Api to get some real data into our app. Checkout their documentation and get familiar with their API, specially the movies/popular endpoint
But when running the application white screen showing pictures does not show movies and I do not know where is the problem
this MainActivity :
package com.walkatheri.movies;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
import retrofit.Callback;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.Response;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
RecyclerView mRecyclerView;
final MoviesAdapter mAdapter;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
mAdapter = new MoviesAdapter(this);
mRecyclerView.setAdapter(mAdapter);
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://api.themoviedb.org/3")
.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addEncodedQueryParam("api_key", "MY _KEY");
}
})
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
MoviesApiService service = restAdapter.create(MoviesApiService.class);
service.getPopularMovies(new Callback<Movies.MovieResult>() {
#Override
public void success(Movies.MovieResult movieResult, Response response) {
mAdapter.setMovieList(movieResult.getResults());
}
#Override
public void failure(RetrofitError error) {
error.printStackTrace();
}
});
}
public static class MovieViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public MovieViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.imageView);
}
}
public static class MoviesAdapter extends RecyclerView.Adapter<MovieViewHolder> {
List<Movies>MovieList ;
private LayoutInflater mInflater;
private Context mContext;
public MoviesAdapter(Context context)
{
this.mContext = context;
this.mInflater = LayoutInflater.from(context);
this.MovieList = new ArrayList<>();
}
public void setMovieList(List<Movies> movieList)
{
this.MovieList=movieList ;
// The adapter needs to know that the data has changed. If we don't call this, app will crash.
notifyDataSetChanged();
}
#Override
public MovieViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.row_movie, parent, false);
MovieViewHolder viewHolder = new MovieViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(MovieViewHolder holder, int position) {
Movies movies = MovieList.get(position);
Picasso.with(mContext)
.load(movies.getPoster()).placeholder(R.color.colorAccent)
.into(holder.imageView);
}
#Override
public int getItemCount() {
return (MovieList == null) ? 0 : MovieList.size();
}
}
}
Movies class :
package com.walkatheri.movies;
import android.graphics.Movie;
import com.google.gson.annotations.SerializedName;
import java.util.List;
/**
* Created by waad on 08/10/2016.
*/
public class Movies {
private String title;
#SerializedName("poster_path")
private String poster;
#SerializedName("overview")
private String description;
#SerializedName("backdrop_path")
private String backdrop;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPoster() {
return "http://image.tmdb.org/t/p/w500" + poster;
}
// public String getPoster() {
// return "http://t2.gstatic.com/images?q=tbn:ANd9GcQW3LbpT94mtUG1PZIIzJNxmFX399wr_NcvoppJ82k7z99Hx6in";
// }
public void setPoster(String poster) {
this.poster = poster;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getBackdrop() {
return backdrop;
}
public void setBackdrop(String backdrop) {
this.backdrop = backdrop;
}
public static class MovieResult {
private List<Movies> resulte;
public List<Movies> getResults() {
return resulte;
}
}}
MoviesApiService class:
package com.walkatheri.movies;
import retrofit.Callback;
import retrofit.http.GET;
/**
* Created by waad on 18/10/2016.
*/
public interface MoviesApiService {
#GET("/movie/popular")
void getPopularMovies(Callback<Movies.MovieResult>cb);
}
Very difficult to point out mistakes without any hint like stacktraces.
Some pointers
Use retrofit asynchronous call.
You need .addConverterFactory(GsonConverterFactory.create()) to convert json to pojos.
Image will be loaded only if you us the url http://image.tmdb.org/t/p/w185"+"yourposterpath". Check the moviedb link
Update your libs and change your api accordingly (Recommended)
Lastly a clean architecture will help you write tests properly. Your code is unstructured and you need to separate components properly. Suggest you read about MVP or MVVM patterns. Dagger can also help.
A good read about retrofit https://inthecheesefactory.com/blog/retrofit-2.0/en
So the changes
public class TestActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private MoviesAdapter mAdapter;
public static final String MOVIE_DB_API_URL = "http://api.themoviedb.org/3/";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
mAdapter = new MoviesAdapter(this);
mRecyclerView.setAdapter(mAdapter);
final OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor())
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15,TimeUnit.SECONDS)
.build();
Retrofit restAdapter = new Retrofit.Builder()
.baseUrl(MOVIE_DB_API_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
MoviesApiService service = restAdapter.create(MoviesApiService.class);
Call<MoviesList> movieResultCallback = service.getPopularMovies();
// asynchronous call
movieResultCallback.enqueue(new Callback<MoviesList>() {
#Override
public void onResponse(Call<MoviesList> call, Response<MoviesList> response) {
//int code = response.code();
// can check the status code
mAdapter.setMovieList(response.body().getResults());
}
#Override
public void onFailure(Call<MoviesList> call, Throwable t) {
}
});
}
public static class MovieViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public MovieViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.image);
}
}
public static class MoviesAdapter extends RecyclerView.Adapter<MovieViewHolder> {
List<Movies>MovieList ;
private LayoutInflater mInflater;
private Context mContext;
public MoviesAdapter(Context context)
{
this.mContext = context;
this.mInflater = LayoutInflater.from(context);
this.MovieList = new ArrayList<>();
}
public void setMovieList(List<Movies> movieList)
{
this.MovieList=movieList ;
// The adapter needs to know that the data has changed. If we don't call this, app will crash.
notifyDataSetChanged();
}
#Override
public MovieViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.row, parent, false);
MovieViewHolder viewHolder = new MovieViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(MovieViewHolder holder, int position) {
Movies movies = MovieList.get(position);
Picasso.with(mContext)
.load("http://image.tmdb.org/t/p/w185"+movies.getPoster_path()).placeholder(R.color.colorAccent)
.into(holder.imageView);
}
#Override
public int getItemCount() {
return (MovieList == null) ? 0 : MovieList.size();
}
}
public static class LoggingInterceptor implements Interceptor {
#Override public okhttp3.Response intercept(Chain chain) throws IOException {
HttpUrl url = chain.request().url()
.newBuilder()
.addQueryParameter("api_key", "4848b32592990671646565fa3240a7bc")
.build();
Request request = chain.request().newBuilder().url(url).build();;
long t1 = System.nanoTime();
String requestLog = String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers());
//YLog.d(String.format("Sending request %s on %s%n%s",
// request.url(), chain.connection(), request.headers()));
if(request.method().compareToIgnoreCase("post")==0){
requestLog ="\n"+requestLog+"\n"+bodyToString(request);
}
Log.d("TAG","request"+"\n"+requestLog);
okhttp3.Response response = chain.proceed(request);
long t2 = System.nanoTime();
String responseLog = String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers());
String bodyString = response.body().string();
Log.d("TAG","response"+"\n"+responseLog+"\n"+bodyString);
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), bodyString))
.build();
//return response;
}
}
private static String bodyToString(final Request request) {
try {
final Request copy = request.newBuilder().build();
final Buffer buffer = new Buffer();
if (copy != null && copy.body() != null) // make sure its not null to avoif NPE
copy.body().writeTo(buffer);
return buffer.readUtf8();
} catch (final IOException e) {
return "did not work";
}
}
}
Then
public interface MoviesApiService {
#GET("movie/popular")
Call<MoviesList> getPopularMovies();
}
My Model classes
Use http://www.jsonschema2pojo.org/ to convert json to pojo
I copied the below for one the respositories on github.
Lots of similar repositories avaiable on github. https://github.com/ewintory/udacity-popular-movies and many more..
public class Movies implements Parcelable {
private int id,vote_count,favourite,reviewsaved,trailersaved;
private float vote_average,popularity;
private String original_language,original_title,overview,release_date,poster_path,title,generids,backdrop_path;
private boolean video,favored;
public Movies()
{
}
public void setReviewsaved(int reviewsaved) {
this.reviewsaved = reviewsaved;
}
public void setTrailersaved(int trailersaved) {
this.trailersaved = trailersaved;
}
public int getTrailersaved() {
return trailersaved;
}
public int getReviewsaved() {
return reviewsaved;
}
public void setFavored(boolean favored) {
this.favored = favored;
}
public void setId(int id) {
this.id = id;
}
public void setVote_count(int vote_count) {
this.vote_count = vote_count;
}
public void setFavourite(int favourite) {
this.favourite = favourite;
}
public void setVote_average(float vote_average) {
this.vote_average = vote_average;
}
public void setOriginal_language(String original_language) {
this.original_language = original_language;
}
public void setOriginal_title(String original_title) {
this.original_title = original_title;
}
public void setOverview(String overview) {
this.overview = overview;
}
public void setRelease_date(String release_date) {
this.release_date = release_date;
}
public void setPoster_path(String poster_path) {
this.poster_path = poster_path;
}
public void setPopularity(float popularity) {
this.popularity = popularity;
}
public void setTitle(String title) {
this.title = title;
}
public void setGenerids(String generids) {
this.generids = generids;
}
public void setbackdrop_path(String backdrop_path) {
this.backdrop_path = backdrop_path;
}
public void setVideo(boolean video) {
this.video = video;
}
public String getGenerids() {
return generids;
}
public int getId() {
return id;
}
public int getVote_count() {
return vote_count;
}
public float getVote_avarage() {
return vote_average;
}
public String getOriginal_language() {
return original_language;
}
public String getOriginal_title() {
return original_title;
}
public String getOverview() {
return overview;
}
public String getRelease_date() {
return release_date;
}
public String getBackdrop_path() {
return backdrop_path;
}
public int getFavourtite() {
return favourite;
}
public String getPoster_path() {
return poster_path;
}
public float getPopularity() {
return popularity;
}
public String getTitle() {
return title;
}
public boolean isVideo() {
return video;
}
// Parcelling part
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.original_language);
dest.writeString(this.original_title);
dest.writeString(this.overview);
dest.writeString(this.poster_path);
dest.writeString(this.generids);
dest.writeString(this.title);
dest.writeString(this.release_date);
dest.writeString(this.backdrop_path);
dest.writeInt(this.favourite);
dest.writeInt(this.id);
dest.writeInt(this.vote_count);
dest.writeFloat(this.vote_average);
dest.writeFloat(this.popularity);
}
protected Movies(Parcel in) {
this.original_language = in.readString();
this.original_title = in.readString();
this.overview = in.readString();
this.poster_path = in.readString();
this.generids = in.readString();
this.title = in.readString();
this.release_date = in.readString();
this.backdrop_path = in.readString();
this.favourite = in.readInt();
this.id = in.readInt();
this.vote_count = in.readInt();
this.vote_average =in.readFloat();
this.popularity = in.readFloat();
}
public static final Creator<Movies> CREATOR = new Creator<Movies>() {
public Movies createFromParcel(Parcel source) {
return new Movies(source);
}
public Movies[] newArray(int size) {
return new Movies[size];
}
};
#Override
public int describeContents() {
return 0;
}
}
MoviesList
public class MoviesList {
private int total_pages;
public int getTotal_pages() {
return total_pages;
}
private ArrayList<Movies> results;
public ArrayList<Movies> getResults() {
return results;
}
}
Finally updated libs
// Okhttp
compile 'com.squareup.okhttp3:okhttp:3.4.1'
//Retrofit and adapters
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.picasso:picasso:2.5.2'
You can check your logs
It's almost impossible to know for sure what's going on, given your vague input, but my bet would be that you haven't specified internet permission in app's manifest:
<uses-permission android:name="android.permission.INTERNET"/>
(in src/main/AndroidManifest.xml, under manifest tag)
New to using okhttp and Gson. I am practicing by creating a List View that will display information from Rotten Tomatoes API
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;
import com.google.gson.Gson;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
ListView listView;
Response responseObj;
CustomAdapter adapter;
String url = "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?apikey=9htuhtcb4ymusd73d4z6jxcj";
Gson gson;
OkHttpClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.myList);
client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(com.squareup.okhttp.Response response) throws IOException {
String responseStr = response.body().string();
gson = new Gson();
**responseObj = gson.fromJson(responseStr,Response.class);**
adapter = new CustomAdapter(MainActivity.this, responseObj.getMovies());
listView.setAdapter(adapter);
}
});
}
}
This is the Error I get for line 44
FATAL EXCEPTION: OkHttp Dispatcher
com.google.gson.JsonSyntaxException: java.lang.NumberFormatException:
Invalid double: ""
public class Response {
private String link_template;
/**
* id : 771312089
* title : The Hunger Games: Mockingjay - Part 2
* year : 2015
* mpaa_rating : PG-13
* runtime : 136
* critics_consensus :
* release_dates : {"theater":"2015-11-20"}
* ratings : {"critics_rating":"Fresh","critics_score":70,"audience_rating":"Upright","audience_score":71}
* synopsis : The second half of Suzanne Collins' final Hunger Games book is adapted in this Lionsgate production. ~ Jeremy Wheeler, Rovi
* posters : {"thumbnail":"http://resizing.flixster.com/nim-D7-9jGbUZS5wczNes_PmWyI=/53x81/dkpu1ddg7pbsk.cloudfront.net/movie/11/20/29/11202951_ori.jpg","profile":"http://resizing.flixster.com/nim-D7-9jGbUZS5wczNes_PmWyI=/53x81/dkpu1ddg7pbsk.cloudfront.net/movie/11/20/29/11202951_ori.jpg","detailed":"http://resizing.flixster.com/nim-D7-9jGbUZS5wczNes_PmWyI=/53x81/dkpu1ddg7pbsk.cloudfront.net/movie/11/20/29/11202951_ori.jpg","original":"http://resizing.flixster.com/nim-D7-9jGbUZS5wczNes_PmWyI=/53x81/dkpu1ddg7pbsk.cloudfront.net/movie/11/20/29/11202951_ori.jpg"}
* abridged_cast : [{"name":"Jennifer Lawrence","id":"770800260","characters":["Katniss Everdeen"]},{"name":"Julianne Moore","id":"162654248","characters":["President Alma Coin"]},{"name":"Gwendoline Christie","id":"771060732","characters":["Commander Lyme"]},{"name":"Josh Hutcherson","id":"162654356","characters":["Peeta Mellark"]},{"name":"Robert Knepper","id":"162707688","characters":["Antonius"]}]
* links : {"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/771312089.json","alternate":"http://www.rottentomatoes.com/m/the_hunger_games_mockingjay_part_2/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/771312089/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/771312089/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/771312089/similar.json"}
*/
private List<MoviesEntity> movies;
public void setLinks(LinksEntity links) {
this.links = links;
}
public void setLink_template(String link_template) {
this.link_template = link_template;
}
public void setMovies(List<MoviesEntity> movies) {
this.movies = movies;
}
public LinksEntity getLinks() {
return links;
}
public String getLink_template() {
return link_template;
}
public List<MoviesEntity> getMovies() {
return movies;
}
public static class LinksEntity {
private String self;
private String alternate;
public void setSelf(String self) {
this.self = self;
}
public void setAlternate(String alternate) {
this.alternate = alternate;
}
public String getSelf() {
return self;
}
public String getAlternate() {
return alternate;
}
}
public static class MoviesEntity {
private String id;
private String title;
private int year;
private String mpaa_rating;
private int runtime;
private String critics_consensus;
/**
* theater : 2015-11-20
*/
private ReleaseDatesEntity release_dates;
/**
* critics_rating : Fresh
* critics_score : 70
* audience_rating : Upright
* audience_score : 71
*/
private RatingsEntity ratings;
private String synopsis;
/**
* thumbnail : http://resizing.flixster.com/nim-D7-9jGbUZS5wczNes_PmWyI=/53x81/dkpu1ddg7pbsk.cloudfront.net/movie/11/20/29/11202951_ori.jpg
* profile : http://resizing.flixster.com/nim-D7-9jGbUZS5wczNes_PmWyI=/53x81/dkpu1ddg7pbsk.cloudfront.net/movie/11/20/29/11202951_ori.jpg
* detailed : http://resizing.flixster.com/nim-D7-9jGbUZS5wczNes_PmWyI=/53x81/dkpu1ddg7pbsk.cloudfront.net/movie/11/20/29/11202951_ori.jpg
* original : http://resizing.flixster.com/nim-D7-9jGbUZS5wczNes_PmWyI=/53x81/dkpu1ddg7pbsk.cloudfront.net/movie/11/20/29/11202951_ori.jpg
*/
private PostersEntity posters;
/**
* self : http://api.rottentomatoes.com/api/public/v1.0/movies/771312089.json
* alternate : http://www.rottentomatoes.com/m/the_hunger_games_mockingjay_part_2/
* cast : http://api.rottentomatoes.com/api/public/v1.0/movies/771312089/cast.json
* reviews : http://api.rottentomatoes.com/api/public/v1.0/movies/771312089/reviews.json
* similar : http://api.rottentomatoes.com/api/public/v1.0/movies/771312089/similar.json
*/
private LinksEntity links;
/**
* name : Jennifer Lawrence
* id : 770800260
* characters : ["Katniss Everdeen"]
*/
private List<AbridgedCastEntity> abridged_cast;
public void setId(String id) {
this.id = id;
}
public void setTitle(String title) {
this.title = title;
}
public void setYear(int year) {
this.year = year;
}
public void setMpaa_rating(String mpaa_rating) {
this.mpaa_rating = mpaa_rating;
}
public void setRuntime(int runtime) {
this.runtime = runtime;
}
public void setCritics_consensus(String critics_consensus) {
this.critics_consensus = critics_consensus;
}
public void setRelease_dates(ReleaseDatesEntity release_dates) {
this.release_dates = release_dates;
}
public void setRatings(RatingsEntity ratings) {
this.ratings = ratings;
}
public void setSynopsis(String synopsis) {
this.synopsis = synopsis;
}
public void setPosters(PostersEntity posters) {
this.posters = posters;
}
public void setLinks(LinksEntity links) {
this.links = links;
}
public void setAbridged_cast(List<AbridgedCastEntity> abridged_cast) {
this.abridged_cast = abridged_cast;
}
public String getId() {
return id;
}
public String getTitle() {
return title;
}
public int getYear() {
return year;
}
public String getMpaa_rating() {
return mpaa_rating;
}
public int getRuntime() {
return runtime;
}
public String getCritics_consensus() {
return critics_consensus;
}
public ReleaseDatesEntity getRelease_dates() {
return release_dates;
}
public RatingsEntity getRatings() {
return ratings;
}
public String getSynopsis() {
return synopsis;
}
public PostersEntity getPosters() {
return posters;
}
public LinksEntity getLinks() {
return links;
}
public List<AbridgedCastEntity> getAbridged_cast() {
return abridged_cast;
}
public static class ReleaseDatesEntity {
private String theater;
public void setTheater(String theater) {
this.theater = theater;
}
public String getTheater() {
return theater;
}
}
public static class RatingsEntity {
private String critics_rating;
private int critics_score;
private String audience_rating;
private int audience_score;
public void setCritics_rating(String critics_rating) {
this.critics_rating = critics_rating;
}
public void setCritics_score(int critics_score) {
this.critics_score = critics_score;
}
public void setAudience_rating(String audience_rating) {
this.audience_rating = audience_rating;
}
public void setAudience_score(int audience_score) {
this.audience_score = audience_score;
}
public String getCritics_rating() {
return critics_rating;
}
public int getCritics_score() {
return critics_score;
}
public String getAudience_rating() {
return audience_rating;
}
public int getAudience_score() {
return audience_score;
}
}
public static class PostersEntity {
private String thumbnail;
private String profile;
private String detailed;
private String original;
public void setThumbnail(String thumbnail) {
this.thumbnail = thumbnail;
}
public void setProfile(String profile) {
this.profile = profile;
}
public void setDetailed(String detailed) {
this.detailed = detailed;
}
public void setOriginal(String original) {
this.original = original;
}
public String getThumbnail() {
return thumbnail;
}
public String getProfile() {
return profile;
}
public String getDetailed() {
return detailed;
}
public String getOriginal() {
return original;
}
}
public static class LinksEntity {
private String self;
private String alternate;
private String cast;
private String reviews;
private String similar;
public void setSelf(String self) {
this.self = self;
}
public void setAlternate(String alternate) {
this.alternate = alternate;
}
public void setCast(String cast) {
this.cast = cast;
}
public void setReviews(String reviews) {
this.reviews = reviews;
}
public void setSimilar(String similar) {
this.similar = similar;
}
public String getSelf() {
return self;
}
public String getAlternate() {
return alternate;
}
public String getCast() {
return cast;
}
public String getReviews() {
return reviews;
}
public String getSimilar() {
return similar;
}
}
public static class AbridgedCastEntity {
private String name;
private String id;
private List<String> characters;
public void setName(String name) {
this.name = name;
}
public void setId(String id) {
this.id = id;
}
public void setCharacters(List<String> characters) {
this.characters = characters;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
public List<String> getCharacters() {
return characters;
}
}
}
}
package com.example.nano1.gsonexample;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.List;
public class CustomAdapter extends BaseAdapter {
private List<Response.MoviesEntity> mMovieItem;
private Context context;
private LayoutInflater inflater;
public CustomAdapter(Context context, List<Response.MoviesEntity> mMovieItem) {
this.context = context;
this.mMovieItem = mMovieItem;
}
#Override
public int getCount() {
return mMovieItem.size();
}
#Override
public Object getItem(int position) {
return mMovieItem.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.each_list_item, parent, false);
Response.MoviesEntity item = (Response.MoviesEntity) getItem(position);
ImageView thumbnail = (ImageView) rowView.findViewById(R.id.thumnnail);
TextView title = (TextView) rowView.findViewById(R.id.title);
TextView rating = (TextView) rowView.findViewById(R.id.rating);
String imageURL = item.getPosters().getOriginal();
Picasso.with(context).load(imageURL).into(thumbnail);
title.setText(item.getTitle());
rating.setText(item.getRatings().getAudience_rating());
return rowView;
}
}
in the declared classes above you have members of type int now in the response you are getting values for these members as empty string "" which is not allowed, it should be an integer. that makes the exception, you either:
1- change member type to String, and handle empty string as 0 in the setters/getters
or
2- ask the back-end team to send correct data
or
3- use a custom TypedAdapter in the Gson converter to handle integers when they have empty string
P.S: i am aware the sample json does not contain empty strings but on the real call on the service, you might have an empty strings for integer members