How to Build a Book Library App using Google Books API in Android?
Last Updated : 02 Apr, 2025
If you are looking for building a book library app and you want to load a huge data of books then for adding this feature, you have to use a simple API which is provided by Google, and of course, it's free. In this article, we will take a look at the implementation of this API in our Android App.
What we are going to build in this article?
We will be building a simple application in which we will be searching different types of books and we will get to see the list of books related to that topic in our RecyclerView. For searching these books we will be using a free API provided by Google which holds a huge collection of books. A sample video is given below to get an idea about what we are going to do in this article.
Note that we are going to implement this project using the Java language.
Step by Step Implementation
Step 1: Create a New Project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio.
Step 2: Add the dependency for Volley in your Gradle files
Navigate to the app > Gradle Scripts > build.gradle.kts (Module :app) file and add below dependency in the dependencies section.
dependencies { ... implementation("com.android.volley:volley:1.2.1") implementation("com.github.bumptech.glide:glide:4.16.0") }
After adding the below dependencies in your gradle file now sync your project. As we will be using volley to fetch data from our API and Glide image loading library to load images from URL.
Step 3: Adding permissions for the Internet
Navigate to the app > manifests > AndroidManifest.xml and add the below permissions to it.
<uses-permission android:name="android.permission.INTERNET" />
As we will be loading the books from API so we have to request Internet permissions from the user. For that add the permissions for the internet in AndroidManifest.xml.
Step 4: Working with the activity_main.xml and its sub layout
Go to the activity_main.xml file and refer to the following code. Now, create a new layout for each item of the recyclerview and name it book_rv_item.xml. Remember to add a drawable for the search button.
The xml code is given below.
activity_main.xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" android:orientation="vertical" tools:context=".MainActivity"> <LinearLayout android:id="@+id/searchLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="32dp" android:orientation="horizontal" android:weightSum="5" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <!-- search bar --> <EditText android:id="@+id/searchEditText" style="@style/Widget.Material3.Button.OutlinedButton" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="4" android:gravity="start|center_vertical" android:hint="Search books..." android:textColor="@color/black" /> <!--search button --> <ImageButton android:id="@+id/searchButton" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_weight="1" android:background="@color/colorPrimary" android:padding="16dp" android:src="@drawable/ic_search" app:tint="@color/white" /> </LinearLayout> <!--recycler view for displaying our list of books--> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="0dp" android:layout_margin="16dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/searchLayout" tools:listitem="@layout/book_rv_item" /> <!--progressbar for displaying our loading indicator--> <ProgressBar android:id="@+id/progressBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
book_rv_item.xml <?xml version="1.0" encoding="utf-8"?> <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" app:cardBackgroundColor="@color/white" android:layout_margin="4dp" app:cardCornerRadius="24dp" app:strokeWidth="2dp" app:cardElevation="0dp"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/bookImage" android:layout_width="130dp" android:layout_height="160dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="16dp" android:src="@drawable/background" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/bookTitle" android:layout_width="0dp" android:layout_height="wrap_content" android:padding="3dp" android:text="Book Title" android:textColor="@color/black" android:layout_marginEnd="16dp" android:textSize="18sp" android:textStyle="bold" app:layout_constraintBottom_toTopOf="@+id/publisher" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toEndOf="@+id/bookImage" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_chainStyle="packed" /> <TextView android:id="@+id/publisher" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="3dp" android:text="Publisher" android:textColor="@color/black" android:textSize="12sp" android:textStyle="italic" app:layout_constraintBottom_toTopOf="@+id/pageCount" app:layout_constraintStart_toEndOf="@+id/bookImage" app:layout_constraintTop_toBottomOf="@+id/bookTitle" /> <TextView android:id="@+id/pageCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/publisher" android:layout_toEndOf="@id/bookImage" android:padding="3dp" android:text="Page count" android:textColor="@color/black" android:textSize="12sp" app:layout_constraintBottom_toTopOf="@+id/date" app:layout_constraintStart_toEndOf="@+id/bookImage" app:layout_constraintTop_toBottomOf="@+id/publisher" /> <TextView android:id="@+id/date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/pageCount" android:layout_alignParentEnd="true" android:padding="3dp" android:text="date" android:textColor="@color/black" android:textSize="12sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@+id/bookImage" app:layout_constraintTop_toBottomOf="@+id/pageCount" /> </androidx.constraintlayout.widget.ConstraintLayout> </com.google.android.material.card.MaterialCardView>
ic_search.xml <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24" android:tint="?attr/colorControlNormal"> <path android:fillColor="@android:color/white" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/> </vector>
Step 5: Creating a Modal Class for storing our data from the API.
For creating a new Modal class. Navigate to the app > java > {package-name}, Right-click on it and Click on, New > Java/Kotlin class and give a name to our file as BookInfo and add below code to it. Comments are added in the code to get to know in more detail.
BookInfo.java package org.geeksforgeeks.demo; import java.util.ArrayList; public class BookInfo { // creating string, int and array list // variables for our book details private String title; private String subtitle; private ArrayList<String> authors; private String publisher; private String publishedDate; private String description; private int pageCount; private String thumbnail; private String previewLink; private String infoLink; private String buyLink; // creating getter and setter methods public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getSubtitle() { return subtitle; } public void setSubtitle(String subtitle) { this.subtitle = subtitle; } public ArrayList<String> getAuthors() { return authors; } public void setAuthors(ArrayList<String> authors) { this.authors = authors; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public String getPublishedDate() { return publishedDate; } public void setPublishedDate(String publishedDate) { this.publishedDate = publishedDate; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public int getPageCount() { return pageCount; } public void setPageCount(int pageCount) { this.pageCount = pageCount; } public String getThumbnail() { return thumbnail; } public void setThumbnail(String thumbnail) { this.thumbnail = thumbnail; } public String getPreviewLink() { return previewLink; } public void setPreviewLink(String previewLink) { this.previewLink = previewLink; } public String getInfoLink() { return infoLink; } public void setInfoLink(String infoLink) { this.infoLink = infoLink; } public String getBuyLink() { return buyLink; } public void setBuyLink(String buyLink) { this.buyLink = buyLink; } // creating a constructor class for our BookInfo public BookInfo(String title, String subtitle, ArrayList<String> authors, String publisher, String publishedDate, String description, int pageCount, String thumbnail, String previewLink, String infoLink, String buyLink) { this.title = title; this.subtitle = subtitle; this.authors = authors; this.publisher = publisher; this.publishedDate = publishedDate; this.description = description; this.pageCount = pageCount; this.thumbnail = thumbnail; this.previewLink = previewLink; this.infoLink = infoLink; this.buyLink = buyLink; } }
BookInfo.kt package org.geeksforgeeks.demo data class BookInfo ( // creating string, int and array list // variables for our book details var title: String, var subtitle: String, var authors: ArrayList<String>, var publisher: String, var publishedDate: String, var description: String, var pageCount: Int, var thumbnail: String, var previewLink: String, var infoLink: String, var buyLink: String )
Step 7: Creating an Adapter class for setting our data to the item of RecyclerView
Navigate to the app > java > {package-name}, Right-click on it and Click on, New > Java/Kotlin class and name it as BookAdapter and add below code to it. Comments are added in the code to get to know in more detail.
BookAdapter.java package org.geeksforgeeks.demo; import android.content.Context; import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import java.util.ArrayList; public class BookAdapter extends RecyclerView.Adapter<BookAdapter.BookViewHolder> { private final ArrayList<BookInfo> bookInfoArrayList; private final Context context; // Constructor to initialize adapter with data public BookAdapter(ArrayList<BookInfo> bookInfoArrayList, Context context) { this.bookInfoArrayList = bookInfoArrayList; this.context = context; } @NonNull @Override public BookViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { // Inflate layout for each RecyclerView item View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.book_rv_item, parent, false); return new BookViewHolder(view); } @Override public void onBindViewHolder(@NonNull BookViewHolder holder, int position) { // Get current book info BookInfo bookInfo = bookInfoArrayList.get(position); // Set data to UI components holder.nameTV.setText(bookInfo.getTitle()); holder.publisherTV.setText(bookInfo.getPublisher()); holder.pageCountTV.setText("Pages : " + bookInfo.getPageCount()); holder.dateTV.setText("Published On : " + bookInfo.getPublishedDate()); // Load image from URL using Glide Glide.with(context).load(bookInfo.getThumbnail()).into(holder.bookIV); // Set click listener to open BookDetails activity with data holder.itemView.setOnClickListener(v -> { Intent intent = new Intent(context, BookDetails.class); intent.putExtra("title", bookInfo.getTitle()); intent.putExtra("subtitle", bookInfo.getSubtitle()); intent.putExtra("authors", bookInfo.getAuthors()); intent.putExtra("publisher", bookInfo.getPublisher()); intent.putExtra("publishedDate", bookInfo.getPublishedDate()); intent.putExtra("description", bookInfo.getDescription()); intent.putExtra("pageCount", bookInfo.getPageCount()); intent.putExtra("thumbnail", bookInfo.getThumbnail()); intent.putExtra("previewLink", bookInfo.getPreviewLink()); intent.putExtra("infoLink", bookInfo.getInfoLink()); intent.putExtra("buyLink", bookInfo.getBuyLink()); // Start new activity with intent context.startActivity(intent); }); } @Override public int getItemCount() { return bookInfoArrayList.size(); } // ViewHolder class to hold UI elements for each item public static class BookViewHolder extends RecyclerView.ViewHolder { TextView nameTV, publisherTV, pageCountTV, dateTV; ImageView bookIV; public BookViewHolder(@NonNull View itemView) { super(itemView); // Initialize UI components nameTV = itemView.findViewById(R.id.bookTitle); publisherTV = itemView.findViewById(R.id.publisher); pageCountTV = itemView.findViewById(R.id.pageCount); dateTV = itemView.findViewById(R.id.date); bookIV = itemView.findViewById(R.id.bookImage); } } }
BookAdapter.kt package org.geeksforgeeks.demo import android.content.Context import android.content.Intent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide class BookAdapter( private val bookInfoArrayList: ArrayList<BookInfo>, private val context: Context ) : RecyclerView.Adapter<BookAdapter.BookViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookViewHolder { // inflating layout for item of recycler view val view: View = LayoutInflater.from(parent.context).inflate(R.layout.book_rv_item, parent, false) return BookViewHolder(view) } override fun onBindViewHolder(holder: BookViewHolder, position: Int) { // setup data to each UI component val bookInfo = bookInfoArrayList[position] holder.nameTV.text = bookInfo.title holder.publisherTV.text = bookInfo.publisher holder.pageCountTV.text = "Pages : " + bookInfo.pageCount holder.dateTV.text = "Published On : " + bookInfo.publishedDate // set image from URL in our image view. Glide.with(context).load(bookInfo.thumbnail).into(holder.bookIV) // add on click listener on the card holder.itemView.setOnClickListener { // call a new activity and passing all the data of that item in next intent val intent = Intent(context, BookDetails::class.java) intent.putExtra("title", bookInfo.title) intent.putExtra("subtitle", bookInfo.subtitle) intent.putExtra("authors", bookInfo.authors) intent.putExtra("publisher", bookInfo.publisher) intent.putExtra("publishedDate", bookInfo.publishedDate) intent.putExtra("description", bookInfo.description) intent.putExtra("pageCount", bookInfo.pageCount) intent.putExtra("thumbnail", bookInfo.thumbnail) intent.putExtra("previewLink", bookInfo.previewLink) intent.putExtra("infoLink", bookInfo.infoLink) intent.putExtra("buyLink", bookInfo.buyLink) // after passing that data we are start new intent context.startActivity(intent) } } override fun getItemCount(): Int = bookInfoArrayList.size inner class BookViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { // initialize text views and image view var nameTV: TextView = itemView.findViewById(R.id.bookTitle) var publisherTV: TextView = itemView.findViewById(R.id.publisher) var pageCountTV: TextView = itemView.findViewById(R.id.pageCount) var dateTV: TextView = itemView.findViewById(R.id.date) var bookIV: ImageView = itemView.findViewById(R.id.bookImage) } }
Step 8: Creating a new Activity for displaying our Book Info in detail
Navigate to the app > java > your app's package name > Right-click on it and click on New > Activity > Select Empty Activity and name it as BookDetails. Make sure to select Empty Activity. Go to the activity_book_details.xml and BookDetails.kt/.java file and refer to the following code.
BookDetails.java package org.geeksforgeeks.demo; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import com.bumptech.glide.Glide; public class BookDetails extends AppCompatActivity { // Declaring variables for book details private String title, subtitle, publisher, publishedDate, description, thumbnail, previewLink, infoLink, buyLink; private int pageCount; // UI components private TextView titleTV, subtitleTV, publisherTV, descTV, pageTV, publishDateTV; private Button previewBtn, buyBtn; private ImageView bookIV; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_book_details); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); // Initializing views titleTV = findViewById(R.id.bookTitle); subtitleTV = findViewById(R.id.bookSubTitle); publisherTV = findViewById(R.id.publisher); descTV = findViewById(R.id.bookDescription); pageTV = findViewById(R.id.pageCount); publishDateTV = findViewById(R.id.publishedDate); previewBtn = findViewById(R.id.idBtnPreview); buyBtn = findViewById(R.id.idBtnBuy); bookIV = findViewById(R.id.bookImage); // Getting data passed from the adapter class Intent intent = getIntent(); title = intent.getStringExtra("title"); subtitle = intent.getStringExtra("subtitle"); publisher = intent.getStringExtra("publisher"); publishedDate = intent.getStringExtra("publishedDate"); description = intent.getStringExtra("description"); pageCount = intent.getIntExtra("pageCount", 0); thumbnail = intent.getStringExtra("thumbnail"); previewLink = intent.getStringExtra("previewLink"); infoLink = intent.getStringExtra("infoLink"); buyLink = intent.getStringExtra("buyLink"); // Setting data to UI components titleTV.setText(title); subtitleTV.setText(subtitle); publisherTV.setText(publisher); publishDateTV.setText("Published On : " + publishedDate); descTV.setText(description); pageTV.setText("Pages : " + pageCount); Glide.with(this).load(thumbnail).into(bookIV); // Adding click listener for preview button previewBtn.setOnClickListener(v -> { if (previewLink == null || previewLink.isEmpty()) { Toast.makeText(BookDetails.this, "No preview link present", Toast.LENGTH_SHORT).show(); return; } Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(previewLink)); startActivity(i); }); // Adding click listener for buy button buyBtn.setOnClickListener(v -> { if (buyLink == null || buyLink.isEmpty()) { Toast.makeText(BookDetails.this, "No buy page present for this book", Toast.LENGTH_SHORT).show(); return; } Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(buyLink)); startActivity(i); }); } }
BookDetails.kt package org.geeksforgeeks.demo import android.content.Intent import android.net.Uri import android.os.Bundle import android.widget.Button import android.widget.ImageView import android.widget.TextView import android.widget.Toast import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import com.bumptech.glide.Glide class BookDetails : AppCompatActivity() { //creating variables for strings,text view, image views and button. private var title: String? = null private var subtitle: String? = null private var publisher: String? = null private var publishedDate: String? = null private var description: String? = null private var thumbnail: String? = null private var previewLink: String? = null private var infoLink: String? = null private var buyLink: String? = null private var pageCount: Int = 0 private lateinit var titleTV: TextView private lateinit var subtitleTV: TextView private lateinit var publisherTV: TextView private lateinit var descTV: TextView private lateinit var pageTV: TextView private lateinit var publishDateTV: TextView private lateinit var previewBtn: Button private lateinit var buyBtn: Button private lateinit var bookIV: ImageView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContentView(R.layout.activity_book_details) ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } //initializing our views.. titleTV = findViewById(R.id.bookTitle) subtitleTV = findViewById(R.id.bookSubTitle) publisherTV = findViewById(R.id.publisher) descTV = findViewById(R.id.bookDescription) pageTV = findViewById(R.id.pageCount) publishDateTV = findViewById(R.id.publishedDate) previewBtn = findViewById(R.id.idBtnPreview) buyBtn = findViewById(R.id.idBtnBuy) bookIV = findViewById(R.id.bookImage) //getting the data which we have passed from our adapter class. title = intent.getStringExtra("title") subtitle = intent.getStringExtra("subtitle") publisher = intent.getStringExtra("publisher") publishedDate = intent.getStringExtra("publishedDate") description = intent.getStringExtra("description") pageCount = intent.getIntExtra("pageCount", 0) thumbnail = intent.getStringExtra("thumbnail") previewLink = intent.getStringExtra("previewLink") infoLink = intent.getStringExtra("infoLink") buyLink = intent.getStringExtra("buyLink") //after getting the data we are setting that data to our text views and image view. titleTV.text = title subtitleTV.text = subtitle publisherTV.text = publisher publishDateTV.text = "Published On : $publishedDate" descTV.text = description pageTV.text = "Pages : $pageCount" Glide.with(this).load(thumbnail).into(bookIV) //adding on click listener for our preview button. previewBtn.setOnClickListener { if (previewLink!!.isEmpty()) { //below toast message is displayed when preview link is not present. Toast.makeText(this@BookDetails, "No preview Link present", Toast.LENGTH_SHORT).show() return@setOnClickListener } //if the link is present we are opening that link via an intent. val uri = Uri.parse(previewLink) val i = Intent(Intent.ACTION_VIEW, uri) startActivity(i) } //initializing on click listener for buy button. buyBtn.setOnClickListener { if (buyLink!!.isEmpty()) { //below toast message is displaying when buy link is empty. Toast.makeText(this@BookDetails, "No buy page present for this book", Toast.LENGTH_SHORT).show() return@setOnClickListener } //if the link is present we are opening the link via an intent. val uri = Uri.parse(buyLink) val i = Intent(Intent.ACTION_VIEW, uri) startActivity(i) } } }
activity_book_details.xml <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/main" android:background="@color/white" android:orientation="vertical" tools:context=".BookDetails"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:orientation="horizontal"> <!--Image view for displaying our book image--> <ImageView android:id="@+id/bookImage" android:layout_width="130dp" android:layout_height="160dp" android:src="@drawable/background" android:layout_margin="18dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:orientation="vertical"> <!--Text view for displaying book publisher--> <TextView android:id="@+id/publisher" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="4dp" android:text="Publisher" android:textStyle="italic" android:textColor="@color/black" android:textSize="15sp" /> <!--text view for displaying number of pages of book--> <TextView android:id="@+id/pageCount" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:padding="4dp" android:text="Number of Pages" android:textColor="@color/black" android:textSize="15sp" /> <!--text view for displaying book publish date--> <TextView android:id="@+id/publishedDate" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:padding="4dp" android:text="Publish Date" android:textColor="@color/black" android:textSize="15sp" /> </LinearLayout> </LinearLayout> <!--text view for displaying book title--> <TextView android:id="@+id/bookTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:padding="4dp" android:text="title" android:textStyle="bold" android:textColor="@color/black" android:textSize="24sp" /> <!--text view for displayig book subtitle--> <TextView android:id="@+id/bookSubTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:padding="4dp" android:textStyle="italic" android:text="subtitle" android:textColor="@color/black" android:textSize="12sp" /> <!--text view for displaying book description--> <TextView android:id="@+id/bookDescription" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:padding="4dp" android:text="description" android:textColor="@color/black" android:textSize="12sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:orientation="horizontal" android:weightSum="2"> <!--button for displaying book preview--> <Button android:id="@+id/idBtnPreview" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="4dp" android:layout_weight="1" android:text="Preview" android:textAllCaps="false" /> <!--button for opening buying page of the book--> <Button android:id="@+id/idBtnBuy" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="4dp" android:layout_weight="1" android:text="Buy" android:textAllCaps="false" /> </LinearLayout> </LinearLayout> </ScrollView>
Step 9: Working with the MainActivity file
Go to the MainActivity.java/.kt file and refer to the following code. Below is the code for the MainActivity file. Comments are added inside the code to understand the code in more detail.
MainActivity.java package org.geeksforgeeks.demo; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.toolbox.JsonObjectRequest; import com.android.volley.toolbox.Volley; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; // MainActivity handles the UI and API request // to fetch books from Google Books API public class MainActivity extends AppCompatActivity { // Variables for networking and UI components private RequestQueue mRequestQueue; private ArrayList<BookInfo> bookInfoArrayList; private ProgressBar progressBar; private EditText searchEdt; private ImageButton searchBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); // Initializing UI components progressBar = findViewById(R.id.progressBar); searchEdt = findViewById(R.id.searchEditText); searchBtn = findViewById(R.id.searchButton); // Setting click listener on the search button searchBtn.setOnClickListener(v -> { // Show progress bar while searching progressBar.setVisibility(View.VISIBLE); String query = searchEdt.getText().toString(); if (query.isEmpty()) { // Error if input is empty searchEdt.setError("Please enter search query"); return; } // Fetch books based on the search query getBooksInfo(query); }); } // Function to fetch book data from Google Books API private void getBooksInfo(String query) { // Initialize the book list bookInfoArrayList = new ArrayList<>(); mRequestQueue = Volley.newRequestQueue(this); // Clear cache before making a new request mRequestQueue.getCache().clear(); // Construct API URL using the search query String url = "https://www.googleapis.com/books/v1/volumes?q=" + query; RequestQueue queue = Volley.newRequestQueue(this); // Make API request to get book data JsonObjectRequest booksObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, response -> { // Hide progress bar after fetching data progressBar.setVisibility(View.GONE); try { // Get book items array JSONArray itemsArray = response.getJSONArray("items"); for (int i = 0; i < itemsArray.length(); i++) { JSONObject itemsObj = itemsArray.getJSONObject(i); JSONObject volumeObj = itemsObj.getJSONObject("volumeInfo"); // Extract book details with default values String title = volumeObj.optString("title", "N/A"); String subtitle = volumeObj.optString("subtitle", "N/A"); JSONArray authorsArray = volumeObj.optJSONArray("authors"); String publisher = volumeObj.optString("publisher", "N/A"); String publishedDate = volumeObj.optString("publishedDate", "N/A"); String description = volumeObj.optString("description", "N/A"); int pageCount = volumeObj.optInt("pageCount", 0); // Get book thumbnail if available JSONObject imageLinks = volumeObj.optJSONObject("imageLinks"); String thumbnail = (imageLinks != null) ? imageLinks.optString("thumbnail", "") : ""; // Get book preview and info links String previewLink = volumeObj.optString("previewLink", ""); String infoLink = volumeObj.optString("infoLink", ""); // Get buy link from sale info (if available) JSONObject saleInfoObj = itemsObj.optJSONObject("saleInfo"); String buyLink = (saleInfoObj != null) ? saleInfoObj.optString("buyLink", "") : ""; // Convert authors JSONArray to ArrayList<String> ArrayList<String> authorsArrayList = new ArrayList<>(); if (authorsArray != null) { for (int j = 0; j < authorsArray.length(); j++) { authorsArrayList.add(authorsArray.optString(j, "Unknown")); } } // Create BookInfo object with fetched details BookInfo bookInfo = new BookInfo( title, subtitle, authorsArrayList, publisher, publishedDate, description, pageCount, thumbnail, previewLink, infoLink, buyLink ); // Add book details to the list bookInfoArrayList.add(bookInfo); } // Set up RecyclerView with BookAdapter to display the book list RecyclerView recyclerView = findViewById(R.id.rv); recyclerView.setLayoutManager(new LinearLayoutManager(this)); BookAdapter adapter = new BookAdapter(bookInfoArrayList, this); recyclerView.setAdapter(adapter); } catch (JSONException e) { e.printStackTrace(); Toast.makeText(this, "No Data Found: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } }, error -> { // Handle API request error Toast.makeText(this, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show(); }); // Add request to the Volley queue queue.add(booksObjRequest); } }
MainActivity.kt package org.geeksforgeeks.demo import android.os.Bundle import android.view.View import android.widget.EditText import android.widget.ImageButton import android.widget.ProgressBar import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.android.volley.Request import com.android.volley.RequestQueue import com.android.volley.VolleyError import com.android.volley.toolbox.JsonObjectRequest import com.android.volley.toolbox.Volley import org.json.JSONArray import org.json.JSONException // MainActivity handles the UI and API request // to fetch books from Google Books API class MainActivity : AppCompatActivity() { // Variables for networking and UI components private lateinit var mRequestQueue: RequestQueue private lateinit var bookInfoArrayList: ArrayList<BookInfo> private lateinit var progressBar: ProgressBar private lateinit var searchEdt: EditText private lateinit var searchBtn: ImageButton override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Initializing UI components progressBar = findViewById(R.id.progressBar) searchEdt = findViewById(R.id.searchEditText) searchBtn = findViewById(R.id.searchButton) // Setting click listener on the search button searchBtn.setOnClickListener { // Show progress bar while searching progressBar.visibility = View.VISIBLE val query = searchEdt.text.toString() if (query.isEmpty()) { // Error if input is empty searchEdt.error = "Please enter search query" return@setOnClickListener } // Fetch books based on the search query getBooksInfo(query) } } // Function to fetch book data from Google Books API private fun getBooksInfo(query: String) { bookInfoArrayList = ArrayList() // Initialize the book list mRequestQueue = Volley.newRequestQueue(this) // Clear cache before making a new request mRequestQueue.cache.clear() // Construct API URL using the search query val url = "https://www.googleapis.com/books/v1/volumes?q=$query" val queue = Volley.newRequestQueue(this) // Make API request to get book data val booksObjRequest = JsonObjectRequest(Request.Method.GET, url, null, { response -> // Hide progress bar after fetching data progressBar.visibility = View.GONE try { // Get book items array val itemsArray = response.getJSONArray("items") for (i in 0 until itemsArray.length()) { val itemsObj = itemsArray.getJSONObject(i) val volumeObj = itemsObj.getJSONObject("volumeInfo") // Extract book details with default values val title = volumeObj.optString("title", "N/A") val subtitle = volumeObj.optString("subtitle", "N/A") val authorsArray = volumeObj.optJSONArray("authors") ?: JSONArray() val publisher = volumeObj.optString("publisher", "N/A") val publishedDate = volumeObj.optString("publishedDate", "N/A") val description = volumeObj.optString("description", "N/A") val pageCount = volumeObj.optInt("pageCount", 0) // Get book thumbnail if available val imageLinks = volumeObj.optJSONObject("imageLinks") val thumbnail = imageLinks?.optString("thumbnail", "") ?: "" // Get book preview and info links val previewLink = volumeObj.optString("previewLink", "") val infoLink = volumeObj.optString("infoLink", "") // Get buy link from sale info (if available) val saleInfoObj = itemsObj.optJSONObject("saleInfo") val buyLink = saleInfoObj?.optString("buyLink", "") ?: "" // Convert authors JSONArray to ArrayList<String> val authorsArrayList = ArrayList<String>() for (j in 0 until authorsArray.length()) { authorsArrayList.add(authorsArray.optString(j, "Unknown")) } // Create BookInfo object with fetched details val bookInfo = BookInfo( title, subtitle, authorsArrayList, publisher, publishedDate, description, pageCount, thumbnail, previewLink, infoLink, buyLink ) // Add book details to the list bookInfoArrayList.add(bookInfo) } // Set up RecyclerView with BookAdapter to display the book list val adapter = BookAdapter(bookInfoArrayList, this) val recyclerView = findViewById<RecyclerView>(R.id.rv) recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.adapter = adapter } catch (e: JSONException) { e.printStackTrace() Toast.makeText(this, "No Data Found: ${e.message}", Toast.LENGTH_SHORT).show() } }, { error: VolleyError -> // Handle API request error Toast.makeText(this, "Error: ${error.message}", Toast.LENGTH_SHORT).show() }) // Add request to the Volley queue queue.add(booksObjRequest) } }
Check out the project on the below link: Book-Library-App-using-Google-Books-API
Output:
Similar Reads
Android - Build a Book Library App using Kotlin There are so many apps that are present in the play store which provides details related to different books inside it. Book Library is considered one of the basic applications which a beginner can develop to learn some basic concepts within android such as JSON parsing, using recycler view, and othe
11 min read
How to Build a ChatGPT Like App in Android using OpenAI API? Chat GPT is nowadays one of the famous AI tools which are like a chatbot. This chatbot answers all the queries which are sent to it. In this article, we will be building a simple ChatGPT-like android application by integrating the OpenAI API(ChatGPT) where we can ask any question and get an appropri
5 min read
How to Make a Joke App in Android Using API Call? Jokes are the best way to keep the face smiling. With the power of technology, we can create apps that provide instant access to a broad Category(i.e. animal, money, career, dev etc ) of jokes at any time. In this article, we will create a Joke App in Android that uses API calls to fetch jokes from
7 min read
How to Build a QR Code Android App using Firebase? QR (Quick Response) code is a type of two-dimensional barcode that contains information encoded in a pattern of black and white squares. It was first developed in 1994 by a company named Denso Wave. Qr codes can be scanned by a smartphone or a dedicated QR code scanner, which uses the device's camer
6 min read
How to Generate API Key for Using Google Maps in Android? For using any Google services in Android, we have to generate an API key or we have to generate some unique key for using that service provided by Google. So Maps is one of the famous and most used services provided by Google. Maps can be seen in each and every app provided by Google and we also can
3 min read