Call rest API using Volley in Android
The very basic requirement in developing the Android application is “Api Integration” and fetch the details. For calling the Api we need the android networking library to interact with the web services and get the response from Api.
One such library is Volley which is developed by Google to handle Api calls.
Volley is an HTTP library that makes networking for Android apps easier and most importantly, faster. Volley is available on GitHub.
To know more about Volley, go here.
Our Post is divided into five parts, we will call https://www.themoviedb.org/
Its a collection of apis , for our demo we are fetching the list of popular movies from tmdb and display in recyclerview.
Pre Requisites:
We need to sign up and get the api_key before we can call any Api.
Dependencies
We need to add below dependencies in app->build.gradle
dependencies { //recyclerview to show list implementation 'com.android.support:recyclerview-v7:27.1.1' //Gson implementation 'com.google.code.gson:gson:2.8.2' //Volley implementation 'com.android.volley:volley:1.1.0' }
Structure for Volley Api request
WebApiRequest.java class is a common class to call APIs. We just have to create an instance of the class and call its appropriate constructor to initialize our Volley api call.
For future enhancement, we have added different parameters if we need to call the APIs with custom headers and parameters.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.askfortrciks.volleywithgsondemo.volley; | |
import com.android.volley.AuthFailureError; | |
import com.android.volley.Response.ErrorListener; | |
import com.android.volley.Response.Listener; | |
import com.android.volley.toolbox.StringRequest; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class WebApiRequest extends StringRequest { | |
private Map<String, String> headers = new HashMap<String, String>(); | |
private Map<String, String> params = new HashMap<String, String>(); | |
public WebApiRequest(int method, String url, Listener<String> listener, | |
ErrorListener errorListener, String token) { | |
super(method, url, listener, errorListener); | |
if (token != null) { | |
this.headers.put("Cookie", token); | |
} | |
} | |
public WebApiRequest(int method, String url, | |
Listener<String> listener, ErrorListener errorListener) { | |
super(method, url, listener, errorListener); | |
} | |
public WebApiRequest(int method, String url, Listener<String> listener, ErrorListener errorListener, | |
String token, Map<String, String> params) { | |
super(method, url, listener, errorListener); | |
if (token != null && params != null) { | |
this.headers.put("Cookie", token); | |
this.params = params; | |
} | |
} | |
@Override | |
public Map<String, String> getHeaders() throws AuthFailureError { | |
return headers; | |
} | |
/** | |
* To add headers in any api request in the form of | |
* key and value | |
* @param title | |
* @param content | |
*/ | |
public void setHeader(String title, String content) { | |
headers.put(title, content); | |
} | |
/** | |
* To add parameters in the api request | |
* @return | |
* @throws AuthFailureError | |
*/ | |
@Override | |
protected Map<String, String> getParams() throws AuthFailureError { | |
return params; | |
} | |
public void setParam(String title, String content) { | |
params.put(title, content); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class WebServicesConstant { | |
//Main Host Url to access apis | |
public static final String BASE_URL_APPLICATION="https://api.themoviedb.org/3/"; | |
//Image urls | |
public static final String BASE_URL_IMAGE_ORIGINAL="https://image.tmdb.org/t/p/original"; | |
public static final String BASE_URL_IMAGE_W_500="https://image.tmdb.org/t/p/w500"; | |
//api key (Its my personal) you have to crate your own to avoid suspension of your account | |
public static final String API_KEY="23fc7389372548c592b1f08cb8a0dffe"; | |
//api connections | |
public static final String MOVIE="movie/"; | |
public static final String TOP_RATED="top_rated"; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.askfortrciks.volleywithgsondemo.volley; | |
import com.android.volley.AuthFailureError; | |
import com.android.volley.Response.ErrorListener; | |
import com.android.volley.Response.Listener; | |
import com.android.volley.toolbox.StringRequest; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class WebApiRequest extends StringRequest { | |
private Map<String, String> headers = new HashMap<String, String>(); | |
private Map<String, String> params = new HashMap<String, String>(); | |
public WebApiRequest(int method, String url, Listener<String> listener, | |
ErrorListener errorListener, String token) { | |
super(method, url, listener, errorListener); | |
if (token != null) { | |
this.headers.put("Cookie", token); | |
} | |
} | |
public WebApiRequest(int method, String url, | |
Listener<String> listener, ErrorListener errorListener) { | |
super(method, url, listener, errorListener); | |
} | |
public WebApiRequest(int method, String url, Listener<String> listener, ErrorListener errorListener, | |
String token, Map<String, String> params) { | |
super(method, url, listener, errorListener); | |
if (token != null && params != null) { | |
this.headers.put("Cookie", token); | |
this.params = params; | |
} | |
} | |
@Override | |
public Map<String, String> getHeaders() throws AuthFailureError { | |
return headers; | |
} | |
/** | |
* To add headers in any api request in the form of | |
* key and value | |
* @param title | |
* @param content | |
*/ | |
public void setHeader(String title, String content) { | |
headers.put(title, content); | |
} | |
/** | |
* To add parameters in the api request | |
* @return | |
* @throws AuthFailureError | |
*/ | |
@Override | |
protected Map<String, String> getParams() throws AuthFailureError { | |
return params; | |
} | |
public void setParam(String title, String content) { | |
params.put(title, content); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class WebServicesConstant { | |
//Main Host Url to access apis | |
public static final String BASE_URL_APPLICATION="https://api.themoviedb.org/3/"; | |
//Image urls | |
public static final String BASE_URL_IMAGE_ORIGINAL="https://image.tmdb.org/t/p/original"; | |
public static final String BASE_URL_IMAGE_W_500="https://image.tmdb.org/t/p/w500"; | |
//api key (Its my personal) you have to crate your own to avoid suspension of your account | |
public static final String API_KEY="23fc7389372548c592b1f08cb8a0dffe"; | |
//api connections | |
public static final String MOVIE="movie/"; | |
public static final String TOP_RATED="top_rated"; | |
} |
Top 10 free Android libraries for app development in android studio
Recyclerview to display List
Here we will call TOP_RATED movie API in the call method mentioned in the MovieListingActivity.java to fetch the results.
The most important method is ReqSuccessListener which will handle the callback if API returns the results.
ReqErrorListener method will handle any server error if any in the response. If the server returned unexpected response then this method will handle it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Success listener to handle the movie listing | |
* process after api returns the movie list | |
* | |
* @return | |
*/ | |
private Response.Listener<String> ReqSuccessListener() { | |
return new Response.Listener<String>() { | |
public void onResponse(String response) { | |
Log.e("movie list_response", response); | |
try { | |
hideProgress(); | |
pageNumber++; | |
MovieList movieListModel = (MovieList) Utils.jsonToPojo(response, MovieList.class); | |
if (movieListModel.getResults() != null && | |
movieListModel.getResults().size() > 0) { | |
moviesRecyclerAdapter.addMovies(movieListModel.getResults()); | |
} else { | |
Log.e(TAG, "list empty=="); | |
} | |
} catch (Exception e) { | |
Log.e(TAG,"Exception=="+e.getLocalizedMessage()); | |
} | |
} | |
}; | |
} | |
/** | |
* To Handle the error | |
* | |
* @return | |
*/ | |
private Response.ErrorListener ReqErrorListener() { | |
return new Response.ErrorListener() { | |
public void onErrorResponse(VolleyError error) { | |
Log.e("volley error", "volley error"); | |
Toast.makeText(MovieListingActivity.this, "" + | |
"Server Error..Please try again after sometime", Toast.LENGTH_SHORT).show(); | |
} | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:tools="http://schemas.android.com/tools" | |
android:id="@+id/rlMoviesList" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<android.support.v7.widget.RecyclerView | |
android:id="@+id/rvMoviesList" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" /> | |
</RelativeLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.askfortrciks.volleywithgsondemo.activity; | |
import android.os.Bundle; | |
import android.support.annotation.Nullable; | |
import android.support.v7.app.AppCompatActivity; | |
import android.support.v7.widget.LinearLayoutManager; | |
import android.support.v7.widget.RecyclerView; | |
import android.util.Log; | |
import android.view.View; | |
import android.widget.ProgressBar; | |
import android.widget.RelativeLayout; | |
import android.widget.Toast; | |
import com.android.volley.Request; | |
import com.android.volley.Response; | |
import com.android.volley.VolleyError; | |
import com.android.volley.toolbox.Volley; | |
import com.askfortrciks.volleywithgsondemo.R; | |
import com.askfortrciks.volleywithgsondemo.adapter.MoviesRecyclerAdapter; | |
import com.askfortrciks.volleywithgsondemo.model.MovieList; | |
import com.askfortrciks.volleywithgsondemo.utils.Utils; | |
import com.askfortrciks.volleywithgsondemo.volley.WebApiRequest; | |
import static com.askfortrciks.volleywithgsondemo.constant.WebServicesConstant.API_KEY; | |
import static com.askfortrciks.volleywithgsondemo.constant.WebServicesConstant.BASE_URL_APPLICATION; | |
import static com.askfortrciks.volleywithgsondemo.constant.WebServicesConstant.MOVIE; | |
import static com.askfortrciks.volleywithgsondemo.constant.WebServicesConstant.TOP_RATED; | |
public class MovieListingActivity extends AppCompatActivity { | |
public static final String TAG = "MovieListingActivity"; | |
private RelativeLayout rlMoviesList; | |
private RecyclerView rvMoviesList; | |
private LinearLayoutManager linearLayoutManager; | |
private ProgressBar progressBar; | |
//For Load more functionality | |
private int previousTotal = 0; | |
private boolean loading = true; | |
private int visibleThreshold = 2; | |
private int firstVisibleItem = 0; | |
private int visibleItemCount = 0; | |
private int totalItemCount = 0; | |
//current page number | |
private int pageNumber = 1; | |
//Adapter class for movie list recycler view | |
MoviesRecyclerAdapter moviesRecyclerAdapter; | |
@Override | |
protected void onCreate(@Nullable Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_movies_list); | |
initView(); | |
callGetTopRatedMoviesApi(); | |
} | |
private void initView() { | |
rlMoviesList = findViewById(R.id.rlMoviesList); | |
rvMoviesList = findViewById(R.id.rvMoviesList); | |
rvMoviesList.setHasFixedSize(true); | |
linearLayoutManager = new LinearLayoutManager(this);// new LinearLayoutManager() | |
rvMoviesList.setLayoutManager(linearLayoutManager); | |
rvMoviesList.clearOnScrollListeners(); //clear scrolllisteners | |
moviesRecyclerAdapter=new MoviesRecyclerAdapter(this); | |
rvMoviesList.setAdapter(moviesRecyclerAdapter); | |
/** | |
* For Adding Load more functionality | |
* | |
*/ | |
rvMoviesList.addOnScrollListener(new RecyclerView.OnScrollListener() { | |
@Override | |
public void onScrolled(RecyclerView recyclerView, int dx, int dy) { | |
super.onScrolled(recyclerView, dx, dy); | |
if (dy > 0) { | |
visibleItemCount = recyclerView.getChildCount(); | |
totalItemCount = linearLayoutManager.getItemCount(); | |
firstVisibleItem = linearLayoutManager.findFirstVisibleItemPosition(); | |
if (loading) { | |
if (totalItemCount > previousTotal) { | |
loading = false; | |
previousTotal = totalItemCount; | |
} | |
} | |
if (!loading && (totalItemCount – visibleItemCount) | |
<= (firstVisibleItem + visibleThreshold)) { | |
// End has been reached | |
Log.i("InfiniteScrollListener", "End reached"); | |
callGetTopRatedMoviesApi(); | |
loading = true; | |
} | |
} | |
} | |
}); | |
} | |
/** | |
* Display Progress bar | |
*/ | |
private void showProgress() { | |
progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge); | |
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100); | |
params.addRule(RelativeLayout.CENTER_IN_PARENT); | |
rlMoviesList.addView(progressBar, params); | |
progressBar.setVisibility(View.VISIBLE); | |
} | |
/** | |
* Hide Progress bar | |
*/ | |
private void hideProgress() { | |
progressBar.setVisibility(View.GONE); | |
} | |
/** | |
* Call the api to fetch the TopRatedMovies list | |
*/ | |
private void callGetTopRatedMoviesApi() { | |
/** | |
* Checking internet connection before api call. | |
* Very important always take care. | |
*/ | |
if (!Utils.isNetworkAvailable(this)) { | |
Toast.makeText(this, | |
"No internet ..Please connect to internet and start app again", | |
Toast.LENGTH_SHORT).show(); | |
return; | |
} | |
showProgress(); | |
//constructing api url | |
String ws_url = BASE_URL_APPLICATION + MOVIE + TOP_RATED + | |
"?api_key=" + API_KEY + "&language=en-US&page=" + pageNumber; | |
//Using Volley to call api | |
WebApiRequest webApiRequest = new WebApiRequest(Request.Method.GET, | |
ws_url, ReqSuccessListener(), ReqErrorListener()); | |
Volley.newRequestQueue(MovieListingActivity.this).add(webApiRequest); | |
} | |
/** | |
* Success listener to handle the movie listing | |
* process after api returns the movie list | |
* | |
* @return | |
*/ | |
private Response.Listener<String> ReqSuccessListener() { | |
return new Response.Listener<String>() { | |
public void onResponse(String response) { | |
Log.e("movie list_response", response); | |
try { | |
hideProgress(); | |
pageNumber++; | |
MovieList movieListModel = (MovieList) Utils.jsonToPojo(response, MovieList.class); | |
if (movieListModel.getResults() != null && | |
movieListModel.getResults().size() > 0) { | |
moviesRecyclerAdapter.addMovies(movieListModel.getResults()); | |
} else { | |
Log.e(TAG, "list empty=="); | |
} | |
} catch (Exception e) { | |
Log.e(TAG,"Exception=="+e.getLocalizedMessage()); | |
} | |
} | |
}; | |
} | |
/** | |
* To Handle the error | |
* | |
* @return | |
*/ | |
private Response.ErrorListener ReqErrorListener() { | |
return new Response.ErrorListener() { | |
public void onErrorResponse(VolleyError error) { | |
Log.e("volley error", "volley error"); | |
Toast.makeText(MovieListingActivity.this, "" + | |
"Server Error..Please try again after sometime", Toast.LENGTH_SHORT).show(); | |
} | |
}; | |
} | |
} |
Calling Tmdb API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private void callGetTopRatedMoviesApi() { | |
/** | |
* Checking internet connection before api call. | |
* Very important always take care. | |
*/ | |
if (!Utils.isNetworkAvailable(this)) { | |
Toast.makeText(this, | |
"No internet ..Please connect to internet and start app again", | |
Toast.LENGTH_SHORT).show(); | |
return; | |
} | |
showProgress(); | |
//constructing api url | |
String ws_url = BASE_URL_APPLICATION + MOVIE + TOP_RATED + | |
"?api_key=" + API_KEY + "&language=en-US&page=" + pageNumber; | |
//Using Volley to call api | |
WebApiRequest webApiRequest = new WebApiRequest(Request.Method.GET, | |
ws_url, ReqSuccessListener(), ReqErrorListener()); | |
Volley.newRequestQueue(MovieListingActivity.this).add(webApiRequest); | |
} | |
/** | |
* Success listener to handle the movie listing | |
* process after api returns the movie list | |
* | |
* @return | |
*/ | |
private Response.Listener<String> ReqSuccessListener() { | |
return new Response.Listener<String>() { | |
public void onResponse(String response) { | |
Log.e("movie list_response", response); | |
try { | |
hideProgress(); | |
pageNumber++; | |
MovieList movieListModel = (MovieList) Utils.jsonToPojo(response, MovieList.class); | |
if (movieListModel.getResults() != null && | |
movieListModel.getResults().size() > 0) { | |
moviesRecyclerAdapter.addMovies(movieListModel.getResults()); | |
} else { | |
Log.e(TAG, "list empty=="); | |
} | |
} catch (Exception e) { | |
Log.e(TAG,"Exception=="+e.getLocalizedMessage()); | |
} | |
} | |
}; | |
} | |
/** | |
* To Handle the error | |
* | |
* @return | |
*/ | |
private Response.ErrorListener ReqErrorListener() { | |
return new Response.ErrorListener() { | |
public void onErrorResponse(VolleyError error) { | |
Log.e("volley error", "volley error"); | |
Toast.makeText(MovieListingActivity.this, "" + | |
"Server Error..Please try again after sometime", Toast.LENGTH_SHORT).show(); | |
} | |
}; | |
} |
Adding the load more or infinite scrollview to recyclerview.
We have attached a scroll listener as always we need to add endless scroll or infinite scroll to load the results. In web format, we call it paging based on the number of results. Say we need 20 results in one API call. And then again next 20 sequentially.
This can be used by you in any application or projects.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* For Adding Load more functionality | |
* | |
*/ | |
rvMoviesList.addOnScrollListener(new RecyclerView.OnScrollListener() { | |
@Override | |
public void onScrolled(RecyclerView recyclerView, int dx, int dy) { | |
super.onScrolled(recyclerView, dx, dy); | |
if (dy > 0) { | |
visibleItemCount = recyclerView.getChildCount(); | |
totalItemCount = linearLayoutManager.getItemCount(); | |
firstVisibleItem = linearLayoutManager.findFirstVisibleItemPosition(); | |
if (loading) { | |
if (totalItemCount > previousTotal) { | |
loading = false; | |
previousTotal = totalItemCount; | |
} | |
} | |
if (!loading && (totalItemCount – visibleItemCount) | |
<= (firstVisibleItem + visibleThreshold)) { | |
// End has been reached | |
Log.i("InfiniteScrollListener", "End reached"); | |
callGetTopRatedMoviesApi(); | |
loading = true; | |
} | |
} | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* For Adding Load more functionality | |
* | |
*/ | |
rvMoviesList.addOnScrollListener(new RecyclerView.OnScrollListener() { | |
@Override | |
public void onScrolled(RecyclerView recyclerView, int dx, int dy) { | |
super.onScrolled(recyclerView, dx, dy); | |
if (dy > 0) { | |
visibleItemCount = recyclerView.getChildCount(); | |
totalItemCount = linearLayoutManager.getItemCount(); | |
firstVisibleItem = linearLayoutManager.findFirstVisibleItemPosition(); | |
if (loading) { | |
if (totalItemCount > previousTotal) { | |
loading = false; | |
previousTotal = totalItemCount; | |
} | |
} | |
if (!loading && (totalItemCount – visibleItemCount) | |
<= (firstVisibleItem + visibleThreshold)) { | |
// End has been reached | |
Log.i("InfiniteScrollListener", "End reached"); | |
callGetTopRatedMoviesApi(); | |
loading = true; | |
} | |
} | |
} | |
}); |
For Complete Demo of Volley using Gson find the source codes in below project.
https://github.com/askfortricks/VolleyWithGsonDemo
Ravi Yadav is an Android developer whose passion is to develop Android applications and sharing his work. He loves to post the tutorials which he created while learning any new latest technology topic.He loves to share about the latest technology happenings and other tricks that will be helpful for readers of Askfortricks.
Feeling glad to receive your comment