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 an external data source. The Jokes Api is Free of cost providing various types of jokes (animal, money, music, dev, etc ).
Api Link: https://api.chucknorris.io/jokes/random?category={category}
Replace {category} by your preferred category.
This article will also help to get knowledge about how to make an API call in Android using the Retrofit library by making a simple Joke app. In this app, a user can select the category of a joke and get that category joke. 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 Radio Buttons to select the Category of the joke and a button by clicking our app fetch the joke from the API and display the jokes using a TextView.
activity_main.xml:
<? xml version = "1.0" encoding = "utf-8" ?>
<!--Linear Layout--> < LinearLayout android:layout_width = "match_parent"
android:orientation = "vertical"
android:gravity = "center"
android:layout_height = "match_parent"
tools:context = ".MainActivity" >
<!--ScrollView Horizontally-->
< HorizontalScrollView
android:id = "@+id/horizontal_scroll_view"
android:layout_width = "match_parent"
android:layout_height = "wrap_content" >
<!--LinearLayout-->
< LinearLayout
android:padding = "15dp"
android:layout_width = "match_parent"
android:orientation = "horizontal"
android:gravity = "center"
android:layout_height = "wrap_content" >
< TextView
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Category :"
android:textSize = "19dp"
android:textStyle = "bold"
android:textColor = "@color/black" />
<!--Radio Group-->
< RadioGroup
android:padding = "10dp"
android:id = "@+id/radiogroup_category"
android:orientation = "horizontal"
android:layout_width = "match_parent"
android:layout_height = "wrap_content" >
< RadioButton
android:id = "@+id/radio_animal"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "animal" />
< RadioButton
android:id = "@+id/radio_career"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "career" />
< RadioButton
android:id = "@+id/radio_celebrity"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "celebrity" />
< RadioButton
android:id = "@+id/radio_dev"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "dev" />
< RadioButton
android:id = "@+id/radio_music"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "music" />
< RadioButton
android:id = "@+id/radio_money"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "money" />
</ RadioGroup >
</ LinearLayout >
</ HorizontalScrollView >
<!--Button-->
< Button
android:layout_marginTop = "15dp"
android:id = "@+id/btn_getjokes"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Get Jokes" />
<!--progress bar for loading -->
< ProgressBar
android:id = "@+id/idLoadingPB"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_gravity = "center"
android:visibility = "gone" />
<!--TextView-->
< TextView
android:padding = "10dp"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Joke : "
android:textSize = "18dp"
android:textColor = "@color/black"
android:textStyle = "bold" />
<!--TextView for displaying jokes-->
< TextView
android:padding = "20dp"
android:id = "@+id/tv_jokess"
android:text = " "
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:textColor = "@color/black"
android:textStyle = "bold"
android:textSize = "18dp" />
</ 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 ChuckNorrisJoke and add the below code to it. Comments are added inside the code to understand the code in more detail.
ChuckNorrisJoke.kt:
package com.example.gfg
// Define a data class as ChuckNorrisJoke data class ChuckNorrisJoke(
// Property that consist the categories
var categories: ArrayList<String>,
// Property that consist the date and time
var created_at: String,
// Property that contains the URL of the icon
var icon_url: String,
// Property that contains the ID
var id: String,
// Property that contains the date and
// time when the joke is updated
var updated_at: String,
// Property that contains the URL
// of the joke as a string
var url: String,
// Property that contains the
// actual joke as a string
var value: 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 ChuckNorrisApi and add the below code to it. Comments are added inside the code to understand the code in more detail.
package com.example.gfg
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
// interface for APICALL interface ChuckNorrisApi {
// Get request
@GET ( "jokes/random" )
// function that pass category as parameter
// and return an ChuckNorrisJoke Object
fun getRandomJoke( @Query ( "category" ) category:String): Call<ChuckNorrisJoke>
} |
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 getRandomJoke() method that is responsible for making API Calls.
ApiCall.kt:
package com.example.gfg
import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class ApiCall {
// Define a function called "getRandomJoke" that takes a
// category string and a callback function as input
fun getRandomJoke(category:String, callback: (ChuckNorrisJoke?) -> Unit) {
// Create a Retrofit instance with base URL, an
// OkHttpClient instance, and a Gson converter factory
val retrofit = Retrofit.Builder()
.client(OkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.build()
// Create an instance of the ChuckNorrisApi interface
// using the Retrofit instance
val api = retrofit.create(ChuckNorrisApi:: class .java)
// Make an asynchronous API call to get a random Chuck Norris
// joke with the given category using the "getRandomJoke"
// function of the ChuckNorrisApi interface
api.getRandomJoke(category).enqueue(object : Callback<ChuckNorrisJoke> {
// it define the code that execute if response is received
override fun onResponse(call: Call<ChuckNorrisJoke>, response: Response<ChuckNorrisJoke>) {
if (response.isSuccessful) {
val joke : ChuckNorrisJoke? = response.body()
callback(joke)
}
// If the response is not successful,
// pass null to the callback function
else {
callback( null )
}
}
// when the API call fails
override fun onFailure(call: Call<ChuckNorrisJoke>, t: Throwable) {
// Pass null to the callback function
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 getRandomJoke() method.
MainActivity.kt:
package com.example.gfg
import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.ProgressBar
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.TextView
import android.widget.Toast
import org.w3c.dom.Text
class MainActivity : AppCompatActivity() {
// assign mSelectedCategory variable with default value "animal"
private var mSelectedCategory: String = "animal"
@SuppressLint ( "MissingInflatedId" )
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btn_jokes: Button = findViewById(R.id.btn_getjokes)
val tv_jokes: TextView = findViewById(R.id.tv_jokess)
val mprogressBar: ProgressBar = findViewById(R.id.idLoadingPB)
// assign lastCheckedId variable with default value 0
var lastCheckedId = 0
// Set the click listener for the Get Jokes button
btn_jokes.setOnClickListener {
val radioGroup = findViewById<RadioGroup>(R.id.radiogroup_category)
// Show the progress bar
mprogressBar.visibility = View.VISIBLE
// Set the onCheckedChanged listener for the radio group
radioGroup.setOnCheckedChangeListener { group, checkedId ->
// If the checked radio button is
// different from the last one
if (checkedId != lastCheckedId) {
// Update the lastCheckedId variable
lastCheckedId = checkedId
val radioButton = findViewById<RadioButton>(checkedId)
// Update the mSelectedCategory variable with
// the selected radio button's text
mSelectedCategory = radioButton.text.toString()
}
}
// Call the API to get a random joke
// based on the selected category
ApiCall().getRandomJoke(mSelectedCategory!!) { joke ->
// Set the text of the TextView to the joke value
tv_jokes.text = joke?.value
// Hide the progress bar
mprogressBar.visibility = View.GONE
}
}
}
} |
Output: