In this article, we will see the process of building a Motivational Quotes App for Android that fetches random quotes from an API and displays them to the user. By the end of this article, we will have a Complete Android application that connects to an API, retrieves motivational quotes and author names, and allows users to navigate through them with a simple UI. Here we are going to use Retrofit Library for API Calling.
About the API:
Api Link : https://type.fit/api/quotes
Base url : https://type.fit/api/
Request Type:- GET
A sample video is given below to get an idea about what we are going to do in this article.
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 and select the language as Kotlin.
Step 2: Add the below dependency in your build.gradle file
Navigate to the Gradle Scripts > build.gradle(Module:app) and add the below dependency in the dependencies section.
// Add the below dependencies to your project
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
After adding you need to Sync your project.
Step 3: Adding permissions to the internet in the AndroidManifest.xml file
Navigate to the app > AndroidManifest.xml and add the below code to it.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Step 4: Change the StatusBar Color
Navigate to app > res > values > themes > themes.xml and add the below code under the style section in the themes.xml file.
<item name="android:statusBarColor" tools:targetApi="l">#308d46</item>
Step 5: Working with the activity_main.xml file
Navigate to the app > res > layout > activity_main.xml and add the below code to that file. Below is the code for the activity_main.xml file. This XML file represents our app UI. Our UI contains some Linear Layout, CardView, TextView, and ImageView.
activity_main.xml:
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:orientation = "vertical"
android:gravity = "center"
tools:context = ".MainActivity" >
<!-- CardView -->
< androidx.cardview.widget.CardView
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
app:cardCornerRadius = "20dp"
app:cardElevation = "100dp"
android:layout_margin = "16dp" >
<!-- Inner LinearLayout -->
< LinearLayout
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:orientation = "vertical"
android:padding = "16dp" >
<!-- TextView for quotes title -->
< TextView
android:id = "@+id/tv_quotes"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:text = "Title"
android:textSize = "20sp"
android:textStyle = "bold" />
<!-- TextView for quotes author name -->
< TextView
android:id = "@+id/tv_author"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:text = "Subtitle"
android:textSize = "16sp" />
</ LinearLayout >
</ androidx.cardview.widget.CardView >
<!-- LinearLayout -->
< LinearLayout
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:orientation = "horizontal"
android:gravity = "center" >
<!-- ImageView for previous button -->
< ImageView
android:id = "@+id/btn_previous"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_marginEnd = "80dp"
android:background = "@drawable/ic_back" />
<!-- ImageView for next button -->
< ImageView
android:id = "@+id/btn_next"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:background = "@drawable/ic_next" />
</ LinearLayout >
</ LinearLayout >
|
Step 6: Creating a Model Class for our jokes
Navigate to the app > java > your app’s package name > Right-click on it > New > create a data class named as QuotesModel and add the below code to it. Comments are added inside the code to understand the code in more detail.
QuotesModel.kt:
package com.example.gfg
// Data Class for our Quotes // containing Quotes and Author Name data class QuotesModel (
var text:String,
var author:String
) |
Step 7: Creating an Interface class for our API
Navigate to the app > java > your app’s package name > Right-click on it > New > interface and name the file as ApiService and add the below code to it. Comments are added inside the code to understand the code in more detail.
ApiService.kt:
package com.example.gfg
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
interface ApiService {
// Get request
@GET ( "quotes" )
// function that return a List of QuotesModel Object
fun getRandomQuotes(): Call<List<QuotesModel>>
} |
Step 8: Create a class for handling API Calls
Navigate to the app > java > your app’s package name > Right-click on it > New > class and name the file as ApiCall and add the below code to it. Comments are added inside the code to understand the code in more detail. In this call, we are going to make a Get request to our API using the Retrofit library. The class consists of getRandomQuotes() callback function that is responsible for making API Calls.
ApiCall.kt:
import com.example.gfg.ApiService
import com.example.gfg.QuotesModel
import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class ApiCall {
// fetch the Quotes from the API
fun getRandomQuotes(callback: (List<QuotesModel>?) -> Unit) {
// Create Retrofit instance
val retrofit = Retrofit.Builder()
.client(OkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.build()
// Create ApiService interface
val api = retrofit.create(ApiService:: class .java)
// Make an API call to get random quotes
api.getRandomQuotes().enqueue(object : Callback<List<QuotesModel>> {
// Callback method on successful API response
override fun onResponse(
call: Call<List<QuotesModel>>,
response: Response<List<QuotesModel>>
) {
if (response.isSuccessful) {
val quoteslist: List<QuotesModel>? = response.body()
callback(quoteslist)
} else {
callback( null )
}
}
// Callback method on API call failure
override fun onFailure(call: Call<List<QuotesModel>>, t: Throwable) {
callback( null )
}
})
}
} |
Step 9: Working with the MainActivity.kt file
Go to the MainActivity.kt and follow the below code. Below is the code for the MainActivity.kt. Comments are added inside the code to understand the code in more detail. In this mainly we are going to call the ApiCall class getRandomQuotes() method.
MainActivity.kt:
package com.example.gfg
import ApiCall
import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
class MainActivity : AppCompatActivity() {
// An pointer to the list for
// displaying previous and next quotes
var position:Int= 0 public lateinit var quoteslist:List<QuotesModel>
@SuppressLint ( "MissingInflatedId" )
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initialize views
var tv_quotes:TextView=findViewById(R.id.tv_quotes)
var tv_author:TextView=findViewById(R.id.tv_author)
var btn_next:ImageView=findViewById(R.id.btn_next)
var btn_previous:ImageView=findViewById(R.id.btn_previous)
// Make API call to get random quotes
ApiCall().getRandomQuotes(){listquote->
if (listquote != null ) {
quoteslist=listquote
tv_quotes.text=quoteslist.get( 0 ).text
tv_author.text= "~ " +quoteslist.get( 0 ).author
} else {
Toast.makeText( this , "Something Went Wrong" ,Toast.LENGTH_SHORT).show()
}
}
// Button click listeners
btn_next.setOnClickListener {
nextQuote(tv_quotes,tv_author)
}
btn_previous.setOnClickListener {
previousQuote(tv_quotes,tv_author)
}
}
// Display the next quote
fun nextQuote(tv_quotes:TextView,tv_author:TextView){
if (position<quoteslist.size && position>= 0 ){
position++;
tv_quotes.text=quoteslist.get(position).text
tv_author.text= "~ " +quoteslist.get(position).author
} else {
Toast.makeText( this @MainActivity , "You Reached the Last page" ,Toast.LENGTH_SHORT).show()
}
}
// Display the previous quote
fun previousQuote(tv_quotes:TextView,tv_author:TextView){
if (position<quoteslist.size && position> 0 ){
position--;
tv_quotes.text=quoteslist.get(position).text
tv_author.text= "~ " +quoteslist.get(position).author
} else {
Toast.makeText( this @MainActivity , "You are on the 1st Page" ,Toast.LENGTH_SHORT).show()
}
}
} |