Network Requests with Retrofit in Android

Jun 5 2024 · Kotlin 1.9.22, Android 14, Android Studio Hedgehog | 2023.1.1

Lesson 01: Understand Network

Demo 1

Episode complete

Play next episode

Next
Transcript

Introduction

In this demo, you’ll learn more about the structure of the project. You’ll also learn how to check your network connectivity in the app.

Open the Starter project for Lesson 1 from the student materials repository. Once it syncs, change your project pane view to Project. It might be set to Android by default. The project view shows a more accurate representation of the structure you’re about to explore.

Project Structure

The project structure is pretty simple. The model package contains User and MovieReview models that will be shown in the app. You’ll have all your network-related code in the networking package. For now, that package holds only MovieDiaryApi, which has some method signatures already prepared for you.

The ui package contains all the UI-related code, further subpackaged by features in the app.

Finally, there are two more classes: App and MainActivity. App creates and provides access to SharedPreferences, and MainActivity is the entry point and a container for the whole app.

Adding Permissions to AndroidManifest.xml

Now that you’re familiar with the project structure, it’s time to start adding some code. The first thing you must do is to add networking dependencies. To do that, open AndroidManifest.xml and add the following code above the <application ..> tag:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  

The first permission lets your app access the internet in general. The second one lets you check the network state.

The next thing you need is a way to check the network status. For that, you’ll create a class called ConnectivityChecker in the networking package. Add the following code to the class:

class ConnectivityChecker(
  private val connectivityManager: ConnectivityManager?
)

You need an instance of ConnectivityManager to get information about the network.

Now, create a function that will read the network’s capabilities. Add this code to the class:

class ConnectivityChecker(private val connectivityManager: ConnectivityManager?) {

  fun hasNetworkConnection(): Boolean {
    val network = connectivityManager?.activeNetwork ?: return false
    val capabilities =
      connectivityManager.getNetworkCapabilities(network) ?: return false
    return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
        || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
        || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
        || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
  }
}

First, you get the active network from the connectivityManager and read its capabilities. Then, you check if it’s connected to Wi-Fi, ethernet, cellular data, or a VPN. If any of those connections exist, you return true, meaning that a user can make a network request.

Using ConnectivityChecker

It’s time to try it out! Open LoginScreen.kt and add the connectivity checker as a parameter to the LoginScreen composable.

@Composable
fun LoginScreen(
  movieDiaryApi: MovieDiaryApi,
  connectivityChecker: ConnectivityChecker,
  onLogin: (String) -> Unit,
  onRegisterTapped: () -> Unit,
)

Scroll down to the Button composable and replace TODO: Add network check with this code:

if (connectivityChecker.hasNetworkConnection()) {

Also replace TODO: Handle no network state with the following:

else {
  scaffoldState.snackbarHostState.showSnackbar("Check your network connection.")
}
}

This checks for a network connection every time a user presses the Login button. If the app’s not connected, a snackbar shows with an error. Otherwise, the program continues normally.

To finish the implementation, open MainActivity.kt and create an instance of ConnectivityChecker by adding the following property:

private val connectivityChecker by lazy { ConnectivityChecker(connectivityManager) }

Scroll down and pass the instance to the LoginScreen composable:

LoginScreen(
  movieDiaryApi = movieApi,
  connectivityChecker = connectivityChecker,
  onLogin = { token ->
    App.saveUserToken(token)
    userLoggedIn = true
    currentScreen = Screens.MOVIES
  },
  onRegisterTapped = { currentScreen = Screens.REGISTER }
)

Implement the same connectivity check on the registration screen in RegisterScreen.kt, like this:

@Composable
fun RegisterScreen(
  movieDiaryApi: MovieDiaryApi,
  connectivityChecker: ConnectivityChecker,
  onUserRegistered: () -> Unit = {},
  onLoginTapped: () -> Unit,
)

Scroll down to the button and replace it with the following code:

Button(onClick = {
  focusManager.clearFocus()
  screenScope.launch {
    if (username.isNotBlank() && email.isNotBlank() && password.isNotBlank()) {
      if (connectivityChecker.hasNetworkConnection()) {
        movieDiaryApi.registerUser(
          username,
          email,
          password
        ) { message, error ->
          screenScope.launch {
            if (error != null) {
              scaffoldState.snackbarHostState.showSnackbar(error.message ?: "")
            } else {
              onUserRegistered()
            }
          }
        }
      } else {
        scaffoldState.snackbarHostState.showSnackbar("Check your network connection.")
      }
    } else {
      scaffoldState.snackbarHostState.showSnackbar("Please fill in all the fields.")
    }
  }
}) {
  Text(text = "Register")
}

And in MainActivity.kt, add the connectivityChecker to RegisterScreen:

RegisterScreen(
  movieDiaryApi = movieApi,
  connectivityChecker = connectivityChecker,
  onUserRegistered = { currentScreen = Screens.LOGIN },
  onLoginTapped = { currentScreen = Screens.LOGIN })

Run the app and turn on airplane mode. Add some input and click Login. You see an error message to check your connection.

Click the Register button and notice that the same happens if you try to register.

Soon, you’ll add code to register a user.

See forum comments
Cinema mode Download course materials from Github
Previous: Instruction Next: Connecting to the internet