Share
Explore

Student Lab Learning Workbook: Creating a Kotlin Android Application to Fetch Data from National Park Service API


Table of Contents

Introduction
Setting Up Your Development Environment
Creating a New Kotlin Android Project
Adding Required Dependencies
Implementing Networking and Data Fetching
Displaying Data in the Application
Conclusion

1. Introduction

In this lab, you will learn how to create a Kotlin Android application that fetches data from the National Park Service API (). The application will display a list of national parks and provide basic information about each park.

2. Setting Up Your Development Environment

Download and install Android Studio ().
Ensure you have the latest version of the Android SDK and Kotlin plugin installed.

3. Creating a New Kotlin Android Project

Open Android Studio and click "Start a new Android Studio project."
Select "Empty Activity" and click "Next."
Name your project "NationalParkApp" and set the package name to "com.example.nationalparkapp."
Select "Kotlin" as the programming language and set the minimum API level to 21.
Click "Finish" to create the project.

4. Adding Required Dependencies

done: In the build.gradle file for your app module, add the following dependencies:
kotlin

dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.google.android.material:material:1.4.0'
}
Sync your project.

5. Implementing Networking and Data Fetching

Create a package named "network" and add an interface named "NationalParkServiceApi."
Define a function named "getParks" with the necessary annotations for Retrofit.
Create a "NetworkModule" object to provide a Retrofit instance.
Create a package named "repository" and add a class named "ParkRepository."
Implement a function named "fetchParks" in "ParkRepository" to fetch park data.

Step 1: Create a package named "network" and add an interface named "NationalParkServiceApi."

// network/NationalParkServiceApi.kt

import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Query

interface NationalParkServiceApi {

@GET("parks")
suspend fun getParks(
@Query("api_key") apiKey: String
): Response<List<Park>>

}
Step 2: Define a function named "getParks" with the necessary annotations for Retrofit.
The function "getParks" is already defined in the "NationalParkServiceApi" interface above.
Step 3: Create a "NetworkModule" object to provide a Retrofit instance.
// network/NetworkModule.kt

import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object NetworkModule {

private const val BASE_URL = "https://developer.nps.gov/api/v1/"

private val okHttpClient = OkHttpClient.Builder().build()

private val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()

val nationalParkServiceApi: NationalParkServiceApi = retrofit.create(NationalParkServiceApi::class.java)

}
Step 4: Create a package named "repository" and add a class named "ParkRepository."
// repository/ParkRepository.kt

import network.NationalParkServiceApi

class ParkRepository(private val api: NationalParkServiceApi) {

suspend fun fetchParks(apiKey: String) = api.getParks(apiKey)

}
Step 5: Implement a function named "fetchParks" in "ParkRepository" to fetch park data.
The function "fetchParks" is already implemented in the "ParkRepository" class above.
You can now use the "ParkRepository" class to fetch park data using the National Park Service API. Make sure to handle the API key securely and manage the API call results (success, error, etc.) in your ViewModel or other appropriate layers in your app.

done: Step 1: Create a package named "network" and add an interface named "NationalParkServiceApi."

// network/NationalParkServiceApi.kt

import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Query

interface NationalParkServiceApi {

@GET("parks")
suspend fun getParks(
@Query("api_key") apiKey: String
): Response<List<Park>>

}
Step 2: Define a function named "getParks" with the necessary annotations for Retrofit.
The function "getParks" is already defined in the "NationalParkServiceApi" interface above.
To create a NetworkModule object in Android Kotlin that provides a Retrofit instance, follow these steps:
Add the necessary dependencies to your app's build.gradle file:
dependencies {
// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

// OkHttp
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
}
Create a new Kotlin file named NetworkModule.kt in your network package.
Import the necessary classes and interfaces:

import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
Create the NetworkModule object with a function to provide a Retrofit instance:
object NetworkModule {

private const val BASE_URL = "https://your-api-base-url.com/"

fun provideRetrofit(): Retrofit {
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}

val okHttpClient = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build()

return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()
}

}
How do I make an object is it like making a file

In Kotlin, you usually create objects by creating a new Kotlin file (.kt) and defining the object within that file. You can follow these steps to create the NetworkModule object:
In your Android Studio project, right-click on the package where you want to create the NetworkModule object, and select New -> Kotlin File/Class.
Name the file "NetworkModule" and click "OK".
Inside the newly created "NetworkModule.kt" file, you'll define the NetworkModule object like this:

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object NetworkModule {
private const val BASE_URL = "https://your-base-url.com/"

private val retrofit: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}

fun provideNationalParkServiceApi(): NationalParkServiceApi {
return retrofit.create(NationalParkServiceApi::class.java)
}
}
Replace "" with the base URL of your API.
Now, with the NetworkModule object created, you can easily create an instance of the NationalParkServiceApi interface by calling the provideNationalParkServiceApi() function:
val nationalParkServiceApi = NetworkModule.provideNationalParkServiceApi()
You can place the above line of code in your ViewModel or Repository, depending on your architecture, to create and use the NationalParkServiceApi instance.

Replace https://your-api-base-url.com/ with your actual API base URL.
Now, you can use the NetworkModule object to provide a Retrofit instance and create an instance of your NationalParkServiceApi interface:
val nationalParkServiceApi: NationalParkServiceApi = NetworkModule.provideRetrofit().create(NationalParkServiceApi::class.java)
This will allow you to make API calls using the nationalParkServiceApi instance.
Step 3: Create a "NetworkModule" object to provide a Retrofit instance.
// network/NetworkModule.kt

import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object NetworkModule {

private const val BASE_URL = "https://developer.nps.gov/api/v1/"

private val okHttpClient = OkHttpClient.Builder().build()

private val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()

val nationalParkServiceApi: NationalParkServiceApi = retrofit.create(NationalParkServiceApi::class.java)

}
Step 4: Create a package named "repository" and add a class named "ParkRepository."
// repository/ParkRepository.kt

import network.NationalParkServiceApi

class ParkRepository(private val api: NationalParkServiceApi) {

suspend fun fetchParks(apiKey: String) = api.getParks(apiKey)

}
Step 5: Implement a function named "fetchParks" in "ParkRepository" to fetch park data.
The function "fetchParks" is already implemented in the "ParkRepository" class above.
You can now use the "ParkRepository" class to fetch park data using the National Park Service API. Make sure to handle the API key securely and manage the API call results (success, error, etc.) in your ViewModel or other appropriate layers in your app.

“how do I Create a package named "network" - what does that mean?”


In the context of a Kotlin Android application, creating a package named "network" means organizing related classes and interfaces related to networking tasks in a separate folder. A package is a way to group related code files and maintain a clean project structure.
To create a package named "network", follow these steps:
Open your Kotlin Android project in Android Studio.
Locate the java folder in your project structure (usually under app/src/main/java).
Right-click on the java folder, then choose New > Package.
In the dialog box that appears, enter the package name network, and click on OK.
Now you have a new package named "network" in your project. You can add the "NationalParkServiceApi" interface, "NetworkModule" object, and any other networking-related classes to this package. This will help you keep your project structure organized and easier to navigate.

Extend the above to include detailed code and procedures to add the "NationalParkServiceApi" interface, "NetworkModule" object, and any other networking-related classes to this package

To add the "NationalParkServiceApi" interface, "NetworkModule" object, and other networking-related classes to the "network" package in a Kotlin Android application, follow these steps:
Create a new package named "network":
Right-click on your app module, usually called "app" or "src", and select New > Package. Name the package "network" and click OK.
Add the necessary dependencies to your app's build.gradle file:

dependencies {
...
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation "com.squareup.okhttp3:logging-interceptor:4.9.1"
}
Sync the project with the added dependencies.
Create the "NationalParkServiceApi" interface:
Right-click on the "network" package and select New > Kotlin Class/File. Choose Interface, name it "NationalParkServiceApi", and click OK. Add the necessary API endpoints with Retrofit annotations:


package com.example.myapplication.network

import retrofit2.http.GET
import retrofit2.http.Query

interface NationalParkServiceApi {
@GET("parks")
suspend fun getParks(@Query("api_key") apiKey: String): ParksResponse
}
Create a data class to represent the API response:
Right-click on the "network" package and select New > Kotlin Class/File. Choose Class, name it "ParksResponse", and click OK. Define the data class with the appropriate fields:


package com.example.myapplication.network

data class ParksResponse(
val data: List<Park>
)

data class Park(
val id: String,
val fullName: String,
val description: String,
val url: String
)
Create the "NetworkModule" object:
Right-click on the "network" package and select New > Kotlin Class/File. Choose Object, name it "NetworkModule", and click OK. Add the necessary functions and constants to create and provide instances of the required networking classes:

package com.example.myapplication.network

import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

private const val BASE_URL = "https://api.nps.gov/"

object NetworkModule {

private fun provideOkHttpClient(): OkHttpClient {
val logging = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}

return OkHttpClient.Builder()
.addInterceptor(logging)
.build()
}

private fun provideRetrofit(client: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
}

fun provideNationalParkServiceApi(retrofit: Retrofit): NationalParkServiceApi {
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.