Currently I am developing a Popular Movies app by udacity and stuck at loading images from the MovieDb api. I have also took reference from this thread Picasso Images are not loading in Gridview Android but no use.
Here is my fragment file:
package com.akshitjain.popularmovies;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* A placeholder fragment containing a simple view.
*/
public class MainActivityFragment extends Fragment {
ImageAdapter mMoviesAdapter;
public MainActivityFragment() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_main, container, false);
GridView gridview = (GridView) rootView.findViewById(R.id.grid_view_movies);
mMoviesAdapter = new ImageAdapter(getActivity());
gridview.setAdapter(mMoviesAdapter);
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(getActivity(), "" + position,
Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_mainfragment,menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == R.id.action_refresh){
String sortOrder = "popularity.desc";
new FetchMoviesTask().execute(sortOrder);
return true;
}
return super.onOptionsItemSelected(item);
}
public class FetchMoviesTask extends AsyncTask<String, Void, String[]> {
private final String LOG_TAG = FetchMoviesTask.class.getSimpleName();
private String[] getMoviesDataFromJson(String moviesJsonStr)
throws JSONException {
final String TMDB_RESULTS = "results";
final String TMDB_POSTER = "poster_path";
JSONObject moviesJson = new JSONObject(moviesJsonStr);
JSONArray moviesArray = moviesJson.getJSONArray(TMDB_RESULTS);
String[] resultStrs = new String[moviesArray.length()];
for(int i=0;i<moviesArray.length();++i) {
JSONObject movieObject = moviesArray.getJSONObject(i);
resultStrs[i] = movieObject.getString(TMDB_POSTER);
}
return resultStrs;
}
#Override
protected String[] doInBackground(String... params) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String moviesJsonStr;
String apiKey = BuildConfig.THE_MOVIE_DB_API_KEY;
try {
// Construct the URL for the TheMovieDb query
// Possible parameters are available at TheMovieDb API page
final String MOVIES_BASE_URL = "http://api.themoviedb.org/3/discover/movie?";
final String SORT_PARAM = "sort_by";
final String API_KEY = "api_key";
Uri builtUri = Uri.parse(MOVIES_BASE_URL).buildUpon()
.appendQueryParameter(SORT_PARAM,params[0])
.appendQueryParameter(API_KEY,apiKey)
.build();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG,"BuiltUri: " + builtUri.toString());
// Create the request to TheMovieDb, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuilder buffer = new StringBuilder();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line).append("\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
moviesJsonStr = buffer.toString();
Log.v(LOG_TAG,"Movies Json String: " + moviesJsonStr);
} catch (IOException e) {
Log.e("MainActivityFragment", "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attempting
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("MainActivityFragment", "Error closing stream", e);
}
}
}
try{
return getMoviesDataFromJson(moviesJsonStr);
}catch (JSONException e){
Log.e(LOG_TAG,e.getMessage(),e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String[] strings) {
if(strings != null){
mMoviesAdapter.clear();
for(String moviesStr:strings){
mMoviesAdapter.add(moviesStr);
}
}
mMoviesAdapter.notifyDataSetChanged();
super.onPostExecute(strings);
}
}
}
Here is my custom adapter file:
package com.akshitjain.popularmovies;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
public class ImageAdapter extends BaseAdapter {
private final String LOG_TAG = ImageAdapter.class.getSimpleName();
private Context mContext;
List<String> list = new ArrayList<>();
public ImageAdapter(Context c) {
this.mContext = c;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.grid_item_movies, parent, false);
}
final String POSTER_BASE_URL = " http://image.tmdb.org/t/p/";
final String POSTER_SIZE = "w185";
ImageView moviePoster = (ImageView) convertView.findViewById(R.id.grid_item_movie_image);
final String POSTER_FINAL_URL = POSTER_BASE_URL + POSTER_SIZE + list.get(position);
Log.v(LOG_TAG,"Poster Urls: " + POSTER_FINAL_URL);
Picasso.with(mContext).load(POSTER_FINAL_URL).into(moviePoster);
return convertView;
}
public void add(String s) {
list.add(s);
}
public void clear() {
list.clear();
}
}
There is no error in the code. App runs successfully. But images are not loading.
final String POSTER_BASE_URL = " http://image.tmdb.org/t/p/";
The space at the beginning of the string was the issue. Picasso will try and load url with space at front.
So String.trim() will remove the space from the beginning as well as the end of a String.
Picasso.with(mContext).load(POSTER_FINAL_URL.trim()).into(moviePoster)
Related
I'm working on udacity popular movies stage 1 project that will allow me to discover movies from themoviedb database.
I've created Movie, MovieAdapter, and MainActivity(with FetchMovieAsyncTask as inner class) classes. But I keep getting below error
java.lang.NullPointerException: Attempt to invoke interface method
'int java.util.List.size()' on a null object reference
These are my codes
Movie class:
public class Movie{
private String mMovieTitle;
private String mPosterPath;
private String mOverview;
private String mReleaseDate;
private double mRating;
public Movie(){
mMovieTitle = null;
mPosterPath = null;
mOverview = null;
mReleaseDate = null;
mRating = -1.0;
}
public Movie(String title){
mMovieTitle = title;
}
public Movie(String title, String posterPath, String overview, String releaseDate, double rating){
mMovieTitle = title;
mPosterPath = posterPath;
mOverview = overview;
mReleaseDate = releaseDate;
mRating = rating;
}
public String getMovieTitle(){
return mMovieTitle;
}
public String getPosterPath(){
return mPosterPath;
}
public String getOverview(){
return mOverview;
}
public String getReleaseData(){
return mReleaseDate;
}
public double getRating(){
return mRating;
}
}
MovieAdapter class:
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
/**
* Created by ibayp on 04/08/2017.
*/
public class MovieAdapter extends ArrayAdapter<Movie> {
Context context;
ArrayList<Movie> movies;
public MovieAdapter(Context context, ArrayList<Movie> movies){
super(context, 0, movies);
this.context = context;
this.movies = movies;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view = convertView;
if(view == null){
view = LayoutInflater.from(getContext()).inflate(R.layout.poster_list, parent, false);
}
ImageView imageView = (ImageView)view.findViewById(R.id.movie_poster);
Picasso.with(getContext())
.load("https://image.tmdb.org/t/p/w500/kqjL17yufvn9OVLyXYpvtyrFfak.jpg")
.into(imageView);
return view;
}
}
and MainActivity class:
package com.android.ibayp.popularmovies;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
GridView gridView;
ArrayList<Movie> movies;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new FetchMovieAsyncTask().execute("popularity.desc");
MovieAdapter adapter = new MovieAdapter(this, movies);
gridView = (GridView)findViewById(R.id.grid_view);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long l) {
Movie movie = (Movie)parent.getItemAtPosition(position);
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
intent.putExtra("title", movie.getMovieTitle());
startActivity(intent);
}
});
}
private class FetchMovieAsyncTask extends AsyncTask<String, Void, ArrayList<Movie>> {
private final String TAG = com.android.ibayp.popularmovies.FetchMovieAsyncTask.class.getSimpleName();
private static final String API_KEY = "api key";
private static final String BASE_URL = "https://api.themoviedb.org/3/discover/movie?";
private String API_PARAM = "api_key";
private String SORT_BY = "sort_by";
public URL buildURL(String[] sortMethod){
Uri builtUri = Uri.parse(BASE_URL).buildUpon()
.appendQueryParameter(API_PARAM, API_KEY)
.appendQueryParameter(SORT_BY, sortMethod[0])
.build();
URL url = null;
try{
url = new URL(builtUri.toString());
}catch (MalformedURLException e){
e.printStackTrace();
}
Log.v(TAG, "BUILT URI: " +url);
return url;
}
private String makeHttpRequst(URL url)throws IOException {
String jsonResponse = "";
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try{
urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
inputStream = urlConnection.getInputStream();
jsonResponse = readStream(inputStream);
}catch (IOException e){
e.printStackTrace();
}finally {
if(urlConnection!=null){
urlConnection.disconnect();
}
if (inputStream!=null){
inputStream.close();
}
}
return jsonResponse;
}
private String readStream(InputStream inputStream) throws IOException{
StringBuilder results = new StringBuilder();
if(inputStream!=null){
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line!=null){
results.append(line);
line = reader.readLine();
}
}
return results.toString();
}
private ArrayList<Movie> getMovieFromJson(String movieJson){
movies = new ArrayList<Movie>();
try{
JSONObject baseResponse = new JSONObject(movieJson);
JSONArray resultsArray = baseResponse.getJSONArray("results");
Log.v(TAG, "Array Results: "+resultsArray.length());
if (resultsArray.length() > 0){
for (int i = 0; i<resultsArray.length(); i++ ){
JSONObject movieInformation = resultsArray.getJSONObject(i);
movies.add(new Movie(movieInformation.getString("title"),
movieInformation.getString("poster_path"),
movieInformation.getString("overview"),
movieInformation.getString("release_date"),
movieInformation.getDouble("vote_average")));
}
}
}catch (JSONException e){
Log.v(TAG, "Problem parsing Json" + e);
}
return movies;
}
#Override
protected ArrayList<Movie> doInBackground(String... strings) {
URL url = buildURL(strings);
String jsonResponse = "";
try{
jsonResponse = makeHttpRequst(url);
}catch (IOException e){
Log.v(TAG, "IO Exception error "+e);
}
movies = getMovieFromJson(jsonResponse);
return movies;
}
#Override
protected void onPostExecute(ArrayList<Movie> movies) {
if (movies==null){
return;
}
super.onPostExecute(movies);
}
}
}
I used logging and managed to get the correct json results, but I can't display it on the ui thread.
How can I solve this? Thanks
*note that I used dummy image for the poster
When you instantiate your adapter movies are null. Because asynctask is running in parallel thread. Instantiate your adapter in your asynctask's onPostExecute method. This way you will be sure asynctask is completed.
#Override
protected void onPostExecute(ArrayList<Movie> movies) {
if (movies==null){
return;
}
super.onPostExecute(movies);
MovieAdapter adapter = new MovieAdapter(MainActivity.this, movies);
gridView.setAdapter(adapter);
}
Call adapter.notifyDataSetChanged() after movies.add(...) or in onPostExecute
I finished the Android Nanodegree a while back and remember working on this project. When you instantiate an adapter it will call the getSize() method to determine how many rows to create for the views and then call getView() on each of them to bind the views.
Since your async Task may not have finished downloading the movies, you're passing an empty list to the adapter and thus getting a NullPointerException.
It's always a good approach to instantiate the adapter in the onPostExecute() method of AsyncTask. This method is called on the UI thread after the background thread has finished execution.
So put these two lines of code in onPostExecute() and it should work
MovieAdapter adapter = new MovieAdapter(MainActivity.this, movies);
gridView.setAdapter(adapter);
I am trying to make an app where I want my app, on launch, to display a grid of popular movie posters. The movie posters are downloaded from TheMovieDataBase API. I then use Picasso to load the images. For the GridView I am also using a custom adapter. I am not able to understand how to do it. Here is what I have done up till now
MovieFragment.java
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MovieFragment extends Fragment {
//ArrayAdapter<String> mMovieAdapter;
String[]movieId,movieTitle,movieOverview,
movieReleaseDate,
moviePosterPath,movieVoteAverage;
public MovieFragment() {
}
MovieAdapter mMovieAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
mMovieAdapter = new MovieAdapter(getActivity());
GridView listView = (GridView) rootView.findViewById(R.id.gridView);
listView.setAdapter(mMovieAdapter);
updateMovie();
return rootView;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
inflater.inflate(R.menu.menu_fragment, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_refresh) {
updateMovie();
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateMovie() {
FetchMovieTask movieTask = new FetchMovieTask();
movieTask.execute();
}
class FetchMovieTask extends AsyncTask<Void, Void, List<String>> {
private final String LOG_TAG = FetchMovieTask.class.getSimpleName();
#Override
protected List<String> doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String movieJsonStr = null;
try {
URL url = new URL("http://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=c20129fdf73b5df3ab44548ad7f73586");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
movieJsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
try {
return getMovieDataFromJson(movieJsonStr);
} catch (JSONException j) {
Log.e(LOG_TAG, "JSON Error", j);
}
return null;
}
private List<String> getMovieDataFromJson(String forecastJsonStr)
throws JSONException {
JSONObject movieJson = new JSONObject(forecastJsonStr);
JSONArray movieArray = movieJson.getJSONArray("results");
List<String> urls = new ArrayList<>();
for (int i = 0; i < movieArray.length(); i++) {
JSONObject movie = movieArray.getJSONObject(i);
urls.add("http://image.tmdb.org/t/p/w185" + movie.getString("poster_path"));
}
return urls;
}
#Override
protected void onPostExecute(List<String> strings) {
mMovieAdapter.replace(strings);
}
}
class MovieAdapter extends BaseAdapter {
private final String LOG_TAG = MovieAdapter.class.getSimpleName();
private final Context context;
private final List<String> urls = new ArrayList<String>();
public MovieAdapter(Context context) {
this.context = context;
Collections.addAll(urls, moviePosterPath);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = new ImageView(context);
}
ImageView imageView = (ImageView) convertView;
String url = getItem(position);
Log.e(LOG_TAG," URL "+url);
Picasso.with(context).load(url).into(imageView);
return convertView;
}
#Override
public int getCount() {
return urls.size();
}
#Override
public String getItem(int position) {
return urls.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void replace(List<String> urls) {
this.urls.clear();
this.urls.addAll(urls);
notifyDataSetChanged();
}
}
}
When I run this code it shows a NullPointerException and a RuntimeException
java.lang.RuntimeException: Unable to start activity ComponentInfo
{com.codesetters.verader/com.codesetters.verader.MainActivity}: java.lang.NullPointerException atandroid.app.ActivityThreadperformLaunchActivity(ActivityThread.java:2404)
Caused by: java.lang.NullPointerException atjava.util.Collections.addAll(Collections.java:2582)
How can I resolve them?
Please Help
You're getting this error because you've used moviePosterPath here :
Collections.addAll(urls, moviePosterPath);
but you've not initialized it anywhere. Initialize it with some value and it should solve the error.
The null pointer could be because the String array moviePosterPath is not initialized. and you are ussing it in Collections.addAll
This is how to initialize an array. Anyway I recommend you to use ArrayList
String[] moviePosterPath = new String[N];
I have been trying too hard to get around this problom, when I tap the refresh button in my app, the images doesn't load on the screen.
This the DataFragment file, when i build this app there are no errors.
package com.example.popularmovis;
import android.app.Fragment;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.os.AsyncTask;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.jar.JarException;
/**
* A placeholder fragment containing a simple view.
*/
public class DataFragment extends Fragment {
public ImageAdapter display;
public DataFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events.
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.datafragment_menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_refresh) {
FetchMovieData movieData = new FetchMovieData();
movieData.execute();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
display = new ImageAdapter(rootView.getContext());
GridView gridView = (GridView) rootView.findViewById(R.id.gridView_movies);
gridView.setAdapter(display); // uses the view to get the context instead of getActivity().
return rootView;
}
public class FetchMovieData extends AsyncTask<Void, Void, String[]>{
private final String LOG_TAG = FetchMovieData.class.getSimpleName();
private String[] extractdisplayFromJason(String jasnData)
throws JSONException{
//These jason display need to be extracted
final String movie_results = "results";
final String movie_poster = "poster_path";
JSONObject movieData = new JSONObject(jasnData);
JSONArray movieArray = movieData.getJSONArray(movie_results);
String[] posterAddreess = new String[movieArray.length()];
//Fill ther posterAddreess with the URL to display
for(int j=0; j < movieArray.length(); j++){
String posterPath;
JSONObject movieArrayItem = movieArray.getJSONObject(j);
posterPath = movieArrayItem.getString(movie_poster);
posterAddreess[j] = "http://image.tmdb.org/t/p/w185/" + posterPath;
}
for (String s : posterAddreess) {
Log.v(LOG_TAG, "Thumbnail Links: " + s);
}
return posterAddreess;
}
#Override
protected String[] doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String JsonData = null;
String country = "US";
String rating = "R";
String sort = "popularity.desc";
String apiKey = "";
//building the URL for the movie DB
try {
//building the URL for the movie DB
final String MovieDatabaseUrl = "https://api.themoviedb.org/3/discover/movie?";
final String Country_for_release = "certification_country";
final String Rating = "certification";
final String Sorting_Order = "sort_by";
final String Api_Id = "api_key";
Uri buildUri = Uri.parse(MovieDatabaseUrl).buildUpon()
.appendQueryParameter(Country_for_release, country)
.appendQueryParameter(Rating, rating)
.appendQueryParameter(Sorting_Order, sort)
.appendQueryParameter(Api_Id, apiKey)
.build();
//Converting URI to URL
URL url = new URL(buildUri.toString());
Log.v(LOG_TAG, "Built URI = "+ buildUri.toString());
//Create the request to the Movie Database
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
//Read the input from the database into string
InputStream inputStream = urlConnection.getInputStream();
//StringBuffer for string Manipulation
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
JsonData = buffer.toString();
Log.v(LOG_TAG,"Forecaast Jason String" + JsonData );
} catch (IOException e) {
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
try {
return extractdisplayFromJason(JsonData);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute(String[] posterAddreess) {
for (String poster : posterAddreess) {
display.addItem(poster);
}
}
}
}
This the ImageAdapter code
package com.example.popularmovis;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import com.example.popularmovis.R;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ArrayList<String> images = new ArrayList<String>();
public ImageAdapter(Context c){
mContext = c;
}
#Override
public int getCount(){
return images.size();
}
#Override
public Object getItem(int position){
return images.get(position);
}
public long getItemId(int position){
return 0;
}
public View getView(int position, View convertView, ViewGroup parent){
ImageView imageview;
if (convertView == null){
imageview = new ImageView(mContext);
imageview.setPadding(0, 0, 0, 0);
//imageview.setLayoutParams(new GridLayout.MarginLayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
imageview.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageview.setAdjustViewBounds(true);
} else {
imageview = (ImageView) convertView;
}
Picasso.with(mContext).load(images.get(position)).placeholder(R.mipmap.ic_launcher).into(imageview);
return imageview;
}
/*
Custom methods
*/
public void addItem(String url){
images.add(url);
}
public void clearItems() {
images.clear();
}
}
When you use this in your onCreate method like this, it means that the object is local to the method and can't be use in other methods.
ImageAdapter display = new ImageAdapter(rootView.getContext());
First create a global class member variable
private ImageAdapter display;
then inside your onCreate method do this
display = new ImageAdapter(rootView.getContext());
I am trying to create android app with image gallery created with grid view using image adapter which fetch data using picasso library.but no image is displayed.It may be a problem of context or in picasso library but i am not sure where is the problem as i get no error.everything works fine according to Logs
**package com.example.android.popmovies;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
/**
* A placeholder fragment containing a simple view.
*/
public class PopMovieFragment extends Fragment {
ImageAdapter imageAdapter;
public PopMovieFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main,container,false);
GridView gridView = (GridView) view.findViewById(R.id.gridview);
imageAdapter = new ImageAdapter(getActivity(),new ArrayList<String>());
gridView.setAdapter(imageAdapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.v("check","ok");
}
});
return inflater.inflate(R.layout.fragment_main, container, false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onStart() {
super.onStart();
updateMovies();
}
public void updateMovies() {
FetchMovieTask movieTask = new FetchMovieTask();
movieTask.execute();
}
public class FetchMovieTask extends AsyncTask<String, Void, String[]> {
final String LOG_TAG = FetchMovieTask.class.getSimpleName();
private String[] getMovieImageFromJson(String movieJsonStr)
throws JSONException {
ArrayList<String> movieResults = new ArrayList<>();
String posterUrl;
final String OWM_MOVIE_RESULTS = "results";
JSONObject jsonObject = new JSONObject(movieJsonStr);
if (jsonObject.has(OWM_MOVIE_RESULTS)) {
JSONArray movieArray = jsonObject.getJSONArray(OWM_MOVIE_RESULTS);
//JSONArray movieArray = jsonObject.getJSONArray(OWM_MOVIE_RESULTS);
for (int i = 0; i < movieArray.length(); i++) {
JSONObject movieObject = movieArray.getJSONObject(i);
posterUrl = movieObject.getString("poster_path");
movieResults.add(posterUrl);
Log.v(LOG_TAG, posterUrl);
}
for (String items : movieResults){
Log.v(LOG_TAG,items);
}
// return null;
}
return movieResults.toArray(new String[0]);
// Log.v(LOG_TAG,posterUrl);
}
#Override
protected String[] doInBackground(String... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String movieJsonStr = null;
//parameters for api link will be here
try {
final String MOVIE_BASE_URL = "https://api.themoviedb.org/3/movie";
final String APPID_PARAM = "api_key";
final String CRITERIA_FOR_MOVIE_SELECTION_TOP = "top_rated";
final String CRITERIA_FOR_MOVIE_SELECTION_POPULAR = "popular";
Uri builtUri = Uri.parse(MOVIE_BASE_URL).buildUpon()
.appendPath(CRITERIA_FOR_MOVIE_SELECTION_TOP)
.appendQueryParameter(APPID_PARAM, BuildConfig.OPEN_MOVIEDB_API_KEY)
.build();
Log.v("TAG","BuiltURI" + builtUri.toString());
URL url = new URL(builtUri.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read input stream into a String
InputStream inputstream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputstream == null) {
movieJsonStr = null;
}
reader = new BufferedReader(new InputStreamReader(inputstream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
movieJsonStr = null;
}
movieJsonStr = buffer.toString();
Log.v(LOG_TAG, "Movie Json String" + movieJsonStr);
} catch (IOException e) {
Log.e(LOG_TAG, "error here" + e);
movieJsonStr = null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "ErrorClosingStream", e);
}
}
}
try {
// here will be method call for JSon parsing.
String [] check_items = getMovieImageFromJson(movieJsonStr);
for (String items : check_items){
Log.v(LOG_TAG,items+"new");
}
return check_items;
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String[] result) {
if (result != null) {
for (String resultItems : result){
Log.v(LOG_TAG,resultItems+"GoodLuck");
final String PICTURE_BASE_URL = "http://image.tmdb.org/t/p/w185/";
final String PICTURE_URL_END = resultItems;
Uri builtUri = Uri.parse(PICTURE_BASE_URL).buildUpon()
.appendPath(PICTURE_URL_END.replace("/",""))
.build();
Log.v(LOG_TAG,resultItems+"GoodLuck"+builtUri.toString());
imageAdapter.setmresultItems(builtUri.toString());
}
}
}
}
}
class ImageAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> mresultItems;
public ImageAdapter(Context c,ArrayList<String> resultItems){
mContext = c;
mresultItems = resultItems;
}
public int getCount(){
// return mThumbsIds.length;
return 0;
}
public Object getItem(int position){
return null;
}
public long getItemId(int position){
return 0;
}
public void setmresultItems(String resultItems){
mresultItems.add(resultItems);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null){
// if it is not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(85,85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8,8,8,8);
}else{
imageView = (ImageView) convertView;
}
//imageView.setImageResource(mThumbsIds[position]);
for(String picResultUrl : mresultItems){
Picasso.with(mContext).load(picResultUrl).into(imageView);
}
return imageView;
}
//references to our Images
//private Integer[] mThumbsIds ;
}**
You shouldn't have a for loop in the getView() method, it already gets called for each item in the list.
Be sure to return the correct count:
public int getCount(){
return mresultItems.size();
}
Then, use just the current position of the data source in getView():
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null){
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(85,85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8,8,8,8);
}else{
imageView = (ImageView) convertView;
}
//modified:
String picUrl = mresultItems.get(position);
Picasso.with(mContext).load(picUrl).into(imageView);
}
return imageView;
}
Also, call notifyDataSetChanged() on the adapter in onPostExecute() after the data source of the adapter has been updated:
#Override
protected void onPostExecute(String[] result) {
if (result != null) {
for (String resultItems : result){
Log.v(LOG_TAG,resultItems+"GoodLuck");
final String PICTURE_BASE_URL = "http://image.tmdb.org/t/p/w185/";
final String PICTURE_URL_END = resultItems;
Uri builtUri = Uri.parse(PICTURE_BASE_URL).buildUpon()
.appendPath(PICTURE_URL_END.replace("/",""))
.build();
Log.v(LOG_TAG,resultItems+"GoodLuck"+builtUri.toString());
imageAdapter.setmresultItems(builtUri.toString());
}
//Add this here:
imageAdapter.notifyDataSetChanged();
}
}
I found that i was not returning view in onCreate method which was the root cause of blank screen.
I'm working on an app and I'm trying to show a listview filled with information from a MySQL database. I already have a different activity where I send and receive from the database using php, I'm doing something similar. I'm not sure if the error I'm having is something with the adapter class or from the Json Parsing part in the AsyncTask. These are the files:
package com.example.xxx.xxx;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.ListView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
public class ListActivity extends ActionBarActivity {
ListView list;
ArrayList<Places> placeslist;
PlacesAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.single_row);
placeslist = new ArrayList<Places>();
new JASONTask().execute("http://xxx.xxx.com/getlist.php");
adapter = new PlacesAdapter(getApplicationContext(), R.layout.single_row, placeslist);
list = (ListView)findViewById(R.id.listView);
list.setAdapter(adapter);
}
public class JASONTask extends AsyncTask<String,Void,Boolean>{
ProgressDialog dialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(ListActivity.this);
dialog.setMessage("Loading, please wait");
dialog.setTitle("Connecting server");
dialog.show();
dialog.setCancelable(false);
}
#Override
protected Boolean doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line ="";
while ((line = reader.readLine()) != null){
buffer.append(line);
}
String finalJson = buffer.toString();
JSONArray theJson = new JSONArray(finalJson);
for (int i=0; i<theJson.length(); i++){
Places place = new Places();
JSONObject jRealObject = theJson.getJSONObject(i);
place.setPlaces_id(jRealObject.getString("places_id"));
place.setName(jRealObject.getString("name"));
place.setLocation_address(jRealObject.getString("location_address"));
placeslist.add(place);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if(connection != null) {
connection.disconnect();
}
try {
if (reader != null){
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (result == false){
//message not parsed
}
}
}
}
The Places class is:
package com.example.xxx.xxx;
/**
* Created by manhols on 10/12/2015.
*/
public class Places {
private String places_id;
private String name;
private String location_address;
public Places(){
}
public String getPlaces_id() {
return places_id;
}
public void setPlaces_id(String places_id) {
this.places_id = places_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation_address() {
return location_address;
}
public void setLocation_address(String location_address) {
this.location_address = location_address;
}
}
And the PlacesAdapter class is:
package com.example.xxx.xxx;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by manhols on 10/12/2015.
*/
public class PlacesAdapter extends ArrayAdapter<Places>{
ArrayList<Places> placeslist;
int Resource;
Context context;
LayoutInflater vi;
public PlacesAdapter(Context context, int resource, ArrayList<Places> objects) {
super(context, resource, objects);
Resource = resource;
placeslist = objects;
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
vi.inflate(Resource, null);
convertView = vi.inflate(Resource,null);
holder = new ViewHolder();
holder.textView = (TextView)convertView.findViewById(R.id.textView);
holder.textView2 = (TextView)convertView.findViewById(R.id.textView2);
holder.textView5 = (TextView)convertView.findViewById(R.id.textView5);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(placeslist.get(position).getName());
holder.textView2.setText(placeslist.get(position).getPlaces_id());
holder.textView5.setText(placeslist.get(position).getLocation_address());
return convertView;
}
static class ViewHolder {
public TextView textView;
public TextView textView2;
public TextView textView5;
}
}
I will highly appreciate any help solving this issue.
I have spotted some errors in your adapter. Please inflate row as convertView = vi.inflate(Resource,parent,false); and also in parsing the data , return true only in try block. From your code i can see that even if you have an exception, you will be returning true which is wrong.
My problem was in the setContentView as #codeMagic mentioned before. I already solved this thanks to him